paul@14 | 1 | /* |
paul@100 | 2 | * Code generation from interface descriptions. |
paul@28 | 3 | * |
paul@157 | 4 | * Copyright (C) 2019, 2020 Paul Boddie <paul@boddie.org.uk> |
paul@28 | 5 | * |
paul@28 | 6 | * This program is free software; you can redistribute it and/or |
paul@28 | 7 | * modify it under the terms of the GNU General Public License as |
paul@28 | 8 | * published by the Free Software Foundation; either version 2 of |
paul@28 | 9 | * the License, or (at your option) any later version. |
paul@28 | 10 | * |
paul@28 | 11 | * This program is distributed in the hope that it will be useful, |
paul@28 | 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
paul@28 | 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
paul@28 | 14 | * GNU General Public License for more details. |
paul@28 | 15 | * |
paul@28 | 16 | * You should have received a copy of the GNU General Public License |
paul@28 | 17 | * along with this program; if not, write to the Free Software |
paul@28 | 18 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, |
paul@28 | 19 | * Boston, MA 02110-1301, USA |
paul@14 | 20 | */ |
paul@14 | 21 | |
paul@14 | 22 | #include <stdlib.h> |
paul@100 | 23 | #include "client.h" |
paul@44 | 24 | #include "common.h" |
paul@126 | 25 | #include "config.h" |
paul@100 | 26 | #include "declaration.h" |
paul@99 | 27 | #include "dispatch.h" |
paul@112 | 28 | #include "includes.h" |
paul@113 | 29 | #include "interface.h" |
paul@98 | 30 | #include "message.h" |
paul@48 | 31 | #include "program.h" |
paul@100 | 32 | #include "server.h" |
paul@22 | 33 | #include "summary.h" |
paul@67 | 34 | #include "templates.h" |
paul@14 | 35 | |
paul@39 | 36 | |
paul@72 | 37 | |
paul@56 | 38 | /* Current filename details. */ |
paul@56 | 39 | |
paul@56 | 40 | char *output_basename = NULL, *output_dirname = NULL; |
paul@56 | 41 | |
paul@87 | 42 | /* Client, server and common files. */ |
paul@87 | 43 | |
paul@87 | 44 | FILE *client_fp = NULL, *client_header_fp = NULL, |
paul@87 | 45 | *server_fp = NULL, *server_header_fp = NULL, |
paul@120 | 46 | *interface_fp = NULL; |
paul@87 | 47 | |
paul@91 | 48 | /* Compound interface and dispatcher files. */ |
paul@56 | 49 | |
paul@91 | 50 | FILE *compound_dispatch_fp = NULL, *compound_dispatch_header_fp = NULL, |
paul@168 | 51 | *compound_interface_fp = NULL, *compound_interfaces_fp = NULL, |
paul@168 | 52 | *compound_interface_type_fp = NULL; |
paul@90 | 53 | |
paul@90 | 54 | /* Processed interfaces. */ |
paul@90 | 55 | |
paul@90 | 56 | int processed_interfaces; |
paul@56 | 57 | |
paul@70 | 58 | /* Maximum number of input items expected by an interface. */ |
paul@70 | 59 | |
paul@70 | 60 | int max_input_items = 0; |
paul@70 | 61 | |
paul@14 | 62 | |
paul@14 | 63 | |
paul@56 | 64 | /* Return the first interface name as the output prefix. */ |
paul@56 | 65 | |
paul@56 | 66 | static char *get_output_prefix(struct interface *i) |
paul@56 | 67 | { |
paul@126 | 68 | if (conf.output_prefix != NULL) |
paul@126 | 69 | return conf.output_prefix; |
paul@56 | 70 | |
paul@56 | 71 | if (i == NULL) |
paul@56 | 72 | return NULL; |
paul@56 | 73 | |
paul@56 | 74 | for (; i->tail != NULL; i = i->tail); |
paul@56 | 75 | return i->name; |
paul@56 | 76 | } |
paul@56 | 77 | |
paul@56 | 78 | /* Obtain the basename and directory name of generated output. */ |
paul@56 | 79 | |
paul@56 | 80 | static int set_output_location(struct interface *iface) |
paul@56 | 81 | { |
paul@56 | 82 | /* Obtain a prefix for the output files. */ |
paul@56 | 83 | |
paul@126 | 84 | conf.output_prefix = get_output_prefix(iface); |
paul@56 | 85 | |
paul@126 | 86 | if (conf.output_prefix == NULL) |
paul@56 | 87 | return 0; |
paul@56 | 88 | |
paul@56 | 89 | /* Obtain the basename of the output prefix. */ |
paul@56 | 90 | |
paul@126 | 91 | output_basename = make_basename(conf.output_prefix); |
paul@56 | 92 | |
paul@56 | 93 | if (output_basename == NULL) |
paul@56 | 94 | return 0; |
paul@56 | 95 | |
paul@56 | 96 | /* Obtain the directory name from the output prefix. */ |
paul@56 | 97 | |
paul@126 | 98 | if (conf.output_dir == NULL) |
paul@126 | 99 | output_dirname = make_dirname(conf.output_prefix); |
paul@56 | 100 | else |
paul@126 | 101 | output_dirname = conf.output_dir; |
paul@56 | 102 | |
paul@56 | 103 | if (output_dirname == NULL) |
paul@56 | 104 | { |
paul@56 | 105 | free(output_basename); |
paul@56 | 106 | return 0; |
paul@56 | 107 | } |
paul@56 | 108 | |
paul@56 | 109 | return 1; |
paul@56 | 110 | } |
paul@56 | 111 | |
paul@56 | 112 | |
paul@56 | 113 | |
paul@91 | 114 | /* Generate compound code output, if requested. */ |
paul@56 | 115 | |
paul@157 | 116 | int begin_compound_output(void) |
paul@56 | 117 | { |
paul@126 | 118 | char *compound_dirname = conf.output_dir != NULL ? conf.output_dir : "."; |
paul@90 | 119 | char *s; |
paul@78 | 120 | |
paul@126 | 121 | if (conf.compound == NULL) |
paul@157 | 122 | return 1; |
paul@56 | 123 | |
paul@90 | 124 | processed_interfaces = 0; |
paul@90 | 125 | |
paul@126 | 126 | if (conf.headers) |
paul@56 | 127 | { |
paul@97 | 128 | compound_dispatch_header_fp = get_output_file(server_header_filename, |
paul@126 | 129 | compound_dirname, conf.compound); |
paul@91 | 130 | if (compound_dispatch_header_fp == NULL) |
paul@157 | 131 | return 0; |
paul@56 | 132 | } |
paul@56 | 133 | |
paul@126 | 134 | if (conf.interfaces) |
paul@90 | 135 | { |
paul@119 | 136 | compound_interface_fp = get_output_file(interface_filename, |
paul@126 | 137 | compound_dirname, conf.compound); |
paul@91 | 138 | if (compound_interface_fp == NULL) |
paul@157 | 139 | return 0; |
paul@90 | 140 | |
paul@168 | 141 | compound_interface_type_fp = get_output_file(compound_interface_type_filename, |
paul@168 | 142 | compound_dirname, conf.compound); |
paul@168 | 143 | if (compound_interface_type_fp == NULL) |
paul@168 | 144 | return 0; |
paul@168 | 145 | |
paul@91 | 146 | compound_interfaces_fp = get_output_file(compound_interfaces_filename, |
paul@126 | 147 | compound_dirname, conf.compound); |
paul@91 | 148 | if (compound_interfaces_fp == NULL) |
paul@157 | 149 | return 0; |
paul@90 | 150 | } |
paul@90 | 151 | |
paul@126 | 152 | if (conf.routines) |
paul@56 | 153 | { |
paul@126 | 154 | s = (conf.language == CPP_LANGUAGE) ? server_filename_cpp : |
paul@97 | 155 | server_filename_c; |
paul@126 | 156 | compound_dispatch_fp = get_output_file(s, compound_dirname, conf.compound); |
paul@91 | 157 | if (compound_dispatch_fp == NULL) |
paul@157 | 158 | return 0; |
paul@56 | 159 | } |
paul@56 | 160 | |
paul@56 | 161 | /* Emit prologues. */ |
paul@56 | 162 | |
paul@91 | 163 | if (compound_dispatch_fp != NULL) |
paul@90 | 164 | { |
paul@126 | 165 | fprintf(compound_dispatch_fp, compound_dispatch_prologue, conf.compound); |
paul@56 | 166 | |
paul@106 | 167 | /* Write the handle function and dispatch function prologue. */ |
paul@90 | 168 | |
paul@126 | 169 | write_handler_signature(conf.compound_name, DEFINITION_ROLE, |
paul@106 | 170 | compound_dispatch_fp); |
paul@126 | 171 | fprintf(compound_dispatch_fp, handle_function, conf.compound_name); |
paul@117 | 172 | fputs(END_FUNCTION, compound_dispatch_fp); |
paul@90 | 173 | |
paul@126 | 174 | write_dispatcher_signature(conf.compound_name, DEFINITION_ROLE, |
paul@106 | 175 | compound_dispatch_fp); |
paul@91 | 176 | fputs(compound_dispatch_function_prologue, compound_dispatch_fp); |
paul@90 | 177 | } |
paul@90 | 178 | |
paul@91 | 179 | if (compound_dispatch_header_fp != NULL) |
paul@90 | 180 | { |
paul@91 | 181 | fprintf(compound_dispatch_header_fp, compound_dispatch_header_prologue, |
paul@126 | 182 | conf.compound); |
paul@90 | 183 | |
paul@106 | 184 | /* Write the handler and dispatch signatures. */ |
paul@90 | 185 | |
paul@126 | 186 | write_handler_signature(conf.compound_name, DECLARATION_ROLE, |
paul@106 | 187 | compound_dispatch_header_fp); |
paul@90 | 188 | |
paul@126 | 189 | write_dispatcher_signature(conf.compound_name, DECLARATION_ROLE, |
paul@106 | 190 | compound_dispatch_header_fp); |
paul@110 | 191 | fputs("\n", compound_dispatch_header_fp); |
paul@90 | 192 | } |
paul@90 | 193 | |
paul@91 | 194 | if (compound_interface_fp != NULL) |
paul@162 | 195 | fprintf(compound_interface_fp, |
paul@162 | 196 | (conf.language == CPP_LANGUAGE) ? compound_interface_prologue_cpp |
paul@162 | 197 | : compound_interface_prologue_c, |
paul@126 | 198 | conf.compound, conf.compound_name); |
paul@90 | 199 | |
paul@168 | 200 | if (compound_interface_type_fp != NULL) |
paul@168 | 201 | { |
paul@168 | 202 | /* Begin reference type. */ |
paul@168 | 203 | |
paul@168 | 204 | if (conf.language != CPP_LANGUAGE) |
paul@168 | 205 | fprintf(compound_interface_type_fp, compound_ref_type_definition_prologue_c, |
paul@168 | 206 | conf.compound, L4_CAP_TYPE); |
paul@168 | 207 | } |
paul@168 | 208 | |
paul@91 | 209 | if (compound_interfaces_fp != NULL) |
paul@91 | 210 | fputs(compound_interfaces_prologue, compound_interfaces_fp); |
paul@56 | 211 | |
paul@157 | 212 | return 1; |
paul@56 | 213 | } |
paul@56 | 214 | |
paul@91 | 215 | void write_compound_output(struct interface *iface) |
paul@56 | 216 | { |
paul@164 | 217 | char *protocol, *ref; |
paul@70 | 218 | int input_items; |
paul@56 | 219 | |
paul@91 | 220 | if (compound_dispatch_fp != NULL) |
paul@56 | 221 | { |
paul@56 | 222 | protocol = get_protocol(iface->attributes); |
paul@56 | 223 | |
paul@69 | 224 | /* Populate a function dispatching to each interface-level function where |
paul@56 | 225 | the same protocol applies to an entire interface. */ |
paul@56 | 226 | |
paul@56 | 227 | if (protocol != NULL) |
paul@164 | 228 | { |
paul@164 | 229 | ref = get_object_conversion(iface, 1); |
paul@164 | 230 | |
paul@91 | 231 | fprintf(compound_dispatch_fp, dispatch_function_interface_case, |
paul@164 | 232 | protocol, iface->name, ref); |
paul@164 | 233 | |
paul@164 | 234 | free(ref); |
paul@164 | 235 | } |
paul@56 | 236 | |
paul@69 | 237 | /* Or dispatch to each operation defined at this level. */ |
paul@56 | 238 | |
paul@56 | 239 | else |
paul@162 | 240 | write_dispatcher_cases(iface->signatures, compound_dispatch_fp, iface, 1); |
paul@56 | 241 | } |
paul@70 | 242 | |
paul@91 | 243 | if (compound_dispatch_header_fp != NULL) |
paul@70 | 244 | { |
paul@70 | 245 | /* Compute the maximum number of items expected by each interface. */ |
paul@70 | 246 | |
paul@70 | 247 | input_items = get_max_input_items(iface->signatures); |
paul@70 | 248 | |
paul@70 | 249 | if (input_items > max_input_items) |
paul@70 | 250 | max_input_items = input_items; |
paul@70 | 251 | } |
paul@90 | 252 | |
paul@91 | 253 | /* Add this interface to the compound interface. */ |
paul@91 | 254 | |
paul@91 | 255 | if (compound_interface_fp != NULL) |
paul@91 | 256 | write_compound_interface(iface); |
paul@90 | 257 | |
paul@91 | 258 | /* Add this interface's header to the compound interface includes. */ |
paul@91 | 259 | |
paul@91 | 260 | if (compound_interfaces_fp != NULL) |
paul@112 | 261 | write_include(output_basename, "_interface.h", compound_interfaces_fp); |
paul@90 | 262 | |
paul@90 | 263 | processed_interfaces++; |
paul@69 | 264 | } |
paul@56 | 265 | |
paul@91 | 266 | /* Generate includes for the server and common declarations from each input |
paul@91 | 267 | file. */ |
paul@56 | 268 | |
paul@91 | 269 | void write_compound_dispatch_include(void) |
paul@69 | 270 | { |
paul@91 | 271 | if (compound_dispatch_header_fp != NULL) |
paul@112 | 272 | write_include(output_basename, "_server.h", compound_dispatch_header_fp); |
paul@56 | 273 | } |
paul@56 | 274 | |
paul@91 | 275 | /* Augment a compound interface class declaration. */ |
paul@90 | 276 | |
paul@91 | 277 | void write_compound_interface(struct interface *iface) |
paul@90 | 278 | { |
paul@162 | 279 | char *sep; |
paul@162 | 280 | |
paul@162 | 281 | if (conf.language == CPP_LANGUAGE) |
paul@162 | 282 | { |
paul@162 | 283 | sep = processed_interfaces ? ", " : " "; |
paul@162 | 284 | fprintf(compound_interface_fp, "%spublic %s", sep, iface->name); |
paul@162 | 285 | } |
paul@162 | 286 | else |
paul@162 | 287 | fprintf(compound_interface_fp, " iface_%s *to_%s;\n", iface->name, iface->name); |
paul@168 | 288 | |
paul@168 | 289 | /* Include reference type. */ |
paul@168 | 290 | |
paul@168 | 291 | if (conf.language != CPP_LANGUAGE) |
paul@168 | 292 | fprintf(compound_interface_type_fp, compound_ref_type_definition_member_c, |
paul@168 | 293 | iface->name, iface->name); |
paul@90 | 294 | } |
paul@90 | 295 | |
paul@91 | 296 | void end_compound_output(void) |
paul@56 | 297 | { |
paul@56 | 298 | /* Close the files. */ |
paul@56 | 299 | |
paul@91 | 300 | if (compound_dispatch_fp != NULL) |
paul@56 | 301 | { |
paul@91 | 302 | fputs(compound_dispatch_epilogue, compound_dispatch_fp); |
paul@117 | 303 | fputs(END_FUNCTION, compound_dispatch_fp); |
paul@91 | 304 | fclose(compound_dispatch_fp); |
paul@56 | 305 | } |
paul@56 | 306 | |
paul@91 | 307 | if (compound_dispatch_header_fp != NULL) |
paul@70 | 308 | { |
paul@112 | 309 | fprintf(compound_dispatch_header_fp, expected_items_definition, |
paul@126 | 310 | conf.compound_name, max_input_items); |
paul@91 | 311 | fclose(compound_dispatch_header_fp); |
paul@70 | 312 | } |
paul@90 | 313 | |
paul@91 | 314 | if (compound_interface_fp != NULL) |
paul@90 | 315 | { |
paul@162 | 316 | if (conf.language == CPP_LANGUAGE) |
paul@162 | 317 | fputs(compound_interface_epilogue_cpp, compound_interface_fp); |
paul@162 | 318 | else |
paul@164 | 319 | { |
paul@162 | 320 | fprintf(compound_interface_fp, compound_interface_epilogue_c, |
paul@162 | 321 | conf.compound_name); |
paul@162 | 322 | |
paul@168 | 323 | /* Include object type. */ |
paul@164 | 324 | |
paul@164 | 325 | fprintf(compound_interface_fp, object_type_definition_c, |
paul@164 | 326 | conf.compound_name, conf.compound_name, conf.compound_name); |
paul@164 | 327 | } |
paul@164 | 328 | |
paul@91 | 329 | fclose(compound_interface_fp); |
paul@90 | 330 | } |
paul@90 | 331 | |
paul@168 | 332 | if (compound_interface_type_fp != NULL) |
paul@168 | 333 | { |
paul@168 | 334 | /* Complete reference type. */ |
paul@168 | 335 | |
paul@168 | 336 | if (conf.language != CPP_LANGUAGE) |
paul@168 | 337 | fprintf(compound_interface_type_fp, compound_ref_type_definition_epilogue_c, |
paul@168 | 338 | conf.compound_name); |
paul@168 | 339 | |
paul@168 | 340 | fclose(compound_interface_type_fp); |
paul@168 | 341 | } |
paul@168 | 342 | |
paul@91 | 343 | if (compound_interfaces_fp != NULL) |
paul@91 | 344 | fclose(compound_interfaces_fp); |
paul@56 | 345 | } |
paul@56 | 346 | |
paul@50 | 347 | |
paul@50 | 348 | |
paul@33 | 349 | /* Generate files containing interface details. */ |
paul@33 | 350 | |
paul@33 | 351 | void write_files(struct interface *iface) |
paul@33 | 352 | { |
paul@110 | 353 | char *filename; |
paul@41 | 354 | |
paul@41 | 355 | /* NOTE: Should exit with an error. */ |
paul@33 | 356 | |
paul@56 | 357 | if (!set_output_location(iface)) |
paul@41 | 358 | return; |
paul@41 | 359 | |
paul@91 | 360 | /* Include server details for a compound interface dispatch function. */ |
paul@69 | 361 | |
paul@91 | 362 | write_compound_dispatch_include(); |
paul@69 | 363 | |
paul@33 | 364 | /* Open the separate files and write the details of each interface. */ |
paul@33 | 365 | |
paul@126 | 366 | if (conf.headers) |
paul@39 | 367 | { |
paul@126 | 368 | if (conf.client) |
paul@45 | 369 | { |
paul@45 | 370 | client_header_fp = get_output_file(client_header_filename, output_dirname, output_basename); |
paul@45 | 371 | if (client_header_fp == NULL) |
paul@45 | 372 | goto finalisation; |
paul@45 | 373 | } |
paul@45 | 374 | |
paul@126 | 375 | if (conf.server) |
paul@45 | 376 | { |
paul@45 | 377 | server_header_fp = get_output_file(server_header_filename, output_dirname, output_basename); |
paul@45 | 378 | if (server_header_fp == NULL) |
paul@45 | 379 | goto finalisation; |
paul@45 | 380 | } |
paul@45 | 381 | } |
paul@45 | 382 | |
paul@126 | 383 | if (conf.interfaces) |
paul@86 | 384 | { |
paul@119 | 385 | interface_fp = get_output_file(interface_filename, output_dirname, output_basename); |
paul@119 | 386 | if (interface_fp == NULL) |
paul@119 | 387 | goto finalisation; |
paul@86 | 388 | } |
paul@86 | 389 | |
paul@126 | 390 | if (conf.routines) |
paul@45 | 391 | { |
paul@126 | 392 | if (conf.client) |
paul@45 | 393 | { |
paul@126 | 394 | filename = (conf.language == CPP_LANGUAGE) ? client_filename_cpp : client_filename_c; |
paul@110 | 395 | client_fp = get_output_file(filename, output_dirname, output_basename); |
paul@45 | 396 | if (client_fp == NULL) |
paul@45 | 397 | goto finalisation; |
paul@45 | 398 | } |
paul@45 | 399 | |
paul@126 | 400 | if (conf.server) |
paul@45 | 401 | { |
paul@126 | 402 | filename = (conf.language == CPP_LANGUAGE) ? server_filename_cpp : server_filename_c; |
paul@110 | 403 | server_fp = get_output_file(filename, output_dirname, output_basename); |
paul@45 | 404 | if (server_fp == NULL) |
paul@56 | 405 | goto finalisation; |
paul@45 | 406 | } |
paul@39 | 407 | } |
paul@35 | 408 | |
paul@35 | 409 | /* Emit prologues. */ |
paul@35 | 410 | |
paul@45 | 411 | if (client_fp != NULL) |
paul@45 | 412 | fprintf(client_fp, client_prologue, output_basename, output_basename); |
paul@45 | 413 | |
paul@45 | 414 | if (client_header_fp != NULL) |
paul@45 | 415 | fputs(header_prologue, client_header_fp); |
paul@35 | 416 | |
paul@45 | 417 | if (server_fp != NULL) |
paul@90 | 418 | fprintf(server_fp, server_prologue, output_basename, output_basename); |
paul@45 | 419 | |
paul@45 | 420 | if (server_header_fp != NULL) |
paul@71 | 421 | fputs(server_header_prologue, server_header_fp); |
paul@71 | 422 | |
paul@119 | 423 | if (interface_fp != NULL) |
paul@119 | 424 | fputs(header_prologue, interface_fp); |
paul@35 | 425 | |
paul@35 | 426 | /* Write the interface details. */ |
paul@33 | 427 | |
paul@87 | 428 | write_interfaces(iface); |
paul@45 | 429 | |
paul@45 | 430 | finalisation: |
paul@35 | 431 | |
paul@35 | 432 | /* Close the files. */ |
paul@35 | 433 | |
paul@45 | 434 | if (client_fp != NULL) |
paul@45 | 435 | fclose(client_fp); |
paul@45 | 436 | |
paul@45 | 437 | if (client_header_fp != NULL) |
paul@45 | 438 | fclose(client_header_fp); |
paul@35 | 439 | |
paul@45 | 440 | if (server_fp != NULL) |
paul@45 | 441 | fclose(server_fp); |
paul@45 | 442 | |
paul@45 | 443 | if (server_header_fp != NULL) |
paul@45 | 444 | fclose(server_header_fp); |
paul@35 | 445 | |
paul@119 | 446 | if (interface_fp != NULL) |
paul@119 | 447 | fclose(interface_fp); |
paul@71 | 448 | |
paul@41 | 449 | /* Free the names. */ |
paul@41 | 450 | |
paul@126 | 451 | if (conf.output_dir == NULL) |
paul@41 | 452 | free(output_dirname); |
paul@41 | 453 | |
paul@41 | 454 | free(output_basename); |
paul@33 | 455 | } |
paul@33 | 456 | |
paul@14 | 457 | /* Generate the source file corresponding to the interface. */ |
paul@14 | 458 | |
paul@87 | 459 | void write_interfaces(struct interface *iface) |
paul@14 | 460 | { |
paul@112 | 461 | int input_items; |
paul@112 | 462 | |
paul@51 | 463 | if (iface == NULL) |
paul@51 | 464 | return; |
paul@51 | 465 | |
paul@33 | 466 | /* The list is reversed. */ |
paul@33 | 467 | |
paul@87 | 468 | write_interfaces(iface->tail); |
paul@14 | 469 | |
paul@51 | 470 | /* Write this particular interface after all referenced ones. */ |
paul@33 | 471 | |
paul@126 | 472 | if (conf.verbose) |
paul@40 | 473 | show_interface(iface); |
paul@22 | 474 | |
paul@91 | 475 | /* Record details of this interface in the compound output. */ |
paul@69 | 476 | |
paul@91 | 477 | write_compound_output(iface); |
paul@69 | 478 | |
paul@46 | 479 | /* Emit function definitions. */ |
paul@14 | 480 | |
paul@45 | 481 | if (client_fp != NULL) |
paul@117 | 482 | { |
paul@46 | 483 | write_functions(iface->signatures, client_fp, iface, |
paul@46 | 484 | write_client_function); |
paul@14 | 485 | |
paul@126 | 486 | if (conf.language == C_LANGUAGE) |
paul@117 | 487 | write_client_interface(iface, client_fp); |
paul@117 | 488 | } |
paul@117 | 489 | |
paul@46 | 490 | if (server_fp != NULL) |
paul@52 | 491 | { |
paul@46 | 492 | write_functions(iface->signatures, server_fp, iface, |
paul@46 | 493 | write_server_function); |
paul@14 | 494 | |
paul@106 | 495 | /* Emit handle and dispatch functions. */ |
paul@106 | 496 | |
paul@117 | 497 | write_handler_signature(iface->name, DEFINITION_ROLE, server_fp); |
paul@106 | 498 | fprintf(server_fp, handle_function, iface->name); |
paul@117 | 499 | fputs(END_FUNCTION, server_fp); |
paul@106 | 500 | |
paul@52 | 501 | write_dispatcher(iface->signatures, server_fp, iface); |
paul@52 | 502 | } |
paul@52 | 503 | |
paul@14 | 504 | /* Emit the headers. */ |
paul@14 | 505 | |
paul@45 | 506 | if (client_header_fp != NULL) |
paul@115 | 507 | { |
paul@116 | 508 | /* Emit interface include to obtain the type employed by the client |
paul@115 | 509 | interface. */ |
paul@115 | 510 | |
paul@116 | 511 | write_include(output_basename, "_interface.h", client_header_fp); |
paul@115 | 512 | |
paul@113 | 513 | write_interface_definition(iface, CLIENT_ROLE, client_header_fp); |
paul@115 | 514 | } |
paul@46 | 515 | |
paul@46 | 516 | if (server_header_fp != NULL) |
paul@46 | 517 | { |
paul@117 | 518 | /* Emit interface include to obtain the interface type. */ |
paul@90 | 519 | |
paul@117 | 520 | write_include(output_basename, "_interface.h", server_header_fp); |
paul@90 | 521 | |
paul@46 | 522 | /* Emit signatures. */ |
paul@46 | 523 | |
paul@117 | 524 | write_signatures(iface->signatures, DECLARATION_ROLE, server_header_fp, |
paul@117 | 525 | iface, write_server_signature); |
paul@52 | 526 | |
paul@106 | 527 | /* Emit dispatch and handle function signatures. */ |
paul@106 | 528 | |
paul@110 | 529 | write_dispatcher_signature(iface->name, DECLARATION_ROLE, server_header_fp); |
paul@110 | 530 | write_handler_signature(iface->name, DECLARATION_ROLE, server_header_fp); |
paul@32 | 531 | } |
paul@32 | 532 | |
paul@120 | 533 | /* The server interface is used by client and server code. */ |
paul@120 | 534 | |
paul@119 | 535 | if (interface_fp != NULL) |
paul@119 | 536 | write_interface_definition(iface, SERVER_ROLE, interface_fp); |
paul@14 | 537 | } |
paul@14 | 538 | |
paul@14 | 539 | /* Generate functions corresponding to the signatures. */ |
paul@14 | 540 | |
paul@51 | 541 | void write_functions(struct signature *sig, FILE *fp, struct interface *iface, |
paul@46 | 542 | void (*write_function)(struct signature *, FILE *, struct interface *)) |
paul@14 | 543 | { |
paul@51 | 544 | if (sig == NULL) |
paul@51 | 545 | return; |
paul@51 | 546 | |
paul@51 | 547 | write_function(sig, fp, iface); |
paul@51 | 548 | write_functions(sig->tail, fp, iface, write_function); |
paul@14 | 549 | } |