1*90a10bbbSdholland /* $NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 dholland Exp $ */
28f0abce1Sglass /*
38f0abce1Sglass * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
48f0abce1Sglass * unrestricted use provided that this legend is included on all tape
58f0abce1Sglass * media and as a part of the software program in whole or part. Users
68f0abce1Sglass * may copy or modify Sun RPC without charge, but are not authorized
78f0abce1Sglass * to license or distribute it to anyone else except as part of a product or
871a0fb45Spk * program developed by the user or with the express written consent of
971a0fb45Spk * Sun Microsystems, Inc.
108f0abce1Sglass *
118f0abce1Sglass * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
128f0abce1Sglass * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
138f0abce1Sglass * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
148f0abce1Sglass *
158f0abce1Sglass * Sun RPC is provided with no support and without any obligation on the
168f0abce1Sglass * part of Sun Microsystems, Inc. to assist in its use, correction,
178f0abce1Sglass * modification or enhancement.
188f0abce1Sglass *
198f0abce1Sglass * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
208f0abce1Sglass * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
218f0abce1Sglass * OR ANY PART THEREOF.
228f0abce1Sglass *
238f0abce1Sglass * In no event will Sun Microsystems, Inc. be liable for any lost revenue
248f0abce1Sglass * or profits or other special, indirect and consequential damages, even if
258f0abce1Sglass * Sun has been advised of the possibility of such damages.
268f0abce1Sglass *
278f0abce1Sglass * Sun Microsystems, Inc.
288f0abce1Sglass * 2550 Garcia Avenue
298f0abce1Sglass * Mountain View, California 94043
308f0abce1Sglass */
3171a0fb45Spk
32b2f78261Sjmc #if HAVE_NBTOOL_CONFIG_H
33b2f78261Sjmc #include "nbtool_config.h"
34b2f78261Sjmc #endif
35b2f78261Sjmc
3693579481Schristos #include <sys/cdefs.h>
3776834aefStv #if defined(__RCSID) && !defined(lint)
3893579481Schristos #if 0
3971a0fb45Spk static char sccsid[] = "@(#)rpc_scan.c 1.11 89/02/22 (C) 1987 SMI";
4093579481Schristos #else
41*90a10bbbSdholland __RCSID("$NetBSD: rpc_scan.c,v 1.15 2015/05/09 23:28:43 dholland Exp $");
4293579481Schristos #endif
438f0abce1Sglass #endif
448f0abce1Sglass
458f0abce1Sglass /*
468f0abce1Sglass * rpc_scan.c, Scanner for the RPC protocol compiler
478f0abce1Sglass * Copyright (C) 1987, Sun Microsystems, Inc.
488f0abce1Sglass */
4971a0fb45Spk #include <stdlib.h>
508f0abce1Sglass #include <stdio.h>
518f0abce1Sglass #include <ctype.h>
5271a0fb45Spk #include <string.h>
538f0abce1Sglass #include "rpc_scan.h"
5471a0fb45Spk #include "rpc_parse.h"
558f0abce1Sglass #include "rpc_util.h"
568f0abce1Sglass
578f0abce1Sglass #define startcomment(where) (where[0] == '/' && where[1] == '*')
588f0abce1Sglass #define endcomment(where) (where[-1] == '*' && where[0] == '/')
598f0abce1Sglass
600213edf0Schristos static void unget_token(token *);
610213edf0Schristos static void findstrconst(char **, const char **);
620213edf0Schristos static void findchrconst(char **, const char **);
630213edf0Schristos static void findconst(char **, const char **);
640213edf0Schristos static void findkind(char **, token *);
650213edf0Schristos static int cppline(const char *);
660213edf0Schristos static int directive(const char *);
670213edf0Schristos static void printdirective(const char *);
680213edf0Schristos static void docppline(char *, int *, const char **);
6993579481Schristos
708f0abce1Sglass static int pushed = 0; /* is a token pushed */
718f0abce1Sglass static token lasttok; /* last token, if pushed */
728f0abce1Sglass
738f0abce1Sglass /*
748f0abce1Sglass * scan expecting 1 given token
758f0abce1Sglass */
768f0abce1Sglass void
scan(tok_kind expect,token * tokp)77e9067f11Sdholland scan(tok_kind expect, token *tokp)
788f0abce1Sglass {
798f0abce1Sglass get_token(tokp);
808f0abce1Sglass if (tokp->kind != expect) {
818f0abce1Sglass expected1(expect);
828f0abce1Sglass }
838f0abce1Sglass }
848f0abce1Sglass /*
8571a0fb45Spk * scan expecting any of the 2 given tokens
868f0abce1Sglass */
878f0abce1Sglass void
scan2(tok_kind expect1,tok_kind expect2,token * tokp)88e9067f11Sdholland scan2(tok_kind expect1, tok_kind expect2, token *tokp)
898f0abce1Sglass {
908f0abce1Sglass get_token(tokp);
918f0abce1Sglass if (tokp->kind != expect1 && tokp->kind != expect2) {
928f0abce1Sglass expected2(expect1, expect2);
938f0abce1Sglass }
948f0abce1Sglass }
958f0abce1Sglass /*
9671a0fb45Spk * scan expecting any of the 3 given token
978f0abce1Sglass */
988f0abce1Sglass void
scan3(tok_kind expect1,tok_kind expect2,tok_kind expect3,token * tokp)99e9067f11Sdholland scan3(tok_kind expect1, tok_kind expect2, tok_kind expect3, token *tokp)
1008f0abce1Sglass {
1018f0abce1Sglass get_token(tokp);
1028f0abce1Sglass if (tokp->kind != expect1 && tokp->kind != expect2
1038f0abce1Sglass && tokp->kind != expect3) {
1048f0abce1Sglass expected3(expect1, expect2, expect3);
1058f0abce1Sglass }
1068f0abce1Sglass }
1078f0abce1Sglass /*
1088f0abce1Sglass * scan expecting a constant, possibly symbolic
1098f0abce1Sglass */
1108f0abce1Sglass void
scan_num(token * tokp)111e9067f11Sdholland scan_num(token *tokp)
1128f0abce1Sglass {
1138f0abce1Sglass get_token(tokp);
1148f0abce1Sglass switch (tokp->kind) {
1158f0abce1Sglass case TOK_IDENT:
1168f0abce1Sglass break;
1178f0abce1Sglass default:
118ceecfabaSdholland error("Expected constant or identifier");
1198f0abce1Sglass }
1208f0abce1Sglass }
1218f0abce1Sglass /*
1228f0abce1Sglass * Peek at the next token
1238f0abce1Sglass */
1248f0abce1Sglass void
peek(token * tokp)125e9067f11Sdholland peek(token *tokp)
1268f0abce1Sglass {
1278f0abce1Sglass get_token(tokp);
1288f0abce1Sglass unget_token(tokp);
1298f0abce1Sglass }
1308f0abce1Sglass /*
1318f0abce1Sglass * Peek at the next token and scan it if it matches what you expect
1328f0abce1Sglass */
1338f0abce1Sglass int
peekscan(tok_kind expect,token * tokp)134e9067f11Sdholland peekscan(tok_kind expect, token *tokp)
1358f0abce1Sglass {
1368f0abce1Sglass peek(tokp);
1378f0abce1Sglass if (tokp->kind == expect) {
1388f0abce1Sglass get_token(tokp);
1398f0abce1Sglass return (1);
1408f0abce1Sglass }
1418f0abce1Sglass return (0);
1428f0abce1Sglass }
1438f0abce1Sglass /*
1448f0abce1Sglass * Get the next token, printing out any directive that are encountered.
1458f0abce1Sglass */
1468f0abce1Sglass void
get_token(token * tokp)147e9067f11Sdholland get_token(token *tokp)
1488f0abce1Sglass {
1498f0abce1Sglass int commenting;
1508f0abce1Sglass
1518f0abce1Sglass if (pushed) {
1528f0abce1Sglass pushed = 0;
1538f0abce1Sglass *tokp = lasttok;
1548f0abce1Sglass return;
1558f0abce1Sglass }
1568f0abce1Sglass commenting = 0;
1578f0abce1Sglass for (;;) {
1588f0abce1Sglass if (*where == 0) {
1598f0abce1Sglass for (;;) {
1608f0abce1Sglass if (!fgets(curline, MAXLINESIZE, fin)) {
1618f0abce1Sglass tokp->kind = TOK_EOF;
1628f0abce1Sglass *where = 0;
1638f0abce1Sglass return;
1648f0abce1Sglass }
1658f0abce1Sglass linenum++;
1668f0abce1Sglass if (commenting) {
1678f0abce1Sglass break;
16899071d1bSlukem } else
16999071d1bSlukem if (cppline(curline)) {
1708f0abce1Sglass docppline(curline, &linenum,
1718f0abce1Sglass &infilename);
17299071d1bSlukem } else
17399071d1bSlukem if (directive(curline)) {
1748f0abce1Sglass printdirective(curline);
1758f0abce1Sglass } else {
1768f0abce1Sglass break;
1778f0abce1Sglass }
1788f0abce1Sglass }
1798f0abce1Sglass where = curline;
18099071d1bSlukem } else
181e4ac7024Schristos if (isspace((unsigned char)*where)) {
182e4ac7024Schristos while (isspace((unsigned char)*where)) {
1838f0abce1Sglass where++; /* eat */
1848f0abce1Sglass }
18599071d1bSlukem } else
18699071d1bSlukem if (commenting) {
18771a0fb45Spk for (where++; *where; where++) {
1888f0abce1Sglass if (endcomment(where)) {
1898f0abce1Sglass where++;
1908f0abce1Sglass commenting--;
19171a0fb45Spk break;
19271a0fb45Spk }
1938f0abce1Sglass }
19499071d1bSlukem } else
19599071d1bSlukem if (startcomment(where)) {
1968f0abce1Sglass where += 2;
1978f0abce1Sglass commenting++;
1988f0abce1Sglass } else {
1998f0abce1Sglass break;
2008f0abce1Sglass }
2018f0abce1Sglass }
2028f0abce1Sglass
2038f0abce1Sglass /*
2048f0abce1Sglass * 'where' is not whitespace, comment or directive Must be a token!
2058f0abce1Sglass */
2068f0abce1Sglass switch (*where) {
2078f0abce1Sglass case ':':
2088f0abce1Sglass tokp->kind = TOK_COLON;
2098f0abce1Sglass where++;
2108f0abce1Sglass break;
2118f0abce1Sglass case ';':
2128f0abce1Sglass tokp->kind = TOK_SEMICOLON;
2138f0abce1Sglass where++;
2148f0abce1Sglass break;
2158f0abce1Sglass case ',':
2168f0abce1Sglass tokp->kind = TOK_COMMA;
2178f0abce1Sglass where++;
2188f0abce1Sglass break;
2198f0abce1Sglass case '=':
2208f0abce1Sglass tokp->kind = TOK_EQUAL;
2218f0abce1Sglass where++;
2228f0abce1Sglass break;
2238f0abce1Sglass case '*':
2248f0abce1Sglass tokp->kind = TOK_STAR;
2258f0abce1Sglass where++;
2268f0abce1Sglass break;
2278f0abce1Sglass case '[':
2288f0abce1Sglass tokp->kind = TOK_LBRACKET;
2298f0abce1Sglass where++;
2308f0abce1Sglass break;
2318f0abce1Sglass case ']':
2328f0abce1Sglass tokp->kind = TOK_RBRACKET;
2338f0abce1Sglass where++;
2348f0abce1Sglass break;
2358f0abce1Sglass case '{':
2368f0abce1Sglass tokp->kind = TOK_LBRACE;
2378f0abce1Sglass where++;
2388f0abce1Sglass break;
2398f0abce1Sglass case '}':
2408f0abce1Sglass tokp->kind = TOK_RBRACE;
2418f0abce1Sglass where++;
2428f0abce1Sglass break;
2438f0abce1Sglass case '(':
2448f0abce1Sglass tokp->kind = TOK_LPAREN;
2458f0abce1Sglass where++;
2468f0abce1Sglass break;
2478f0abce1Sglass case ')':
2488f0abce1Sglass tokp->kind = TOK_RPAREN;
2498f0abce1Sglass where++;
2508f0abce1Sglass break;
2518f0abce1Sglass case '<':
2528f0abce1Sglass tokp->kind = TOK_LANGLE;
2538f0abce1Sglass where++;
2548f0abce1Sglass break;
2558f0abce1Sglass case '>':
2568f0abce1Sglass tokp->kind = TOK_RANGLE;
2578f0abce1Sglass where++;
2588f0abce1Sglass break;
2598f0abce1Sglass
2608f0abce1Sglass case '"':
2618f0abce1Sglass tokp->kind = TOK_STRCONST;
2628f0abce1Sglass findstrconst(&where, &tokp->str);
2638f0abce1Sglass break;
26471a0fb45Spk case '\'':
26571a0fb45Spk tokp->kind = TOK_CHARCONST;
26671a0fb45Spk findchrconst(&where, &tokp->str);
26771a0fb45Spk break;
2688f0abce1Sglass
2698f0abce1Sglass case '-':
2708f0abce1Sglass case '0':
2718f0abce1Sglass case '1':
2728f0abce1Sglass case '2':
2738f0abce1Sglass case '3':
2748f0abce1Sglass case '4':
2758f0abce1Sglass case '5':
2768f0abce1Sglass case '6':
2778f0abce1Sglass case '7':
2788f0abce1Sglass case '8':
2798f0abce1Sglass case '9':
2808f0abce1Sglass tokp->kind = TOK_IDENT;
2818f0abce1Sglass findconst(&where, &tokp->str);
2828f0abce1Sglass break;
2838f0abce1Sglass
2848f0abce1Sglass default:
285e4ac7024Schristos if (!(isalpha((unsigned char)*where) || *where == '_')) {
286e4ac7024Schristos if (isprint((unsigned char)*where)) {
287*90a10bbbSdholland error("Illegal character '%c' in file", *where);
2888f0abce1Sglass } else {
289*90a10bbbSdholland error("Illegal character %d in file", *where);
2908f0abce1Sglass }
2918f0abce1Sglass }
2928f0abce1Sglass findkind(&where, tokp);
2938f0abce1Sglass break;
2948f0abce1Sglass }
2958f0abce1Sglass }
2968f0abce1Sglass
29793579481Schristos static void
unget_token(token * tokp)298e9067f11Sdholland unget_token(token *tokp)
2998f0abce1Sglass {
3008f0abce1Sglass lasttok = *tokp;
3018f0abce1Sglass pushed = 1;
3028f0abce1Sglass }
3038f0abce1Sglass
30493579481Schristos static void
findstrconst(char ** str,const char ** val)305e9067f11Sdholland findstrconst(char **str, const char **val)
3068f0abce1Sglass {
3078f0abce1Sglass char *p;
3088f0abce1Sglass int size;
309e9067f11Sdholland char *tmp;
3108f0abce1Sglass
3118f0abce1Sglass p = *str;
3128f0abce1Sglass do {
31393579481Schristos p++;
3148f0abce1Sglass } while (*p && *p != '"');
3158f0abce1Sglass if (*p == 0) {
316ceecfabaSdholland error("Unterminated string constant");
3178f0abce1Sglass }
3188f0abce1Sglass p++;
3198f0abce1Sglass size = p - *str;
320e9067f11Sdholland tmp = alloc(size + 1);
321e9067f11Sdholland (void) strncpy(tmp, *str, size);
322e9067f11Sdholland tmp[size] = 0;
323e9067f11Sdholland *val = tmp;
3248f0abce1Sglass *str = p;
3258f0abce1Sglass }
3268f0abce1Sglass
32793579481Schristos static void
findchrconst(char ** str,const char ** val)328e9067f11Sdholland findchrconst(char **str, const char **val)
32971a0fb45Spk {
33071a0fb45Spk char *p;
33171a0fb45Spk int size;
332e9067f11Sdholland char *tmp;
33371a0fb45Spk
33471a0fb45Spk p = *str;
33571a0fb45Spk do {
33693579481Schristos p++;
33771a0fb45Spk } while (*p && *p != '\'');
33871a0fb45Spk if (*p == 0) {
339ceecfabaSdholland error("Unterminated string constant");
34071a0fb45Spk }
34171a0fb45Spk p++;
34271a0fb45Spk size = p - *str;
34371a0fb45Spk if (size != 3) {
344ceecfabaSdholland error("Empty character");
34571a0fb45Spk }
346e9067f11Sdholland tmp = alloc(size + 1);
347e9067f11Sdholland (void) strncpy(tmp, *str, size);
348e9067f11Sdholland tmp[size] = 0;
349e9067f11Sdholland *val = tmp;
35071a0fb45Spk *str = p;
35171a0fb45Spk }
35271a0fb45Spk
35393579481Schristos static void
findconst(char ** str,const char ** val)354e9067f11Sdholland findconst(char **str, const char **val)
3558f0abce1Sglass {
3568f0abce1Sglass char *p;
3578f0abce1Sglass int size;
358e9067f11Sdholland char *tmp;
3598f0abce1Sglass
3608f0abce1Sglass p = *str;
3618f0abce1Sglass if (*p == '0' && *(p + 1) == 'x') {
3628f0abce1Sglass p++;
3638f0abce1Sglass do {
3648f0abce1Sglass p++;
365e4ac7024Schristos } while (isxdigit((unsigned char)*p));
3668f0abce1Sglass } else {
3678f0abce1Sglass do {
3688f0abce1Sglass p++;
369e4ac7024Schristos } while (isdigit((unsigned char)*p));
3708f0abce1Sglass }
3718f0abce1Sglass size = p - *str;
372e9067f11Sdholland tmp = alloc(size + 1);
373e9067f11Sdholland (void) strncpy(tmp, *str, size);
374e9067f11Sdholland tmp[size] = 0;
375e9067f11Sdholland *val = tmp;
3768f0abce1Sglass *str = p;
3778f0abce1Sglass }
3788f0abce1Sglass
379e9067f11Sdholland static const token symbols[] = {
3808f0abce1Sglass {TOK_CONST, "const"},
3818f0abce1Sglass {TOK_UNION, "union"},
3828f0abce1Sglass {TOK_SWITCH, "switch"},
3838f0abce1Sglass {TOK_CASE, "case"},
3848f0abce1Sglass {TOK_DEFAULT, "default"},
3858f0abce1Sglass {TOK_STRUCT, "struct"},
3868f0abce1Sglass {TOK_TYPEDEF, "typedef"},
3878f0abce1Sglass {TOK_ENUM, "enum"},
3888f0abce1Sglass {TOK_OPAQUE, "opaque"},
3898f0abce1Sglass {TOK_BOOL, "bool"},
3908f0abce1Sglass {TOK_VOID, "void"},
3918f0abce1Sglass {TOK_CHAR, "char"},
3928f0abce1Sglass {TOK_INT, "int"},
3938f0abce1Sglass {TOK_UNSIGNED, "unsigned"},
3948f0abce1Sglass {TOK_SHORT, "short"},
3958f0abce1Sglass {TOK_LONG, "long"},
3963cad8d1dSginsbach {TOK_HYPER, "hyper"},
3978f0abce1Sglass {TOK_FLOAT, "float"},
3988f0abce1Sglass {TOK_DOUBLE, "double"},
3993cad8d1dSginsbach {TOK_QUAD, "quadruple"},
4008f0abce1Sglass {TOK_STRING, "string"},
4018f0abce1Sglass {TOK_PROGRAM, "program"},
4028f0abce1Sglass {TOK_VERSION, "version"},
4038f0abce1Sglass {TOK_EOF, "??????"},
4048f0abce1Sglass };
4058f0abce1Sglass
40693579481Schristos static void
findkind(char ** mark,token * tokp)407e9067f11Sdholland findkind(char **mark, token *tokp)
4088f0abce1Sglass {
4098f0abce1Sglass int len;
410e9067f11Sdholland const token *s;
4118f0abce1Sglass char *str;
412e9067f11Sdholland char *tmp;
4138f0abce1Sglass
4148f0abce1Sglass str = *mark;
4158f0abce1Sglass for (s = symbols; s->kind != TOK_EOF; s++) {
4168f0abce1Sglass len = strlen(s->str);
4178f0abce1Sglass if (strncmp(str, s->str, len) == 0) {
418e4ac7024Schristos if (!isalnum((unsigned char)str[len]) &&
419e4ac7024Schristos str[len] != '_') {
4208f0abce1Sglass tokp->kind = s->kind;
4218f0abce1Sglass tokp->str = s->str;
4228f0abce1Sglass *mark = str + len;
4238f0abce1Sglass return;
4248f0abce1Sglass }
4258f0abce1Sglass }
4268f0abce1Sglass }
4278f0abce1Sglass tokp->kind = TOK_IDENT;
428e4ac7024Schristos for (len = 0; isalnum((unsigned char)str[len]) ||
429e4ac7024Schristos str[len] == '_'; len++);
430e9067f11Sdholland tmp = alloc(len + 1);
431e9067f11Sdholland (void) strncpy(tmp, str, len);
432e9067f11Sdholland tmp[len] = 0;
433e9067f11Sdholland tokp->str = tmp;
4348f0abce1Sglass *mark = str + len;
4358f0abce1Sglass }
4368f0abce1Sglass
43793579481Schristos static int
cppline(const char * line)438e9067f11Sdholland cppline(const char *line)
4398f0abce1Sglass {
4408f0abce1Sglass return (line == curline && *line == '#');
4418f0abce1Sglass }
4428f0abce1Sglass
44393579481Schristos static int
directive(const char * line)444e9067f11Sdholland directive(const char *line)
4458f0abce1Sglass {
4468f0abce1Sglass return (line == curline && *line == '%');
4478f0abce1Sglass }
4488f0abce1Sglass
44993579481Schristos static void
printdirective(const char * line)450e9067f11Sdholland printdirective(const char *line)
4518f0abce1Sglass {
4528f0abce1Sglass f_print(fout, "%s", line + 1);
4538f0abce1Sglass }
4548f0abce1Sglass
45593579481Schristos static void
docppline(char * line,int * lineno,const char ** fname)456e9067f11Sdholland docppline(char *line, int *lineno, const char **fname)
4578f0abce1Sglass {
4588f0abce1Sglass char *file;
4598f0abce1Sglass int num;
4608f0abce1Sglass char *p;
4618f0abce1Sglass
4628f0abce1Sglass line++;
463e4ac7024Schristos while (isspace((unsigned char)*line)) {
4648f0abce1Sglass line++;
4658f0abce1Sglass }
4668f0abce1Sglass num = atoi(line);
467e4ac7024Schristos while (isdigit((unsigned char)*line)) {
4688f0abce1Sglass line++;
4698f0abce1Sglass }
470e4ac7024Schristos while (isspace((unsigned char)*line)) {
4718f0abce1Sglass line++;
4728f0abce1Sglass }
4738f0abce1Sglass if (*line != '"') {
474ceecfabaSdholland error("Preprocessor error");
4758f0abce1Sglass }
4768f0abce1Sglass line++;
4778f0abce1Sglass p = file = alloc(strlen(line) + 1);
4788f0abce1Sglass while (*line && *line != '"') {
4798f0abce1Sglass *p++ = *line++;
4808f0abce1Sglass }
4818f0abce1Sglass if (*line == 0) {
482ceecfabaSdholland error("Preprocessor error");
4838f0abce1Sglass }
4848f0abce1Sglass *p = 0;
4858f0abce1Sglass if (*file == 0) {
4868f0abce1Sglass *fname = NULL;
4873e7dafb5Selad free(file);
4888f0abce1Sglass } else {
4898f0abce1Sglass *fname = file;
4908f0abce1Sglass }
4918f0abce1Sglass *lineno = num - 1;
4928f0abce1Sglass }
493