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