1 /* 2 * Generation of interface headers. 3 * 4 * Copyright (C) 2019, 2022 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 <string.h> 24 #include "client.h" 25 #include "common.h" 26 #include "config.h" 27 #include "declaration.h" 28 #include "includes.h" 29 #include "interface.h" 30 #include "server.h" 31 #include "structure.h" 32 #include "templates.h" 33 34 35 36 /* Emit compound interface includes. */ 37 38 static void write_compound_includes(FILE *fp, struct interface *iface) 39 { 40 struct interface_ref *base; 41 42 for (base = iface->bases; base != NULL; base = base->tail) 43 { 44 /* Only output includes where the base resides in a different file. */ 45 46 if (strcmp(iface->output_basename, base->iface->output_basename)) 47 fprintf(fp, compound_interface_include, base->iface->output_basename); 48 } 49 } 50 51 /* Write the reference type members. */ 52 53 static void write_reference_type_members(FILE *fp, struct interface_ref *base) 54 { 55 if (base == NULL) 56 return; 57 58 /* Reverse the list by processing subsequent members first. */ 59 60 write_reference_type_members(fp, base->tail); 61 62 fprintf(fp, compound_ref_type_definition_member_c, 63 base->name, base->name); 64 } 65 66 /* Generate a reference type for C language interfaces. */ 67 68 static void write_reference_type(FILE *fp, struct interface *iface) 69 { 70 struct interface *i; 71 72 if (is_compound_interface(iface)) 73 { 74 fprintf(fp, compound_ref_type_definition_prologue_c, L4_CAP_TYPE); 75 76 write_reference_type_members(fp, iface->bases); 77 78 fprintf(fp, compound_ref_type_definition_epilogue_c, 79 iface->name); 80 } 81 else 82 fprintf(fp, ref_type_definition_c, L4_CAP_TYPE, iface->name); 83 } 84 85 /* Augment compound interface class declarations. */ 86 87 static void write_compound_interface_bases_c(FILE *fp, struct interface *iface) 88 { 89 struct interface_ref *base; 90 91 for (base = iface->bases; base != NULL; base = base->tail) 92 fprintf(fp, interface_body_base_c, base->name, base->name); 93 } 94 95 /* Augment compound interface type declarations. */ 96 97 static void write_compound_interface_bases_cpp(FILE *fp, struct interface *iface) 98 { 99 struct interface_ref *base; 100 int first; 101 102 for (base = iface->bases, first = 1; base != NULL; base = base->tail, first = 0) 103 fprintf(fp, interface_prologue_base_cpp, first ? " : " : ", ", base->name); 104 } 105 106 107 108 /* Write the definition of an interface to the given file for use by client or 109 server components. Client headers employ such definitions as do server 110 interface headers, whereas server wrapper headers employ other descriptions 111 of their operations. */ 112 113 void write_interface_definition(struct interface *iface, 114 enum component_role component, FILE *fp) 115 { 116 int cpp = (conf.language == CPP_LANGUAGE); 117 int client = (component == CLIENT_ROLE); 118 int input_items = get_max_input_items(iface); 119 char *class_name = get_interface_class_name(iface, component); 120 char *name = iface->name; 121 122 /* Emit include statements. */ 123 124 write_includes_separator(iface->includes, fp); 125 write_includes(iface->includes, fp); 126 write_compound_includes(fp, iface); 127 128 /* Generate interface abstractions. */ 129 130 if (!cpp) 131 { 132 /* Define an object reference type for C. */ 133 134 if (!client) 135 write_reference_type(fp, iface); 136 137 /* Define C client signatures representing the client functions. */ 138 139 else 140 write_signatures(iface->signatures, DECLARATION_ROLE, 141 fp, iface, write_client_signature); 142 } 143 144 /* Begin any namespace, defining the class or type. 145 C++ code employs an abstract server interface and a concrete client 146 interface class. 147 C code only employs a server interface which is instantiated for client 148 use elsewhere by employing the client functions. */ 149 150 if (cpp || !client) 151 { 152 if (cpp) 153 { 154 fprintf(fp, interface_prologue_cpp, class_name); 155 156 /* Inherit from the actual interface in the client. */ 157 158 if (client) 159 fprintf(fp, client_interface_prologue_cpp, name); 160 } 161 else 162 fputs(interface_prologue_c, fp); 163 164 /* Augment the interface declaration with base interfaces for compound 165 interfaces. */ 166 167 if (!client && cpp && is_compound_interface(iface)) 168 write_compound_interface_bases_cpp(fp, iface); 169 170 /* Start the class or type body. */ 171 172 fputs(interface_body_begin, fp); 173 174 /* Augment the interface declaration with base interfaces for compound 175 interfaces. */ 176 177 if (!client && !cpp && is_compound_interface(iface)) 178 write_compound_interface_bases_c(fp, iface); 179 180 /* Define any state and initialisation details of a class. */ 181 182 if (cpp) 183 { 184 if (client) 185 fprintf(fp, client_interface_endpoint_declaration_cpp, L4_CAP_TYPE); 186 187 if (iface->signatures != NULL) 188 fputs(interface_signatures_prologue_cpp, fp); 189 190 /* Define a constructor. */ 191 192 if (client) 193 fprintf(fp, client_interface_constructor_cpp, class_name, L4_CAP_TYPE); 194 } 195 196 /* Emit signatures. */ 197 198 write_signatures(iface->signatures, MEMBER_DECLARATION_ROLE, 199 fp, iface, 200 client ? write_client_signature 201 : write_server_interface_signature); 202 203 /* Terminate the class or type body. */ 204 205 if (cpp) 206 fputs(interface_epilogue_cpp, fp); 207 else 208 fprintf(fp, interface_epilogue_c, name); 209 } 210 211 /* Define the maximum number of expected items for the interface. */ 212 213 if (!client) 214 fprintf(fp, expected_items_definition, name, input_items); 215 216 /* Define an object type for C and declare a client interface. */ 217 218 if (!cpp && !client) 219 fprintf(fp, object_type_definition_c, name, name, name); 220 221 if (!cpp && client) 222 fprintf(fp, client_interface_declaration_c, name, name); 223 224 /* Emit opcodes and message access structures with the generic server 225 interface, these being common to both client and server. */ 226 227 if (!client && (iface->signatures != NULL)) 228 { 229 write_opcode_definition(iface, fp); 230 write_structures(iface->signatures, fp, iface); 231 } 232 233 /* Emit a conversion macro for compound interface dispatch. */ 234 235 if (!client) 236 { 237 if (cpp) 238 fprintf(fp, compound_interface_conversion_cpp, name); 239 else 240 fprintf(fp, compound_interface_conversion_c, name, name, name, name); 241 } 242 243 free(class_name); 244 }