| /* |
| * From: @(#)rpc_util.c 1.11 89/02/22 |
| * |
| * Copyright (c) 2010, Oracle America, Inc. |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions are |
| * met: |
| * |
| * * Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * * Redistributions in binary form must reproduce the above |
| * copyright notice, this list of conditions and the following |
| * disclaimer in the documentation and/or other materials |
| * provided with the distribution. |
| * * Neither the name of the "Oracle America, Inc." nor the names of its |
| * contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, |
| * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE |
| * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
| * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, |
| * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
| * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| /* |
| * rpc_util.c, Utility routines for the RPC protocol compiler |
| */ |
| #include <stdio.h> |
| #include <ctype.h> |
| #include <string.h> |
| #include <unistd.h> |
| #include "rpc_scan.h" |
| #include "rpc_parse.h" |
| #include "rpc_util.h" |
| #include "proto.h" |
| |
| #define ARGEXT "argument" |
| |
| char curline[MAXLINESIZE]; /* current read line */ |
| const char *where = curline; /* current point in line */ |
| int linenum = 0; /* current line number */ |
| |
| const char *infilename; /* input filename */ |
| |
| #define NFILES 7 |
| const char *outfiles[NFILES]; /* output file names */ |
| int nfiles; |
| |
| FILE *fout; /* file pointer of current output */ |
| FILE *fin; /* file pointer of current input */ |
| |
| list *defined; /* list of defined things */ |
| |
| static int findit (const definition * def, const char *type); |
| static const char *fixit (const char *type, const char *orig); |
| static int typedefed (const definition * def, const char *type); |
| static const char *toktostr (tok_kind kind); |
| static void printbuf (void); |
| static void printwhere (void); |
| |
| /* |
| * Reinitialize the world |
| */ |
| void |
| reinitialize (void) |
| { |
| memset (curline, 0, MAXLINESIZE); |
| where = curline; |
| linenum = 0; |
| defined = NULL; |
| } |
| |
| /* |
| * string equality |
| */ |
| int |
| streq (const char *a, const char *b) |
| { |
| return strcmp (a, b) == 0; |
| } |
| |
| /* |
| * find a value in a list |
| */ |
| definition * |
| findval (list *lst, const char *val, |
| int (*cmp) (const definition *, const char *)) |
| { |
| |
| for (; lst != NULL; lst = lst->next) |
| { |
| if (cmp (lst->val, val)) |
| { |
| return lst->val; |
| } |
| } |
| return NULL; |
| } |
| |
| /* |
| * store a value in a list |
| */ |
| void |
| storeval (list **lstp, definition *val) |
| { |
| list **l; |
| list *lst; |
| |
| |
| for (l = lstp; *l != NULL; l = (list **) & (*l)->next); |
| lst = ALLOC (list); |
| lst->val = val; |
| lst->next = NULL; |
| *l = lst; |
| } |
| |
| static int |
| findit (const definition * def, const char *type) |
| { |
| return streq (def->def_name, type); |
| } |
| |
| static const char * |
| fixit (const char *type, const char *orig) |
| { |
| definition *def; |
| |
| def = findval (defined, type, findit); |
| if (def == NULL || def->def_kind != DEF_TYPEDEF) |
| { |
| return orig; |
| } |
| switch (def->def.ty.rel) |
| { |
| case REL_VECTOR: |
| if (streq (def->def.ty.old_type, "opaque")) |
| return ("char"); |
| else |
| return (def->def.ty.old_type); |
| case REL_ALIAS: |
| return (fixit (def->def.ty.old_type, orig)); |
| default: |
| return orig; |
| } |
| } |
| |
| const char * |
| fixtype (const char *type) |
| { |
| return fixit (type, type); |
| } |
| |
| const char * |
| stringfix (const char *type) |
| { |
| if (streq (type, "string")) |
| { |
| return "wrapstring"; |
| } |
| else |
| { |
| return type; |
| } |
| } |
| |
| void |
| ptype (const char *prefix, const char *type, int follow) |
| { |
| if (prefix != NULL) |
| { |
| if (streq (prefix, "enum")) |
| { |
| f_print (fout, "enum "); |
| } |
| else |
| { |
| f_print (fout, "struct "); |
| } |
| } |
| if (streq (type, "bool")) |
| { |
| f_print (fout, "bool_t "); |
| } |
| else if (streq (type, "string")) |
| { |
| f_print (fout, "char *"); |
| } |
| else |
| { |
| f_print (fout, "%s ", follow ? fixtype (type) : type); |
| } |
| } |
| |
| static int |
| typedefed (const definition * def, const char *type) |
| { |
| if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL) |
| { |
| return 0; |
| } |
| else |
| { |
| return streq (def->def_name, type); |
| } |
| } |
| |
| int |
| isvectordef (const char *type, relation rel) |
| { |
| definition *def; |
| |
| for (;;) |
| { |
| switch (rel) |
| { |
| case REL_VECTOR: |
| return !streq (type, "string"); |
| case REL_ARRAY: |
| return 0; |
| case REL_POINTER: |
| return 0; |
| case REL_ALIAS: |
| def = findval (defined, type, typedefed); |
| if (def == NULL) |
| { |
| return 0; |
| } |
| type = def->def.ty.old_type; |
| rel = def->def.ty.rel; |
| } |
| } |
| } |
| |
| char * |
| locase (const char *str) |
| { |
| char c; |
| static char buf[100]; |
| char *p = buf; |
| |
| while ((c = *str++) != 0) |
| { |
| *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c; |
| } |
| *p = 0; |
| return buf; |
| } |
| |
| void |
| pvname_svc (const char *pname, const char *vnum) |
| { |
| f_print (fout, "%s_%s_svc", locase (pname), vnum); |
| } |
| |
| void |
| pvname (const char *pname, const char *vnum) |
| { |
| f_print (fout, "%s_%s", locase (pname), vnum); |
| } |
| |
| /* |
| * print a useful (?) error message, and then die |
| */ |
| void |
| error (const char *msg) |
| { |
| printwhere (); |
| f_print (stderr, "%s, line %d: ", infilename, linenum); |
| f_print (stderr, "%s\n", msg); |
| crash (); |
| } |
| |
| /* |
| * Something went wrong, unlink any files that we may have created and then |
| * die. |
| */ |
| void |
| crash (void) |
| { |
| int i; |
| |
| for (i = 0; i < nfiles; i++) |
| { |
| unlink (outfiles[i]); |
| } |
| exit (1); |
| } |
| |
| void |
| record_open (const char *file) |
| { |
| if (nfiles < NFILES) |
| { |
| outfiles[nfiles++] = file; |
| } |
| else |
| { |
| f_print (stderr, "too many files!\n"); |
| crash (); |
| } |
| } |
| |
| static char expectbuf[100]; |
| |
| /* |
| * error, token encountered was not the expected one |
| */ |
| void |
| expected1 (tok_kind exp1) |
| { |
| s_print (expectbuf, "expected '%s'", |
| toktostr (exp1)); |
| error (expectbuf); |
| } |
| |
| /* |
| * error, token encountered was not one of two expected ones |
| */ |
| void |
| expected2 (tok_kind exp1, tok_kind exp2) |
| { |
| s_print (expectbuf, "expected '%s' or '%s'", |
| toktostr (exp1), |
| toktostr (exp2)); |
| error (expectbuf); |
| } |
| |
| /* |
| * error, token encountered was not one of 3 expected ones |
| */ |
| void |
| expected3 (tok_kind exp1, tok_kind exp2, tok_kind exp3) |
| { |
| s_print (expectbuf, "expected '%s', '%s' or '%s'", |
| toktostr (exp1), |
| toktostr (exp2), |
| toktostr (exp3)); |
| error (expectbuf); |
| } |
| |
| void |
| tabify (FILE * f, int tab) |
| { |
| while (tab--) |
| { |
| (void) fputc ('\t', f); |
| } |
| } |
| |
| |
| static const token tokstrings[] = |
| { |
| {TOK_IDENT, "identifier"}, |
| {TOK_CONST, "const"}, |
| {TOK_RPAREN, ")"}, |
| {TOK_LPAREN, "("}, |
| {TOK_RBRACE, "}"}, |
| {TOK_LBRACE, "{"}, |
| {TOK_LBRACKET, "["}, |
| {TOK_RBRACKET, "]"}, |
| {TOK_STAR, "*"}, |
| {TOK_COMMA, ","}, |
| {TOK_EQUAL, "="}, |
| {TOK_COLON, ":"}, |
| {TOK_SEMICOLON, ";"}, |
| {TOK_UNION, "union"}, |
| {TOK_STRUCT, "struct"}, |
| {TOK_SWITCH, "switch"}, |
| {TOK_CASE, "case"}, |
| {TOK_DEFAULT, "default"}, |
| {TOK_ENUM, "enum"}, |
| {TOK_TYPEDEF, "typedef"}, |
| {TOK_INT, "int"}, |
| {TOK_SHORT, "short"}, |
| {TOK_LONG, "long"}, |
| {TOK_UNSIGNED, "unsigned"}, |
| {TOK_DOUBLE, "double"}, |
| {TOK_FLOAT, "float"}, |
| {TOK_CHAR, "char"}, |
| {TOK_STRING, "string"}, |
| {TOK_OPAQUE, "opaque"}, |
| {TOK_BOOL, "bool"}, |
| {TOK_VOID, "void"}, |
| {TOK_PROGRAM, "program"}, |
| {TOK_VERSION, "version"}, |
| {TOK_EOF, "??????"} |
| }; |
| |
| static const char * |
| toktostr (tok_kind kind) |
| { |
| const token *sp; |
| |
| for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++); |
| return sp->str; |
| } |
| |
| static void |
| printbuf (void) |
| { |
| char c; |
| int i; |
| int cnt; |
| |
| #define TABSIZE 4 |
| |
| for (i = 0; (c = curline[i]) != 0; i++) |
| { |
| if (c == '\t') |
| { |
| cnt = 8 - (i % TABSIZE); |
| c = ' '; |
| } |
| else |
| { |
| cnt = 1; |
| } |
| while (cnt--) |
| { |
| (void) fputc (c, stderr); |
| } |
| } |
| } |
| |
| static void |
| printwhere (void) |
| { |
| int i; |
| char c; |
| int cnt; |
| |
| printbuf (); |
| for (i = 0; i < where - curline; i++) |
| { |
| c = curline[i]; |
| if (c == '\t') |
| { |
| cnt = 8 - (i % TABSIZE); |
| } |
| else |
| { |
| cnt = 1; |
| } |
| while (cnt--) |
| { |
| (void) fputc ('^', stderr); |
| } |
| } |
| (void) fputc ('\n', stderr); |
| } |
| |
| char * |
| make_argname (const char *pname, const char *vname) |
| { |
| char *name; |
| |
| name = malloc (strlen (pname) + strlen (vname) + strlen (ARGEXT) + 3); |
| if (!name) |
| { |
| fprintf (stderr, "failed in malloc"); |
| exit (1); |
| } |
| sprintf (name, "%s_%s_%s", locase (pname), vname, ARGEXT); |
| return name; |
| } |
| |
| bas_type *typ_list_h; |
| bas_type *typ_list_t; |
| |
| void |
| add_type (int len, const char *type) |
| { |
| bas_type *ptr; |
| |
| |
| if ((ptr = malloc (sizeof (bas_type))) == NULL) |
| { |
| fprintf (stderr, "failed in malloc"); |
| exit (1); |
| } |
| |
| ptr->name = type; |
| ptr->length = len; |
| ptr->next = NULL; |
| if (typ_list_t == NULL) |
| { |
| |
| typ_list_t = ptr; |
| typ_list_h = ptr; |
| } |
| else |
| { |
| |
| typ_list_t->next = ptr; |
| typ_list_t = ptr; |
| } |
| |
| } |
| |
| |
| bas_type * |
| find_type (const char *type) |
| { |
| bas_type *ptr; |
| |
| ptr = typ_list_h; |
| |
| |
| while (ptr != NULL) |
| { |
| if (strcmp (ptr->name, type) == 0) |
| return ptr; |
| else |
| ptr = ptr->next; |
| }; |
| return NULL; |
| } |