1 /* 2 * Generation of declaration elements such as parameters and members. 3 * 4 * Copyright (C) 2019 Paul Boddie <paul@boddie.org.uk> 5 * 6 * This program is free software; you can redistribute it and/or 7 * modify it under the terms of the GNU General Public License as 8 * published by the Free Software Foundation; either version 2 of 9 * the License, or (at your option) any later version. 10 * 11 * This program is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with this program; if not, write to the Free Software 18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, 19 * Boston, MA 02110-1301, USA 20 */ 21 22 #include <stdlib.h> 23 #include "common.h" 24 #include "config.h" 25 #include "declaration.h" 26 #include "templates.h" 27 28 29 30 /* Generate each operation signature for use in defining an interface. */ 31 32 void write_interface_signature(struct signature *sig, enum signature_role role, 33 enum component_role component, 34 enum function_role function, FILE *fp, 35 struct interface *iface) 36 { 37 int cpp = (conf.language == CPP_LANGUAGE); 38 int have_init_param = (conf.language == C_LANGUAGE); 39 int declaration = (role & DECLARATION_ROLE); 40 int member = (role & MEMBER_ROLE); 41 int server = (component == SERVER_ROLE); 42 enum specifier direction = get_server_function_direction(function); 43 44 /* Indent and provide a qualifier for C++ class declarations. */ 45 46 char *qualifier = (cpp && declaration) ? " virtual " : member ? " " : ""; 47 48 /* Structure the function name appropriately. */ 49 50 char *opname = get_signature_operation_name(iface, sig, component, role, 51 conf.language); 52 53 /* Prefix any function name appropriately. */ 54 55 char *prefix = (function == COMPLETION_REPLY_ROLE) ? "complete_" : ""; 56 57 /* Introduce an initial parameter for the component state. */ 58 59 if (!cpp && member) 60 fprintf(fp, interface_struct_member_function_signature_prologue, prefix, 61 opname); 62 else 63 fprintf(fp, interface_function_signature_prologue, qualifier, prefix, 64 opname); 65 66 if (have_init_param) 67 write_initial_parameter(iface->name, fp); 68 69 /* Emit the parameters. */ 70 71 write_parameters(sig->parameters, fp, SIGNATURE_ROLE, function, direction, 72 have_init_param); 73 74 fputs(")", fp); 75 76 /* Add a body for the function, this being used to define unimplemented 77 methods or ahead-of-time reply completion functions in C++. The client 78 has method definitions and therefore normal virtual methods. */ 79 80 if (cpp && declaration && server) 81 { 82 if (function == COMPLETION_REPLY_ROLE) 83 write_interface_completion_reply_method(sig, fp, iface); 84 else 85 write_interface_unimplemented_method(sig, direction, fp); 86 } 87 else 88 fputs(get_signature_terminator(role), fp); 89 90 free(opname); 91 } 92 93 /* Write a completion reply member function body for a C++ interface. */ 94 95 void write_interface_completion_reply_method(struct signature *sig, 96 FILE *fp, struct interface *iface) 97 { 98 int have_init_param = (conf.language == C_LANGUAGE); 99 char *opname = get_operation_name(iface, sig); 100 101 fprintf(fp, interface_completion_reply_method_prologue_cpp, opname); 102 103 if (have_init_param) 104 write_initial_parameter(iface->name, fp); 105 106 /* Write the parameters for an invocation of the server function completing an 107 operation by sending a reply. */ 108 109 write_parameters(sig->parameters, fp, INVOCATION_ROLE, COMPLETION_ROLE, 110 OUT_PARAMETER, have_init_param); 111 112 fputs(interface_completion_reply_method_epilogue_cpp, fp); 113 } 114 115 /* Write an unimplemented member function body for a C++ interface. */ 116 117 void write_interface_unimplemented_method(struct signature *sig, 118 enum specifier direction, FILE *fp) 119 { 120 struct parameter *param; 121 122 fputs(interface_unimplemented_method_prologue_cpp, fp); 123 124 for (param = sig->parameters; param != NULL; param = param->tail) 125 { 126 if (param->specifier & direction) 127 fprintf(fp, interface_unused_parameter, get_parameter_name(param->identifiers)); 128 } 129 130 fputs(interface_unimplemented_method_epilogue_cpp, fp); 131 } 132 133 /* Write the initial parameter in an interface signature. */ 134 135 void write_initial_parameter(const char *name, FILE *fp) 136 { 137 if (conf.language == CPP_LANGUAGE) 138 fprintf(fp, "%s *_self", name); 139 else 140 fprintf(fp, "ref_%s _self", name); 141 } 142 143 /* Generate signatures. */ 144 145 void write_signatures(struct signature *sig, enum signature_role role, FILE *fp, 146 struct interface *iface, 147 void (*write_signature)(struct signature *, 148 enum signature_role role, 149 FILE *, struct interface *)) 150 { 151 if (sig == NULL) 152 return; 153 154 write_signature(sig, role, fp, iface); 155 write_signatures(sig->tail, role, fp, iface, write_signature); 156 } 157 158 159 160 /* Generate parameters in each function signature. */ 161 162 void write_parameters(struct parameter *param, FILE *fp, enum parameter_role role, 163 enum function_role function, enum specifier direction, 164 int continuing) 165 { 166 for (; param != NULL; param = param->tail) 167 { 168 if (param->specifier & direction) 169 { 170 if (continuing) 171 fputs(", ", fp); 172 else 173 continuing = 1; 174 175 write_parameter(param, fp, role, function); 176 } 177 } 178 } 179 180 /* Generate a parameter in a signature or invocation. */ 181 182 void write_parameter(struct parameter *param, FILE *fp, 183 enum parameter_role role, enum function_role function) 184 { 185 struct identifier *ident = param->identifiers; 186 char *type; 187 int invocation = (role == INVOCATION_ROLE); 188 int first = 1; 189 190 while (ident != NULL) 191 { 192 /* Put spaces between each type identifier. */ 193 194 if (!invocation) 195 { 196 if (first) 197 first = 0; 198 else 199 fputs(" ", fp); 200 } 201 202 /* Emit type identifiers for signatures. */ 203 204 if (ident->tail != NULL) 205 { 206 if (!invocation) 207 fputs(ident->identifier, fp); 208 } 209 210 /* Emit the parameter name. */ 211 212 else 213 { 214 /* Items must have their type identifiers restored. */ 215 216 if ((param->cls & ITEM_CLASS) && !invocation) 217 { 218 type = param->cls == FPAGE_ITEM ? L4_FPAGE_TYPE : L4_CAP_TYPE; 219 fputs(type, fp); 220 fputs(" ", fp); 221 } 222 223 /* Emit the decoration and parameter name. */ 224 225 fprintf(fp, "%s%s", get_parameter_decoration(param, role, function), 226 ident->identifier); 227 } 228 229 ident = ident->tail; 230 } 231 } 232 233 /* Write structure members for word data structures or variable declarations for 234 parameters. */ 235 236 void write_declarations(struct parameter *param, enum specifier direction, 237 enum parameter_class cls, FILE *fp) 238 { 239 for (; param != NULL; param = param->tail) 240 { 241 if ((param->specifier & direction) && (param->cls & cls)) 242 { 243 fputs(INDENT_MEMBER, fp); 244 write_parameter(param, fp, STRUCTURE_ROLE, GENERAL_FUNCTION_ROLE); 245 fputs(COMPLETE_MEMBER, fp); 246 } 247 } 248 }