1 /* 2 * Server code generation. 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 "declaration.h" 25 #include "message.h" 26 #include "server.h" 27 #include "templates.h" 28 29 30 31 /* Output language, set in the main program. */ 32 33 extern enum language output_language; 34 35 36 37 static void write_signature_end(FILE *fp) 38 { 39 fputs(";\n", fp); 40 } 41 42 /* Generate operation wrapper function details used by the server. */ 43 44 void _write_server_signature(struct signature *sig, FILE *fp, struct interface *iface) 45 { 46 /* NOTE: Qualifier discarded for now. */ 47 48 char *opname = get_operation_name(iface, sig), 49 *type = (output_language == CPP_LANGUAGE) ? iface->name : "void"; 50 51 fprintf(fp, "\nlong wrap_%s(ipc_message_t *msg, %s *_self)", opname, type); 52 53 free(opname); 54 } 55 56 /* Generate each signature for a wrapper function used by the server. */ 57 58 void write_server_signature(struct signature *sig, FILE *fp, struct interface *iface) 59 { 60 _write_server_signature(sig, fp, iface); 61 write_signature_end(fp); 62 } 63 64 /* Generate each operation signature or "function prototype" for server use. */ 65 66 void write_server_interface_signature(struct signature *sig, FILE *fp, struct interface *iface) 67 { 68 char *opname = get_interface_operation_name(iface, sig, output_language); 69 70 /* NOTE: Qualifier discarded for now. */ 71 72 int have_init_param = (output_language == C_LANGUAGE); 73 74 /* Indent and provide a qualifier for C++ class declarations. */ 75 76 char *type = (output_language == CPP_LANGUAGE) ? iface->name : "void", 77 *qualifier = (output_language == CPP_LANGUAGE) ? " virtual " : "", 78 *value_qualifier = (output_language == CPP_LANGUAGE) ? " = 0" : "", 79 *init_param = have_init_param ? "void *_self" : ""; 80 81 /* Introduce an initial parameter for the component state. */ 82 83 fprintf(fp, "\n%slong %s(%s", qualifier, opname, init_param); 84 85 if (have_init_param) 86 write_parameter_separator(sig->parameters, fp); 87 write_parameters(sig->parameters, fp, SIGNATURE_ROLE); 88 89 fprintf(fp, ")%s;\n", value_qualifier); 90 91 free(opname); 92 } 93 94 /* Generate function source code for each operation, with the generated function 95 unpacking a message, calling the actual operation and repacking the 96 results. */ 97 98 void write_server_function(struct signature *sig, FILE *fp, struct interface *iface) 99 { 100 char *type = (output_language == CPP_LANGUAGE) ? iface->name : "void"; 101 102 _write_server_signature(sig, fp, iface); 103 fputs("\n{\n", fp); 104 write_server_function_body(sig->parameters, fp, iface, sig); 105 fputs("}\n", fp); 106 } 107 108 /* Generate a function body corresponding to an operation for server use. */ 109 110 void write_server_function_body(struct parameter *param, FILE *fp, 111 struct interface *iface, struct signature *sig) 112 { 113 int input_words, input_items, output_words, output_items; 114 char *opname = get_operation_name(iface, sig); 115 116 /* Generate the prologue. */ 117 118 fputs(server_function_body_prologue, fp); 119 120 /* Count the number of input words, items and output words. */ 121 122 count_parameters(param, &input_words, &input_items, &output_words, &output_items); 123 124 /* Generate variable declarations. */ 125 126 write_declarations(param, ANY_PARAMETER, ANY_CLASS, fp); 127 128 /* Generate types parameterised with the qualified operation name. */ 129 130 write_accessor_declaration(input_words, output_words, opname, fp); 131 132 /* Unpack each word and item from the message into variables. */ 133 134 if (input_words) 135 { 136 write_accessor_initialisation(IN_PARAMETER, SERVER_ROLE, opname, fp); 137 write_message_access(param, SERVER_ROLE, IN_PARAMETER, WORD_CLASS, fp); 138 } 139 140 if (input_items) 141 { 142 fputs("\n", fp); 143 write_message_access(param, SERVER_ROLE, IN_PARAMETER, ITEM_CLASS, fp); 144 } 145 146 /* Invoke the actual operation using the variables. */ 147 148 write_server_function_call(param, fp, iface, sig); 149 150 /* Pack the outputs into the message and perform any other housekeeping. */ 151 152 if (output_words) 153 { 154 write_accessor_initialisation(OUT_PARAMETER, SERVER_ROLE, opname, fp); 155 write_message_access(param, SERVER_ROLE, OUT_PARAMETER, WORD_CLASS, fp); 156 } 157 158 if (output_items) 159 { 160 fputs("\n", fp); 161 write_message_access(param, SERVER_ROLE, OUT_PARAMETER, ITEM_CLASS, fp); 162 } 163 164 /* Return success. */ 165 166 fprintf(fp, "\n return L4_EOK;\n"); 167 168 /* Free allocated strings. */ 169 170 free(opname); 171 } 172 173 /* Generate an invocation of the actual server operation. */ 174 175 void write_server_function_call(struct parameter *param, FILE *fp, 176 struct interface *iface, struct signature *sig) 177 { 178 char *name, *addr, 179 *opname = get_interface_operation_name(iface, sig, output_language); 180 181 fputs("\n err = ", fp); 182 183 /* Access a method when emitting C++. */ 184 185 if (output_language == CPP_LANGUAGE) 186 fprintf(fp, "_self->%s(", opname); 187 188 /* Employ a function otherwise. */ 189 190 else 191 { 192 fprintf(fp, "%s(_self", opname); 193 write_parameter_separator(param, fp); 194 } 195 196 /* Generate the parameter list, employing addresses for output parameters. */ 197 198 for (; param != NULL; param = param->tail) 199 { 200 addr = param->specifier & OUT_PARAMETER ? "&" : ""; 201 name = get_parameter_name(param->identifiers); 202 fprintf(fp, "%s%s", addr, name); 203 write_parameter_separator(param->tail, fp); 204 } 205 206 fputs(");\n", fp); 207 208 /* Emit post-invocation details. */ 209 210 fputs(server_function_body_call, fp); 211 212 /* Free allocated strings. */ 213 214 free(opname); 215 }