1.1 --- a/docs/idl.1 Wed Nov 06 15:53:52 2019 +0100
1.2 +++ b/docs/idl.1 Wed Nov 06 17:52:12 2019 +0100
1.3 @@ -83,16 +83,17 @@
1.4 of the option and an equals sign (\fB=\fP) or in the argument that follows them:
1.5 .PP
1.6 .TP
1.7 +.BR \-C ", " \-\-compound
1.8 +Generate compound interface files, indicating the name of the compound interface
1.9 +which will also be the prefix of the generated files; such files are employed by
1.10 +servers to pass control to individual interfaces.
1.11 +.TP
1.12 .BR \-d ", " \-\-dir
1.13 Indicate the output directory for generated files.
1.14 .TP
1.15 -.BR \-D ", " \-\-dispatcher
1.16 -Generate common dispatch files, indicating the name prefix of the files; such
1.17 -files are employed by servers to pass control to individual interfaces.
1.18 -.TP
1.19 .BR \-l ", " \-\-language
1.20 Select the programming language to be used for output; currently only
1.21 -.IR C " and " C++
1.22 +.BR C " and " C++
1.23 are accepted as values for this option.
1.24 .SH EXAMPLES
1.25 Compile the interfaces in
1.26 @@ -123,12 +124,14 @@
1.27 .IP
1.28 idl --language=C++ -r -s hello.idl
1.29 .PP
1.30 -Generate common dispatch header files and routines for a server:
1.31 +Generate compound interface header files and dispatch routines for a server:
1.32 .IP
1.33 -idl -D greetings hello.idl goodbye.idl
1.34 +idl -C greetings hello.idl goodbye.idl
1.35 .PP
1.36 -The above would create a dispatch mechanism for a component supporting both of
1.37 -the indicated interfaces. The following generates just the interface headers:
1.38 +The above would create a dispatch mechanism for a component called
1.39 +.I greetings
1.40 +supporting both of the indicated interfaces. The following generates just the
1.41 +interface headers for the individual interfaces:
1.42 .IP
1.43 idl -i hello.idl goodbye.idl
1.44 .SH INTERFACE DESCRIPTIONS
1.45 @@ -164,12 +167,12 @@
1.46 .SH FILES
1.47 .B idl
1.48 reads all interfaces in a single input file and generates output files that
1.49 -each contain the details of all of these interfaces. Apart from the common
1.50 -dispatch files, output files are written alongside their corresponding input
1.51 +each contain the details of all of these interfaces. Apart from the compound
1.52 +interface files, output files are written alongside their corresponding input
1.53 files. This behaviour can be overridden with the
1.54 .BR \-d " or " \--dir
1.55 -options, choosing a specific output directory for all files including common
1.56 -dispatch files.
1.57 +options, choosing a specific output directory for all files including compound
1.58 +interface files.
1.59 .PP
1.60 The following kinds of output files are generated for a file with a name of the
1.61 form
1.62 @@ -178,46 +181,51 @@
1.63 .TP
1.64 .IR name _client.c
1.65 contains the function definitions needed for the operations of all the
1.66 -interfaces
1.67 +interfaces.
1.68 .TP
1.69 .IR name _client.h
1.70 contains the function declarations, signatures or prototypes for the
1.71 -operations
1.72 +operations.
1.73 .TP
1.74 .IR name _common.h
1.75 contains structures and values associated with the operations; these are used by
1.76 -client and server code
1.77 +client and server code.
1.78 .TP
1.79 .IR name _interface.h
1.80 contains the function declarations, signatures or prototypes for the actual
1.81 -server operations
1.82 +server operations.
1.83 .TP
1.84 -.IR name _server.c
1.85 +.IR name "_server.c or " name _server.cc
1.86 contains the function definitions needed to provide entry points for the
1.87 -operations of all the interfaces
1.88 +operations of all the interfaces.
1.89 .TP
1.90 .IR name _server.h
1.91 contains the function declarations, signatures or prototypes for the entry
1.92 -points
1.93 +points.
1.94 .PP
1.95 Where many input files are provided,
1.96 .B idl
1.97 processes each one in turn, generating a separate set of output files for each
1.98 input file.
1.99 .PP
1.100 -For server components, common dispatch files can also be produced with their
1.101 +For server components, compound interface files can also be produced with their
1.102 names chosen using the
1.103 -.BR \-D " or " \-\-dispatcher
1.104 +.BR \-C " or " \-\-compound
1.105 options. With a value of
1.106 .I name
1.107 given with these options, files of the following form are produced:
1.108 .TP
1.109 -.IR name _dispatch.c
1.110 -contains the function definitions needed to dispatch to the interfaces
1.111 +.IR name _compound_interface.h
1.112 +contains a compound interface declaration (for C++ only) needed for the dispatch
1.113 +mechanism to function, also to be used by the actual component implementing the
1.114 +interfaces.
1.115 +.TP
1.116 +.IR name "_dispatch.c or " name _dispatch.cc
1.117 +contains the function definitions needed to dispatch to the interfaces.
1.118 .TP
1.119 .IR name _dispatch.h
1.120 contains the function declarations, signatures or prototypes for the dispatch
1.121 -functions
1.122 +functions.
1.123 .PP
1.124 These files provide support for interpreting messages received by servers and
1.125 directing handling of such messages to interface-specific dispatch functions or
1.126 @@ -251,7 +259,7 @@
1.127 .PP
1.128 Each individual component exporting interfaces must have dispatch functions
1.129 generated using the
1.130 -.BR \-D " or " \-\-dispatcher
1.131 +.BR \-C " or " \-\-compound
1.132 options. The generated code is combined with the other server code generated for
1.133 the individual interfaces.
1.134 .PP
2.1 --- a/main.c Wed Nov 06 15:53:52 2019 +0100
2.2 +++ b/main.c Wed Nov 06 17:52:12 2019 +0100
2.3 @@ -40,7 +40,10 @@
2.4
2.5 char *output_prefix = NULL;
2.6 char *output_dir = NULL;
2.7 -char *output_dispatcher = NULL;
2.8 +
2.9 +/* Compound interface and dispatcher output. */
2.10 +
2.11 +char *output_compound = NULL;
2.12
2.13 int output_client = 0;
2.14 int output_server = 0;
2.15 @@ -82,8 +85,8 @@
2.16 /* long opt following var pointer short opt */
2.17 {"all", no_argument, NULL, 'a' },
2.18 {"client", no_argument, NULL, 'c' },
2.19 + {"compound", required_argument, NULL, 'C' },
2.20 {"dir", required_argument, NULL, 'd' },
2.21 - {"dispatcher", required_argument, NULL, 'D' },
2.22 {"headers", no_argument, NULL, 'h' },
2.23 {"interfaces", no_argument, NULL, 'i' },
2.24 {"language", required_argument, NULL, 'l' },
2.25 @@ -110,7 +113,7 @@
2.26
2.27 while (1)
2.28 {
2.29 - option = getopt_long(argc, argv, "acd:D:hil:rsv", long_options, NULL);
2.30 + option = getopt_long(argc, argv, "acC:d:hil:rsv", long_options, NULL);
2.31 if (option == -1)
2.32 break;
2.33
2.34 @@ -130,17 +133,17 @@
2.35 output_selected_role = 1;
2.36 break;
2.37
2.38 + /* Select compound interface name and output. */
2.39 + case 'C':
2.40 + output_compound = optarg;
2.41 + output_selected_role = 1;
2.42 + break;
2.43 +
2.44 /* Set output directory. */
2.45 case 'd':
2.46 output_dir = optarg;
2.47 break;
2.48
2.49 - /* Select common dispatcher name and output. */
2.50 - case 'D':
2.51 - output_dispatcher = optarg;
2.52 - output_selected_role = 1;
2.53 - break;
2.54 -
2.55 /* Generate headers. */
2.56 case 'h':
2.57 output_headers = 1;
2.58 @@ -200,9 +203,9 @@
2.59 output_client = 1; output_server = 1;
2.60 }
2.61
2.62 - /* Begin generating any common dispatcher function. */
2.63 + /* Begin generating any compound interface code. */
2.64
2.65 - begin_common_dispatcher();
2.66 + begin_compound_output();
2.67
2.68 /* Process standard input without any named files. */
2.69
2.70 @@ -241,9 +244,9 @@
2.71 }
2.72 }
2.73
2.74 - /* End generating any common dispatcher function. */
2.75 + /* End generating any compound interface code. */
2.76
2.77 - end_common_dispatcher();
2.78 + end_compound_output();
2.79
2.80 return 0;
2.81 }
3.1 --- a/program.c Wed Nov 06 15:53:52 2019 +0100
3.2 +++ b/program.c Wed Nov 06 17:52:12 2019 +0100
3.3 @@ -28,7 +28,7 @@
3.4
3.5 /* Program state set in the main program. */
3.6
3.7 -extern char *output_prefix, *output_dir, *output_dispatcher;
3.8 +extern char *output_prefix, *output_dir, *output_compound;
3.9
3.10 extern int output_client, output_server,
3.11 output_headers, output_interfaces, output_routines,
3.12 @@ -47,11 +47,10 @@
3.13 *server_interface_fp = NULL,
3.14 *common_fp = NULL;
3.15
3.16 -/* Common dispatcher files. */
3.17 +/* Compound interface and dispatcher files. */
3.18
3.19 -FILE *dispatcher_fp = NULL, *dispatcher_header_fp = NULL,
3.20 - *dispatcher_interface_fp = NULL,
3.21 - *dispatcher_interfaces_fp = NULL;
3.22 +FILE *compound_dispatch_fp = NULL, *compound_dispatch_header_fp = NULL,
3.23 + *compound_interface_fp = NULL, *compound_interfaces_fp = NULL;
3.24
3.25 /* Processed interfaces. */
3.26
3.27 @@ -125,105 +124,103 @@
3.28
3.29
3.30
3.31 -/* Generate a common dispatcher function, if requested. */
3.32 +/* Generate compound code output, if requested. */
3.33
3.34 -void begin_common_dispatcher(void)
3.35 +void begin_compound_output(void)
3.36 {
3.37 char *common_dirname = output_dir != NULL ? output_dir : ".";
3.38 - char *dispatcher_filename;
3.39 char *s;
3.40
3.41 - if (output_dispatcher == NULL)
3.42 + if (output_compound == NULL)
3.43 return;
3.44
3.45 processed_interfaces = 0;
3.46
3.47 if (output_headers)
3.48 {
3.49 - dispatcher_header_fp = get_output_file(dispatcher_header_filename,
3.50 - common_dirname, output_dispatcher);
3.51 - if (dispatcher_header_fp == NULL)
3.52 + compound_dispatch_header_fp = get_output_file(compound_dispatch_header_filename,
3.53 + common_dirname, output_compound);
3.54 + if (compound_dispatch_header_fp == NULL)
3.55 goto fail;
3.56 }
3.57
3.58 if (output_interfaces)
3.59 {
3.60 - dispatcher_interface_fp = get_output_file(dispatcher_interface_filename,
3.61 - common_dirname, output_dispatcher);
3.62 - if (dispatcher_interface_fp == NULL)
3.63 + compound_interface_fp = get_output_file(compound_interface_filename,
3.64 + common_dirname, output_compound);
3.65 + if (compound_interface_fp == NULL)
3.66 goto fail;
3.67
3.68 - dispatcher_interfaces_fp = get_output_file(dispatcher_interfaces_filename,
3.69 - common_dirname, output_dispatcher);
3.70 - if (dispatcher_interfaces_fp == NULL)
3.71 + compound_interfaces_fp = get_output_file(compound_interfaces_filename,
3.72 + common_dirname, output_compound);
3.73 + if (compound_interfaces_fp == NULL)
3.74 goto fail;
3.75 }
3.76
3.77 if (output_routines)
3.78 {
3.79 - dispatcher_filename = (output_language == CPP_LANGUAGE) ?
3.80 - dispatcher_filename_cpp :
3.81 - dispatcher_filename_c;
3.82 - dispatcher_fp = get_output_file(dispatcher_filename, common_dirname,
3.83 - output_dispatcher);
3.84 - if (dispatcher_fp == NULL)
3.85 + s = (output_language == CPP_LANGUAGE) ? compound_dispatch_filename_cpp :
3.86 + compound_dispatch_filename_c;
3.87 + compound_dispatch_fp = get_output_file(s, common_dirname, output_compound);
3.88 + if (compound_dispatch_fp == NULL)
3.89 goto fail;
3.90 }
3.91
3.92 /* Emit prologues. */
3.93
3.94 - if (dispatcher_fp != NULL)
3.95 + if (compound_dispatch_fp != NULL)
3.96 {
3.97 - fprintf(dispatcher_fp, dispatcher_prologue,
3.98 - output_dispatcher, output_dispatcher, output_dispatcher);
3.99 + fprintf(compound_dispatch_fp, compound_dispatch_prologue,
3.100 + output_compound, output_compound, output_compound);
3.101
3.102 /* Write the handler function. */
3.103
3.104 - write_common_dispatcher_handler_signature(dispatcher_fp);
3.105 - fputs("\n", dispatcher_fp);
3.106 - fprintf(dispatcher_fp, dispatcher_handle_function, output_dispatcher);
3.107 + write_compound_handler_signature(compound_dispatch_fp);
3.108 + fputs("\n", compound_dispatch_fp);
3.109 + fprintf(compound_dispatch_fp, compound_handle_function, output_compound);
3.110
3.111 /* Write the dispatch function. */
3.112
3.113 - write_common_dispatcher_signature(dispatcher_fp);
3.114 - fputs("\n", dispatcher_fp);
3.115 - fputs(dispatcher_function_prologue, dispatcher_fp);
3.116 + write_compound_dispatch_signature(compound_dispatch_fp);
3.117 + fputs("\n", compound_dispatch_fp);
3.118 + fputs(compound_dispatch_function_prologue, compound_dispatch_fp);
3.119 }
3.120
3.121 - if (dispatcher_header_fp != NULL)
3.122 + if (compound_dispatch_header_fp != NULL)
3.123 {
3.124 - fprintf(dispatcher_header_fp, dispatcher_header_prologue, output_dispatcher);
3.125 + fprintf(compound_dispatch_header_fp, compound_dispatch_header_prologue,
3.126 + output_compound);
3.127
3.128 /* Write the handler signature. */
3.129
3.130 - write_common_dispatcher_handler_signature(dispatcher_header_fp);
3.131 - fputs(";\n", dispatcher_header_fp);
3.132 + write_compound_handler_signature(compound_dispatch_header_fp);
3.133 + fputs(";\n", compound_dispatch_header_fp);
3.134
3.135 /* Write the dispatch signature. */
3.136
3.137 - write_common_dispatcher_signature(dispatcher_header_fp);
3.138 - fputs(";\n\n", dispatcher_header_fp);
3.139 + write_compound_dispatch_signature(compound_dispatch_header_fp);
3.140 + fputs(";\n\n", compound_dispatch_header_fp);
3.141 }
3.142
3.143 - if (dispatcher_interface_fp != NULL)
3.144 - fprintf(dispatcher_interface_fp, dispatcher_interface_prologue,
3.145 - output_dispatcher, output_dispatcher);
3.146 + if (compound_interface_fp != NULL)
3.147 + fprintf(compound_interface_fp, compound_interface_prologue,
3.148 + output_compound, output_compound);
3.149
3.150 - if (dispatcher_interfaces_fp != NULL)
3.151 - fputs(dispatcher_interfaces_prologue, dispatcher_interfaces_fp);
3.152 + if (compound_interfaces_fp != NULL)
3.153 + fputs(compound_interfaces_prologue, compound_interfaces_fp);
3.154
3.155 return;
3.156
3.157 fail:
3.158 - end_common_dispatcher();
3.159 + end_compound_output();
3.160 }
3.161
3.162 -void write_common_dispatcher(struct interface *iface)
3.163 +void write_compound_output(struct interface *iface)
3.164 {
3.165 char *protocol;
3.166 int input_items;
3.167
3.168 - if (dispatcher_fp != NULL)
3.169 + if (compound_dispatch_fp != NULL)
3.170 {
3.171 protocol = get_protocol(iface->attributes);
3.172
3.173 @@ -231,19 +228,16 @@
3.174 the same protocol applies to an entire interface. */
3.175
3.176 if (protocol != NULL)
3.177 - {
3.178 - fprintf(dispatcher_fp, " case %s:\n", protocol);
3.179 - fprintf(dispatcher_fp, " dispatch_%s(msg, _self);\n", iface->name);
3.180 - fprintf(dispatcher_fp, " break;\n\n");
3.181 - }
3.182 + fprintf(compound_dispatch_fp, dispatch_function_interface_case,
3.183 + protocol, iface->name);
3.184
3.185 /* Or dispatch to each operation defined at this level. */
3.186
3.187 else
3.188 - write_dispatcher_cases(iface->signatures, dispatcher_fp, iface);
3.189 + write_dispatcher_cases(iface->signatures, compound_dispatch_fp, iface);
3.190 }
3.191
3.192 - if (dispatcher_header_fp != NULL)
3.193 + if (compound_dispatch_header_fp != NULL)
3.194 {
3.195 /* Compute the maximum number of items expected by each interface. */
3.196
3.197 @@ -253,77 +247,85 @@
3.198 max_input_items = input_items;
3.199 }
3.200
3.201 - if (dispatcher_interface_fp != NULL)
3.202 - write_common_interface(iface);
3.203 + /* Add this interface to the compound interface. */
3.204 +
3.205 + if (compound_interface_fp != NULL)
3.206 + write_compound_interface(iface);
3.207
3.208 - if (dispatcher_interfaces_fp != NULL)
3.209 - fprintf(dispatcher_interfaces_fp, "#include \"%s_interface.h\"\n", output_basename);
3.210 + /* Add this interface's header to the compound interface includes. */
3.211 +
3.212 + if (compound_interfaces_fp != NULL)
3.213 + fprintf(compound_interfaces_fp, "#include \"%s_interface.h\"\n",
3.214 + output_basename);
3.215
3.216 processed_interfaces++;
3.217 }
3.218
3.219 -/* Generate includes for each input file's declarations. */
3.220 +/* Generate includes for the server and common declarations from each input
3.221 + file. */
3.222
3.223 -void write_common_dispatcher_include(void)
3.224 +void write_compound_dispatch_include(void)
3.225 {
3.226 - if (dispatcher_header_fp != NULL)
3.227 + if (compound_dispatch_header_fp != NULL)
3.228 {
3.229 - fprintf(dispatcher_header_fp, "#include \"%s_server.h\"\n", output_basename);
3.230 - fprintf(dispatcher_header_fp, "#include \"%s_common.h\"\n", output_basename);
3.231 + fprintf(compound_dispatch_header_fp, "#include \"%s_server.h\"\n",
3.232 + output_basename);
3.233 + fprintf(compound_dispatch_header_fp, "#include \"%s_common.h\"\n",
3.234 + output_basename);
3.235 }
3.236 }
3.237
3.238 -void write_common_dispatcher_signature(FILE *fp)
3.239 +void write_compound_dispatch_signature(FILE *fp)
3.240 {
3.241 char *s = (output_language == CPP_LANGUAGE) ?
3.242 - dispatcher_function_signature_cpp :
3.243 - dispatcher_function_signature_c;
3.244 + compound_dispatch_function_signature_cpp :
3.245 + compound_dispatch_function_signature_c;
3.246
3.247 - fprintf(fp, s, output_dispatcher, output_dispatcher);
3.248 + fprintf(fp, s, output_compound, output_compound);
3.249 }
3.250
3.251 -void write_common_dispatcher_handler_signature(FILE *fp)
3.252 +void write_compound_handler_signature(FILE *fp)
3.253 {
3.254 char *s = (output_language == CPP_LANGUAGE) ?
3.255 - dispatcher_handle_function_signature_cpp :
3.256 - dispatcher_handle_function_signature_c;
3.257 + compound_handle_function_signature_cpp :
3.258 + compound_handle_function_signature_c;
3.259
3.260 - fprintf(fp, s, output_dispatcher, output_dispatcher);
3.261 + fprintf(fp, s, output_compound, output_compound);
3.262 }
3.263
3.264 -/* Write a common interface class. */
3.265 +/* Augment a compound interface class declaration. */
3.266
3.267 -void write_common_interface(struct interface *iface)
3.268 +void write_compound_interface(struct interface *iface)
3.269 {
3.270 char *sep = processed_interfaces ? ", " : " ";
3.271 - fprintf(dispatcher_interface_fp, "%spublic %s", sep, iface->name);
3.272 + fprintf(compound_interface_fp, "%spublic %s", sep, iface->name);
3.273 }
3.274
3.275 -void end_common_dispatcher(void)
3.276 +void end_compound_output(void)
3.277 {
3.278 /* Close the files. */
3.279
3.280 - if (dispatcher_fp != NULL)
3.281 + if (compound_dispatch_fp != NULL)
3.282 {
3.283 - fputs(dispatcher_epilogue, dispatcher_fp);
3.284 - fclose(dispatcher_fp);
3.285 + fputs(compound_dispatch_epilogue, compound_dispatch_fp);
3.286 + fclose(compound_dispatch_fp);
3.287 }
3.288
3.289 - if (dispatcher_header_fp != NULL)
3.290 + if (compound_dispatch_header_fp != NULL)
3.291 {
3.292 - fprintf(dispatcher_header_fp, dispatcher_header_epilogue, output_dispatcher,
3.293 - max_input_items);
3.294 - fclose(dispatcher_header_fp);
3.295 + fprintf(compound_dispatch_header_fp, compound_dispatch_header_epilogue,
3.296 + output_compound, max_input_items);
3.297 + fclose(compound_dispatch_header_fp);
3.298 }
3.299
3.300 - if (dispatcher_interface_fp != NULL)
3.301 + if (compound_interface_fp != NULL)
3.302 {
3.303 - fputs(dispatcher_interface_epilogue, dispatcher_interface_fp);
3.304 - fclose(dispatcher_interface_fp);
3.305 + fputs(compound_interface_epilogue, compound_interface_fp);
3.306 + fclose(compound_interface_fp);
3.307 }
3.308
3.309 - if (dispatcher_interfaces_fp != NULL)
3.310 - fclose(dispatcher_interfaces_fp);
3.311 + if (compound_interfaces_fp != NULL)
3.312 + fclose(compound_interfaces_fp);
3.313 }
3.314
3.315
3.316 @@ -339,9 +341,9 @@
3.317 if (!set_output_location(iface))
3.318 return;
3.319
3.320 - /* Record each file in the common dispatcher. */
3.321 + /* Include server details for a compound interface dispatch function. */
3.322
3.323 - write_common_dispatcher_include();
3.324 + write_compound_dispatch_include();
3.325
3.326 /* Open the separate files and write the details of each interface. */
3.327
3.328 @@ -464,9 +466,9 @@
3.329 if (output_verbose)
3.330 show_interface(iface);
3.331
3.332 - /* Record each interface in the common dispatcher. */
3.333 + /* Record details of this interface in the compound output. */
3.334
3.335 - write_common_dispatcher(iface);
3.336 + write_compound_output(iface);
3.337
3.338 /* Emit function definitions. */
3.339
3.340 @@ -713,9 +715,7 @@
3.341
3.342 /* Generate the case and invocation. */
3.343
3.344 - fprintf(fp, " case %s:\n", opcode);
3.345 - fprintf(fp, " ipc_message_send_error(msg, wrap_%s(msg, _self));\n", opname);
3.346 - fprintf(fp, " break;\n\n");
3.347 + fprintf(fp, dispatch_function_wrapper_case, opcode, opname);
3.348
3.349 /* Generate the other cases. */
3.350