1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2014 Garrett D'Amore <garrett@damore.org> 24 * 25 * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 29 /* All Rights Reserved */ 30 /* 31 * University Copyright- Copyright (c) 1982, 1986, 1988 32 * The Regents of the University of California 33 * All Rights Reserved 34 * 35 * University Acknowledgment- Portions of this document are derived from 36 * software developed by the University of California, Berkeley, and its 37 * contributors. 38 */ 39 40 /* 41 * rpc_hout.c, Header file outputter for the RPC protocol compiler 42 */ 43 #include <stdio.h> 44 #include <stdlib.h> 45 #include <ctype.h> 46 #include "rpc_parse.h" 47 #include "rpc_util.h" 48 49 extern void pprocdef(proc_list *, version_list *, char *, int); 50 extern void pdeclaration(char *, declaration *, int, char *); 51 52 static void storexdrfuncdecl(char *, int); 53 static void pconstdef(definition *); 54 static void pstructdef(definition *); 55 static void puniondef(definition *); 56 static void pdefine(char *, char *); 57 static void pprogramdef(definition *); 58 static void parglist(proc_list *, char *); 59 static void penumdef(definition *); 60 static void ptypedef(definition *); 61 static uint_t undefined2(char *, char *); 62 63 enum rpc_gvc { 64 PROGRAM, 65 VERSION, 66 PROCEDURE 67 }; 68 69 /* 70 * Print the C-version of an xdr definition 71 */ 72 void 73 print_datadef(definition *def) 74 { 75 if (def->def_kind == DEF_PROGRAM) /* handle data only */ 76 return; 77 78 if (def->def_kind != DEF_CONST) 79 f_print(fout, "\n"); 80 switch (def->def_kind) { 81 case DEF_STRUCT: 82 pstructdef(def); 83 break; 84 case DEF_UNION: 85 puniondef(def); 86 break; 87 case DEF_ENUM: 88 penumdef(def); 89 break; 90 case DEF_TYPEDEF: 91 ptypedef(def); 92 break; 93 case DEF_PROGRAM: 94 pprogramdef(def); 95 break; 96 case DEF_CONST: 97 pconstdef(def); 98 break; 99 } 100 if (def->def_kind != DEF_PROGRAM && def->def_kind != DEF_CONST) 101 storexdrfuncdecl(def->def_name, def->def_kind != DEF_TYPEDEF || 102 !isvectordef(def->def.ty.old_type, def->def.ty.rel)); 103 } 104 105 106 void 107 print_funcdef(definition *def) 108 { 109 switch (def->def_kind) { 110 case DEF_PROGRAM: 111 f_print(fout, "\n"); 112 pprogramdef(def); 113 break; 114 } 115 } 116 117 /* 118 * store away enough information to allow the XDR functions to be spat 119 * out at the end of the file 120 */ 121 static void 122 storexdrfuncdecl(char *name, int pointerp) 123 { 124 xdrfunc *xdrptr; 125 126 xdrptr = malloc(sizeof (struct xdrfunc)); 127 128 xdrptr->name = name; 129 xdrptr->pointerp = pointerp; 130 xdrptr->next = NULL; 131 132 if (xdrfunc_tail == NULL) { 133 xdrfunc_head = xdrptr; 134 xdrfunc_tail = xdrptr; 135 } else { 136 xdrfunc_tail->next = xdrptr; 137 xdrfunc_tail = xdrptr; 138 } 139 140 141 } 142 143 void 144 print_xdr_func_def(char *name, int pointerp) 145 { 146 f_print(fout, "extern bool_t xdr_%s(XDR *, %s%s);\n", name, 147 name, pointerp ? "*" : ""); 148 } 149 150 151 static void 152 pconstdef(definition *def) 153 { 154 pdefine(def->def_name, def->def.co); 155 } 156 157 /* 158 * print out the definitions for the arguments of functions in the 159 * header file 160 */ 161 static void 162 pargdef(definition *def) 163 { 164 decl_list *l; 165 version_list *vers; 166 char *name; 167 proc_list *plist; 168 169 for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) { 170 for (plist = vers->procs; plist != NULL; plist = plist->next) { 171 if (!newstyle || plist->arg_num < 2) 172 continue; /* old style or single args */ 173 name = plist->args.argname; 174 f_print(fout, "struct %s {\n", name); 175 for (l = plist->args.decls; l != NULL; l = l->next) 176 pdeclaration(name, &l->decl, 1, ";\n"); 177 f_print(fout, "};\n"); 178 f_print(fout, "typedef struct %s %s;\n", name, name); 179 storexdrfuncdecl(name, 1); 180 f_print(fout, "\n"); 181 } 182 } 183 } 184 185 186 static void 187 pstructdef(definition *def) 188 { 189 decl_list *l; 190 char *name = def->def_name; 191 192 f_print(fout, "struct %s {\n", name); 193 for (l = def->def.st.decls; l != NULL; l = l->next) 194 pdeclaration(name, &l->decl, 1, ";\n"); 195 f_print(fout, "};\n"); 196 f_print(fout, "typedef struct %s %s;\n", name, name); 197 } 198 199 static void 200 puniondef(definition *def) 201 { 202 case_list *l; 203 char *name = def->def_name; 204 declaration *decl; 205 206 f_print(fout, "struct %s {\n", name); 207 decl = &def->def.un.enum_decl; 208 if (streq(decl->type, "bool")) 209 f_print(fout, "\tbool_t %s;\n", decl->name); 210 else 211 f_print(fout, "\t%s %s;\n", decl->type, decl->name); 212 f_print(fout, "\tunion {\n"); 213 for (l = def->def.un.cases; l != NULL; l = l->next) { 214 if (l->contflag == 0) 215 pdeclaration(name, &l->case_decl, 2, ";\n"); 216 } 217 decl = def->def.un.default_decl; 218 if (decl && !streq(decl->type, "void")) 219 pdeclaration(name, decl, 2, ";\n"); 220 f_print(fout, "\t} %s_u;\n", name); 221 f_print(fout, "};\n"); 222 f_print(fout, "typedef struct %s %s;\n", name, name); 223 } 224 225 static void 226 pdefine(char *name, char *num) 227 { 228 f_print(fout, "#define\t%s %s\n", name, num); 229 } 230 231 static void 232 puldefine(char *name, char *num, enum rpc_gvc which) 233 { 234 switch (which) { 235 case PROGRAM: 236 case VERSION: 237 case PROCEDURE: 238 f_print(fout, "#define\t%s\t%s\n", name, num); 239 break; 240 default: 241 break; 242 } 243 } 244 245 static uint_t 246 define_printed(proc_list *stop, version_list *start) 247 { 248 version_list *vers; 249 proc_list *proc; 250 251 for (vers = start; vers != NULL; vers = vers->next) { 252 for (proc = vers->procs; proc != NULL; proc = proc->next) { 253 if (proc == stop) 254 return (0); 255 if (streq(proc->proc_name, stop->proc_name)) 256 return (1); 257 } 258 } 259 abort(); 260 /* NOTREACHED */ 261 } 262 263 static void 264 pfreeprocdef(char *name, char *vers) 265 { 266 f_print(fout, "extern int "); 267 pvname(name, vers); 268 f_print(fout, "_freeresult(SVCXPRT *, xdrproc_t, caddr_t);\n"); 269 } 270 271 static void 272 pprogramdef(definition *def) 273 { 274 version_list *vers; 275 proc_list *proc; 276 277 pargdef(def); 278 279 puldefine(def->def_name, def->def.pr.prog_num, PROGRAM); 280 for (vers = def->def.pr.versions; vers != NULL; vers = vers->next) { 281 if (tblflag) { 282 f_print(fout, 283 "extern struct rpcgen_table %s_%s_table[];\n", 284 locase(def->def_name), vers->vers_num); 285 f_print(fout, 286 "extern int %s_%s_nproc;\n", 287 locase(def->def_name), vers->vers_num); 288 } 289 puldefine(vers->vers_name, vers->vers_num, VERSION); 290 291 for (proc = vers->procs; proc != NULL; 292 proc = proc->next) { 293 if (!define_printed(proc, 294 def->def.pr.versions)) { 295 puldefine(proc->proc_name, 296 proc->proc_num, PROCEDURE); 297 } 298 f_print(fout, "extern "); 299 pprocdef(proc, vers, "CLIENT *", 0); 300 f_print(fout, "extern "); 301 pprocdef(proc, vers, "struct svc_req *", 1); 302 } 303 pfreeprocdef(def->def_name, vers->vers_num); 304 } 305 } 306 307 void 308 pprocdef(proc_list *proc, version_list *vp, char *addargtype, int server_p) 309 { 310 if (mtflag) { 311 /* Print MT style stubs */ 312 if (server_p) 313 f_print(fout, "bool_t "); 314 else 315 f_print(fout, "enum clnt_stat "); 316 } else { 317 ptype(proc->res_prefix, proc->res_type, 1); 318 f_print(fout, "* "); 319 } 320 if (server_p) 321 pvname_svc(proc->proc_name, vp->vers_num); 322 else 323 pvname(proc->proc_name, vp->vers_num); 324 325 parglist(proc, addargtype); 326 } 327 328 /* print out argument list of procedure */ 329 static void 330 parglist(proc_list *proc, char *addargtype) 331 { 332 decl_list *dl; 333 int oneway = streq(proc->res_type, "oneway"); 334 335 f_print(fout, "("); 336 if (proc->arg_num < 2 && newstyle && 337 streq(proc->args.decls->decl.type, "void")) { 338 /* 0 argument in new style: do nothing */ 339 /* EMPTY */ 340 } else { 341 for (dl = proc->args.decls; dl != NULL; dl = dl->next) { 342 ptype(dl->decl.prefix, dl->decl.type, 1); 343 if (!newstyle || (dl->decl.rel == REL_POINTER)) 344 f_print(fout, "*"); 345 /* old style passes by reference */ 346 f_print(fout, ", "); 347 } 348 } 349 350 if (mtflag && !oneway) { 351 ptype(proc->res_prefix, proc->res_type, 1); 352 f_print(fout, "*, "); 353 } 354 355 f_print(fout, "%s);\n", addargtype); 356 } 357 358 static void 359 penumdef(definition *def) 360 { 361 char *name = def->def_name; 362 enumval_list *l; 363 char *last = NULL; 364 int count = 0; 365 366 f_print(fout, "enum %s {\n", name); 367 for (l = def->def.en.vals; l != NULL; l = l->next) { 368 f_print(fout, "\t%s", l->name); 369 if (l->assignment) { 370 f_print(fout, " = %s", l->assignment); 371 last = l->assignment; 372 count = 1; 373 } else { 374 if (last == NULL) 375 f_print(fout, " = %d", count++); 376 else 377 f_print(fout, " = %s + %d", last, count++); 378 } 379 if (l->next) 380 f_print(fout, ",\n"); 381 else 382 f_print(fout, "\n"); 383 } 384 f_print(fout, "};\n"); 385 f_print(fout, "typedef enum %s %s;\n", name, name); 386 } 387 388 static void 389 ptypedef(definition *def) 390 { 391 char *name = def->def_name; 392 char *old = def->def.ty.old_type; 393 char prefix[8]; /* enough to contain "struct ", including NUL */ 394 relation rel = def->def.ty.rel; 395 396 397 if (!streq(name, old)) { 398 if (streq(old, "string")) { 399 old = "char"; 400 rel = REL_POINTER; 401 } else if (streq(old, "opaque")) { 402 old = "char"; 403 } else if (streq(old, "bool")) { 404 old = "bool_t"; 405 } 406 if (undefined2(old, name) && def->def.ty.old_prefix) 407 (void) snprintf(prefix, sizeof (prefix), "%s ", 408 def->def.ty.old_prefix); 409 else 410 prefix[0] = 0; 411 f_print(fout, "typedef "); 412 switch (rel) { 413 case REL_ARRAY: 414 f_print(fout, "struct {\n"); 415 f_print(fout, "\tu_int %s_len;\n", name); 416 f_print(fout, "\t%s%s *%s_val;\n", prefix, old, name); 417 f_print(fout, "} %s", name); 418 break; 419 case REL_POINTER: 420 f_print(fout, "%s%s *%s", prefix, old, name); 421 break; 422 case REL_VECTOR: 423 f_print(fout, "%s%s %s[%s]", prefix, old, name, 424 def->def.ty.array_max); 425 break; 426 case REL_ALIAS: 427 f_print(fout, "%s%s %s", prefix, old, name); 428 break; 429 } 430 f_print(fout, ";\n"); 431 } 432 } 433 434 void 435 pdeclaration(char *name, declaration *dec, int tab, char *separator) 436 { 437 char buf[8]; /* enough to hold "struct ", include NUL */ 438 char *prefix; 439 char *type; 440 441 if (streq(dec->type, "void")) 442 return; 443 tabify(fout, tab); 444 if (streq(dec->type, name) && !dec->prefix) 445 f_print(fout, "struct "); 446 if (streq(dec->type, "string")) { 447 f_print(fout, "char *%s", dec->name); 448 } else { 449 prefix = ""; 450 if (streq(dec->type, "bool")) { 451 type = "bool_t"; 452 } else if (streq(dec->type, "opaque")) { 453 type = "char"; 454 } else { 455 if (dec->prefix) { 456 (void) snprintf(buf, sizeof (buf), 457 "%s ", dec->prefix); 458 prefix = buf; 459 } 460 type = dec->type; 461 } 462 switch (dec->rel) { 463 case REL_ALIAS: 464 f_print(fout, "%s%s %s", prefix, type, dec->name); 465 break; 466 case REL_VECTOR: 467 f_print(fout, "%s%s %s[%s]", prefix, type, dec->name, 468 dec->array_max); 469 break; 470 case REL_POINTER: 471 f_print(fout, "%s%s *%s", prefix, type, dec->name); 472 break; 473 case REL_ARRAY: 474 f_print(fout, "struct {\n"); 475 tabify(fout, tab); 476 f_print(fout, "\tu_int %s_len;\n", dec->name); 477 tabify(fout, tab); 478 f_print(fout, 479 "\t%s%s *%s_val;\n", prefix, type, dec->name); 480 tabify(fout, tab); 481 f_print(fout, "} %s", dec->name); 482 break; 483 } 484 } 485 /* LINTED variable format */ 486 f_print(fout, separator); 487 } 488 489 static uint_t 490 undefined2(char *type, char *stop) 491 { 492 list *l; 493 definition *def; 494 495 for (l = defined; l != NULL; l = l->next) { 496 def = (definition *) l->val; 497 if (def->def_kind != DEF_PROGRAM) { 498 if (streq(def->def_name, stop)) 499 return (1); 500 if (streq(def->def_name, type)) 501 return (0); 502 } 503 } 504 return (1); 505 }