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