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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 /* 30 * University Copyright- Copyright (c) 1982, 1986, 1988 31 * The Regents of the University of California 32 * All Rights Reserved 33 * 34 * University Acknowledgment- Portions of this document are derived from 35 * software developed by the University of California, Berkeley, and its 36 * contributors. 37 */ 38 39 #pragma ident "%Z%%M% %I% %E% SMI" 40 41 /* 42 * rpc_util.c, Utility routines for the RPC protocol compiler 43 */ 44 #include <stdio.h> 45 #include <stdlib.h> 46 #include <unistd.h> 47 #include <ctype.h> 48 #include <string.h> 49 #include "rpc_scan.h" 50 #include "rpc_parse.h" 51 #include "rpc_util.h" 52 53 extern void crash(void); 54 55 static void printwhere(void); 56 57 #define ARGEXT "argument" 58 59 char curline[MAXLINESIZE]; /* current read line */ 60 char *where = curline; /* current point in line */ 61 int linenum = 0; /* current line number */ 62 63 char *infilename; /* input filename */ 64 65 #define NFILES 15 66 char *outfiles[NFILES]; /* output file names */ 67 int nfiles; 68 69 FILE *fout; /* file pointer of current output */ 70 FILE *fin; /* file pointer of current input */ 71 72 list *defined; /* list of defined things */ 73 74 /* 75 * Reinitialize the world 76 */ 77 void 78 reinitialize(void) 79 { 80 (void) memset(curline, 0, MAXLINESIZE); 81 where = curline; 82 linenum = 0; 83 defined = NULL; 84 } 85 86 /* 87 * string equality 88 */ 89 int 90 streq(char *a, char *b) 91 { 92 return (strcmp(a, b) == 0); 93 } 94 95 /* 96 * find a value in a list 97 */ 98 definition * 99 findval(list *lst, char *val, int (*cmp)()) 100 { 101 for (; lst != NULL; lst = lst->next) { 102 if ((*cmp) (lst->val, val)) 103 return (lst->val); 104 } 105 return (NULL); 106 } 107 108 /* 109 * store a value in a list 110 */ 111 void 112 storeval(list **lstp, definition *val) 113 { 114 list **l; 115 list *lst; 116 117 for (l = lstp; *l != NULL; l = (list **)&(*l)->next); 118 lst = calloc(1, sizeof (list)); 119 lst->val = val; 120 lst->next = NULL; 121 *l = lst; 122 } 123 124 static int 125 findit(definition *def, char *type) 126 { 127 return (streq(def->def_name, type)); 128 } 129 130 static char * 131 fixit(char *type, char *orig) 132 { 133 definition *def; 134 135 def = (definition *)FINDVAL(defined, type, findit); 136 if (def == NULL || def->def_kind != DEF_TYPEDEF) 137 return (orig); 138 switch (def->def.ty.rel) { 139 case REL_VECTOR: 140 if (streq(def->def.ty.old_type, "opaque")) 141 return ("char"); 142 return (def->def.ty.old_type); 143 144 case REL_ALIAS: 145 return (fixit(def->def.ty.old_type, orig)); 146 default: 147 return (orig); 148 } 149 } 150 151 char * 152 fixtype(char *type) 153 { 154 return (fixit(type, type)); 155 } 156 157 char * 158 stringfix(char *type) 159 { 160 if (streq(type, "string")) 161 return ("wrapstring"); 162 return (type); 163 } 164 165 void 166 ptype(char *prefix, char *type, int follow) 167 { 168 if (prefix != NULL) { 169 if (streq(prefix, "enum")) { 170 f_print(fout, "enum "); 171 } else { 172 f_print(fout, "struct "); 173 } 174 } 175 if (streq(type, "bool")) { 176 f_print(fout, "bool_t "); 177 } else if (streq(type, "string")) { 178 f_print(fout, "char *"); 179 } else if (streq(type, "oneway")) { 180 f_print(fout, "void "); 181 } else { 182 f_print(fout, "%s ", follow ? fixtype(type) : type); 183 } 184 } 185 186 static int 187 typedefed(definition *def, char *type) 188 { 189 if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) 190 return (0); 191 return (streq(def->def_name, type)); 192 } 193 194 int 195 isvectordef(char *type, relation rel) 196 { 197 definition *def; 198 199 for (;;) { 200 switch (rel) { 201 case REL_VECTOR: 202 return (!streq(type, "string")); 203 case REL_ARRAY: 204 return (0); 205 case REL_POINTER: 206 return (0); 207 case REL_ALIAS: 208 def = (definition *)FINDVAL(defined, type, typedefed); 209 if (def == NULL) 210 return (0); 211 type = def->def.ty.old_type; 212 rel = def->def.ty.rel; 213 } 214 } 215 } 216 217 char * 218 locase(char *str) 219 { 220 char c; 221 static char buf[100]; 222 char *p = buf; 223 224 while (c = *str++) 225 *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; 226 *p = 0; 227 return (buf); 228 } 229 230 void 231 pvname_svc(char *pname, char *vnum) 232 { 233 f_print(fout, "%s_%s_svc", locase(pname), vnum); 234 } 235 236 void 237 pvname(char *pname, char *vnum) 238 { 239 f_print(fout, "%s_%s", locase(pname), vnum); 240 } 241 242 /* 243 * print a useful (?) error message, and then die 244 */ 245 void 246 error(char *msg) 247 { 248 printwhere(); 249 f_print(stderr, "%s, line %d: ", infilename, linenum); 250 f_print(stderr, "%s\n", msg); 251 crash(); 252 } 253 254 /* 255 * Something went wrong, unlink any files that we may have created and then 256 * die. 257 */ 258 void 259 crash(void) 260 { 261 int i; 262 263 for (i = 0; i < nfiles; i++) 264 (void) unlink(outfiles[i]); 265 exit(1); 266 } 267 268 void 269 record_open(char *file) 270 { 271 if (nfiles < NFILES) { 272 outfiles[nfiles++] = file; 273 return; 274 } 275 f_print(stderr, "too many files!\n"); 276 crash(); 277 } 278 279 static char expectbuf[100]; 280 static char *toktostr(); 281 282 /* 283 * error, token encountered was not the expected one 284 */ 285 void 286 expected1(tok_kind exp1) 287 { 288 (void) snprintf(expectbuf, 289 sizeof (expectbuf), "expected '%s'", toktostr(exp1)); 290 error(expectbuf); 291 } 292 293 /* 294 * error, token encountered was not one of two expected ones 295 */ 296 void 297 expected2(tok_kind exp1, tok_kind exp2) 298 { 299 (void) snprintf(expectbuf, 300 sizeof (expectbuf), "expected '%s' or '%s'", toktostr(exp1), 301 toktostr(exp2)); 302 error(expectbuf); 303 } 304 305 /* 306 * error, token encountered was not one of 3 expected ones 307 */ 308 void 309 expected3(tok_kind exp1, tok_kind exp2, tok_kind exp3) 310 { 311 (void) snprintf(expectbuf, 312 sizeof (expectbuf), "expected '%s', '%s' or '%s'", 313 toktostr(exp1), toktostr(exp2), toktostr(exp3)); 314 error(expectbuf); 315 } 316 317 void 318 tabify(FILE *f, int tab) 319 { 320 while (tab--) 321 (void) fputc('\t', f); 322 } 323 324 static token tokstrings[] = { 325 {TOK_IDENT, "identifier"}, 326 {TOK_CONST, "const"}, 327 {TOK_RPAREN, ")"}, 328 {TOK_LPAREN, "("}, 329 {TOK_RBRACE, "}"}, 330 {TOK_LBRACE, "{"}, 331 {TOK_LBRACKET, "["}, 332 {TOK_RBRACKET, "]"}, 333 {TOK_STAR, "*"}, 334 {TOK_COMMA, ","}, 335 {TOK_EQUAL, "="}, 336 {TOK_COLON, ":"}, 337 {TOK_SEMICOLON, ";"}, 338 {TOK_UNION, "union"}, 339 {TOK_STRUCT, "struct"}, 340 {TOK_SWITCH, "switch"}, 341 {TOK_CASE, "case"}, 342 {TOK_DEFAULT, "default"}, 343 {TOK_ENUM, "enum"}, 344 {TOK_TYPEDEF, "typedef"}, 345 {TOK_INT, "int"}, 346 {TOK_SHORT, "short"}, 347 {TOK_LONG, "long"}, 348 {TOK_UNSIGNED, "unsigned"}, 349 {TOK_DOUBLE, "double"}, 350 {TOK_FLOAT, "float"}, 351 {TOK_CHAR, "char"}, 352 {TOK_STRING, "string"}, 353 {TOK_OPAQUE, "opaque"}, 354 {TOK_BOOL, "bool"}, 355 {TOK_VOID, "void"}, 356 {TOK_PROGRAM, "program"}, 357 {TOK_VERSION, "version"}, 358 {TOK_EOF, "??????"} 359 }; 360 361 static char * 362 toktostr(tok_kind kind) 363 { 364 token *sp; 365 366 for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++); 367 return (sp->str); 368 } 369 370 static void 371 printbuf(void) 372 { 373 char c; 374 int i; 375 int cnt; 376 377 #define TABSIZE 4 378 379 for (i = 0; (c = curline[i]) != '\0'; i++) { 380 if (c == '\t') { 381 cnt = 8 - (i % TABSIZE); 382 c = ' '; 383 } else { 384 cnt = 1; 385 } 386 while (cnt--) 387 (void) fputc(c, stderr); 388 } 389 } 390 391 static void 392 printwhere(void) 393 { 394 int i; 395 char c; 396 int cnt; 397 398 printbuf(); 399 for (i = 0; i < where - curline; i++) { 400 c = curline[i]; 401 if (c == '\t') { 402 cnt = 8 - (i % TABSIZE); 403 } else { 404 cnt = 1; 405 } 406 while (cnt--) 407 (void) fputc('^', stderr); 408 } 409 (void) fputc('\n', stderr); 410 } 411 412 char * 413 make_argname(char *pname, char *vname) 414 { 415 char *name; 416 size_t nlen; 417 418 nlen = strlen(pname) + strlen(vname) + strlen(ARGEXT) + 3; 419 name = malloc(nlen); 420 if (name == NULL) { 421 (void) fprintf(stderr, "failed in malloc"); 422 exit(1); 423 } 424 (void) snprintf(name, nlen, "%s_%s_%s", locase(pname), vname, ARGEXT); 425 return (name); 426 } 427 428 bas_type *typ_list_h; 429 bas_type *typ_list_t; 430 431 void 432 add_type(int len, char *type) 433 { 434 bas_type *ptr; 435 436 if ((ptr = malloc(sizeof (bas_type))) == NULL) { 437 (void) fprintf(stderr, "failed in malloc"); 438 exit(1); 439 } 440 441 ptr->name = type; 442 ptr->length = len; 443 ptr->next = NULL; 444 if (typ_list_t == NULL) { 445 typ_list_t = ptr; 446 typ_list_h = ptr; 447 } else { 448 typ_list_t->next = ptr; 449 typ_list_t = ptr; 450 } 451 } 452 453 454 bas_type * 455 find_type(char *type) 456 { 457 bas_type *ptr; 458 459 ptr = typ_list_h; 460 while (ptr != NULL) { 461 if (strcmp(ptr->name, type) == 0) 462 return (ptr); 463 ptr = ptr->next; 464 } 465 return (NULL); 466 } 467