[BACK]Return to rpc_scan.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / rpcgen

Annotation of src/usr.bin/rpcgen/rpc_scan.c, Revision 1.16

1.16    ! deraadt     1: /*     $OpenBSD: rpc_scan.c,v 1.15 2010/09/01 14:43:34 millert Exp $   */
1.1       deraadt     2: /*     $NetBSD: rpc_scan.c,v 1.4 1995/06/11 21:50:02 pk Exp $  */
1.15      millert     3:
1.1       deraadt     4: /*
1.15      millert     5:  * Copyright (c) 2010, Oracle America, Inc.
1.1       deraadt     6:  *
1.15      millert     7:  * Redistribution and use in source and binary forms, with or without
                      8:  * modification, are permitted provided that the following conditions are
                      9:  * met:
1.1       deraadt    10:  *
1.15      millert    11:  *     * Redistributions of source code must retain the above copyright
                     12:  *       notice, this list of conditions and the following disclaimer.
                     13:  *     * Redistributions in binary form must reproduce the above
                     14:  *       copyright notice, this list of conditions and the following
                     15:  *       disclaimer in the documentation and/or other materials
                     16:  *       provided with the distribution.
                     17:  *     * Neither the name of the "Oracle America, Inc." nor the names of its
                     18:  *       contributors may be used to endorse or promote products derived
                     19:  *       from this software without specific prior written permission.
1.1       deraadt    20:  *
1.15      millert    21:  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
                     22:  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
                     23:  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
                     24:  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
                     25:  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
                     26:  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     27:  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
                     28:  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     29:  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
                     30:  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
                     31:  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
                     32:  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1.1       deraadt    33:  */
                     34:
                     35: /*
1.7       deraadt    36:  * rpc_scan.c, Scanner for the RPC protocol compiler
1.1       deraadt    37:  */
                     38: #include <stdlib.h>
                     39: #include <stdio.h>
                     40: #include <ctype.h>
                     41: #include <string.h>
                     42: #include "rpc_scan.h"
                     43: #include "rpc_parse.h"
                     44: #include "rpc_util.h"
                     45:
1.10      deraadt    46: static void unget_token(token *tokp);
                     47: static void findstrconst(char **, char **);
                     48: static void findchrconst(char **, char **);
                     49: static void findconst(char **, char **);
                     50: static void findkind(char **, token *);
                     51: static int cppline(char *);
                     52: static int directive(char *);
                     53: static void printdirective(char *);
                     54: static void docppline(char *, int *, char **);
1.1       deraadt    55:
                     56: #define startcomment(where) (where[0] == '/' && where[1] == '*')
                     57: #define endcomment(where) (where[-1] == '*' && where[0] == '/')
                     58:
                     59: static int pushed = 0; /* is a token pushed */
                     60: static token lasttok;  /* last token, if pushed */
                     61:
                     62: /*
1.7       deraadt    63:  * scan expecting 1 given token
1.1       deraadt    64:  */
                     65: void
                     66: scan(expect, tokp)
                     67:        tok_kind expect;
                     68:        token *tokp;
                     69: {
                     70:        get_token(tokp);
1.7       deraadt    71:        if (tokp->kind != expect)
1.1       deraadt    72:                expected1(expect);
                     73: }
                     74:
                     75: /*
1.7       deraadt    76:  * scan expecting any of the 2 given tokens
1.1       deraadt    77:  */
                     78: void
                     79: scan2(expect1, expect2, tokp)
                     80:        tok_kind expect1;
                     81:        tok_kind expect2;
                     82:        token *tokp;
                     83: {
                     84:        get_token(tokp);
1.7       deraadt    85:        if (tokp->kind != expect1 && tokp->kind != expect2)
1.1       deraadt    86:                expected2(expect1, expect2);
                     87: }
                     88:
                     89: /*
1.7       deraadt    90:  * scan expecting any of the 3 given token
1.1       deraadt    91:  */
                     92: void
                     93: scan3(expect1, expect2, expect3, tokp)
                     94:        tok_kind expect1;
                     95:        tok_kind expect2;
                     96:        tok_kind expect3;
                     97:        token *tokp;
                     98: {
                     99:        get_token(tokp);
1.7       deraadt   100:        if (tokp->kind != expect1 && tokp->kind != expect2 &&
                    101:            tokp->kind != expect3)
1.1       deraadt   102:                expected3(expect1, expect2, expect3);
                    103: }
                    104:
                    105: /*
1.7       deraadt   106:  * scan expecting a constant, possibly symbolic
1.1       deraadt   107:  */
                    108: void
                    109: scan_num(tokp)
                    110:        token *tokp;
                    111: {
                    112:        get_token(tokp);
                    113:        switch (tokp->kind) {
                    114:        case TOK_IDENT:
                    115:                break;
                    116:        default:
                    117:                error("constant or identifier expected");
                    118:        }
                    119: }
                    120:
                    121: /*
1.7       deraadt   122:  * Peek at the next token
1.1       deraadt   123:  */
                    124: void
                    125: peek(tokp)
                    126:        token *tokp;
                    127: {
                    128:        get_token(tokp);
                    129:        unget_token(tokp);
                    130: }
                    131:
                    132: /*
1.7       deraadt   133:  * Peek at the next token and scan it if it matches what you expect
1.1       deraadt   134:  */
                    135: int
                    136: peekscan(expect, tokp)
                    137:        tok_kind expect;
                    138:        token *tokp;
                    139: {
                    140:        peek(tokp);
                    141:        if (tokp->kind == expect) {
                    142:                get_token(tokp);
                    143:                return (1);
                    144:        }
                    145:        return (0);
                    146: }
                    147:
                    148: /*
1.7       deraadt   149:  * Get the next token, printing out any directive that are encountered.
1.1       deraadt   150:  */
                    151: void
                    152: get_token(tokp)
                    153:        token *tokp;
                    154: {
                    155:        int commenting;
                    156:
                    157:        if (pushed) {
                    158:                pushed = 0;
                    159:                *tokp = lasttok;
                    160:                return;
                    161:        }
                    162:        commenting = 0;
                    163:        for (;;) {
                    164:                if (*where == 0) {
                    165:                        for (;;) {
                    166:                                if (!fgets(curline, MAXLINESIZE, fin)) {
                    167:                                        tokp->kind = TOK_EOF;
                    168:                                        *where = 0;
                    169:                                        return;
                    170:                                }
                    171:                                linenum++;
                    172:                                if (commenting) {
                    173:                                        break;
                    174:                                } else if (cppline(curline)) {
1.7       deraadt   175:                                        docppline(curline, &linenum,
                    176:                                            &infilename);
1.1       deraadt   177:                                } else if (directive(curline)) {
                    178:                                        printdirective(curline);
                    179:                                } else {
                    180:                                        break;
                    181:                                }
                    182:                        }
                    183:                        where = curline;
                    184:                } else if (isspace(*where)) {
                    185:                        while (isspace(*where)) {
                    186:                                where++;        /* eat */
                    187:                        }
                    188:                } else if (commenting) {
                    189:                        for (where++; *where; where++) {
                    190:                                if (endcomment(where)) {
                    191:                                        where++;
                    192:                                        commenting--;
                    193:                                        break;
                    194:                                }
                    195:                        }
                    196:                } else if (startcomment(where)) {
                    197:                        where += 2;
                    198:                        commenting++;
                    199:                } else {
                    200:                        break;
                    201:                }
                    202:        }
                    203:
                    204:        /*
1.7       deraadt   205:         * 'where' is not whitespace, comment or directive Must be a token!
1.1       deraadt   206:         */
                    207:        switch (*where) {
                    208:        case ':':
                    209:                tokp->kind = TOK_COLON;
                    210:                where++;
                    211:                break;
                    212:        case ';':
                    213:                tokp->kind = TOK_SEMICOLON;
                    214:                where++;
                    215:                break;
                    216:        case ',':
                    217:                tokp->kind = TOK_COMMA;
                    218:                where++;
                    219:                break;
                    220:        case '=':
                    221:                tokp->kind = TOK_EQUAL;
                    222:                where++;
                    223:                break;
                    224:        case '*':
                    225:                tokp->kind = TOK_STAR;
                    226:                where++;
                    227:                break;
                    228:        case '[':
                    229:                tokp->kind = TOK_LBRACKET;
                    230:                where++;
                    231:                break;
                    232:        case ']':
                    233:                tokp->kind = TOK_RBRACKET;
                    234:                where++;
                    235:                break;
                    236:        case '{':
                    237:                tokp->kind = TOK_LBRACE;
                    238:                where++;
                    239:                break;
                    240:        case '}':
                    241:                tokp->kind = TOK_RBRACE;
                    242:                where++;
                    243:                break;
                    244:        case '(':
                    245:                tokp->kind = TOK_LPAREN;
                    246:                where++;
                    247:                break;
                    248:        case ')':
                    249:                tokp->kind = TOK_RPAREN;
                    250:                where++;
                    251:                break;
                    252:        case '<':
                    253:                tokp->kind = TOK_LANGLE;
                    254:                where++;
                    255:                break;
                    256:        case '>':
                    257:                tokp->kind = TOK_RANGLE;
                    258:                where++;
                    259:                break;
                    260:
                    261:        case '"':
                    262:                tokp->kind = TOK_STRCONST;
                    263:                findstrconst(&where, &tokp->str);
                    264:                break;
                    265:        case '\'':
                    266:                tokp->kind = TOK_CHARCONST;
                    267:                findchrconst(&where, &tokp->str);
                    268:                break;
                    269:
                    270:        case '-':
                    271:        case '0':
                    272:        case '1':
                    273:        case '2':
                    274:        case '3':
                    275:        case '4':
                    276:        case '5':
                    277:        case '6':
                    278:        case '7':
                    279:        case '8':
                    280:        case '9':
                    281:                tokp->kind = TOK_IDENT;
                    282:                findconst(&where, &tokp->str);
                    283:                break;
                    284:
                    285:        default:
                    286:                if (!(isalpha(*where) || *where == '_')) {
1.11      deraadt   287:                        char buf[100], chs[20];
1.1       deraadt   288:
                    289:                        if (isprint(*where)) {
1.11      deraadt   290:                                snprintf(chs, sizeof chs, "%c", *where);
1.1       deraadt   291:                        } else {
1.11      deraadt   292:                                snprintf(chs, sizeof chs, "%d", *where);
1.1       deraadt   293:                        }
1.11      deraadt   294:
                    295:                        snprintf(buf, sizeof buf,
                    296:                            "illegal character in file: %s", chs);
1.1       deraadt   297:                        error(buf);
                    298:                }
                    299:                findkind(&where, tokp);
                    300:                break;
                    301:        }
                    302: }
                    303:
1.10      deraadt   304: static void
1.1       deraadt   305: unget_token(tokp)
                    306:        token *tokp;
                    307: {
                    308:        lasttok = *tokp;
                    309:        pushed = 1;
                    310: }
                    311:
1.10      deraadt   312: static void
1.1       deraadt   313: findstrconst(str, val)
                    314:        char **str;
                    315:        char **val;
                    316: {
                    317:        char *p;
                    318:        int size;
                    319:
                    320:        p = *str;
                    321:        do {
1.10      deraadt   322:                p++;
1.1       deraadt   323:        } while (*p && *p != '"');
                    324:        if (*p == 0) {
                    325:                error("unterminated string constant");
                    326:        }
                    327:        p++;
                    328:        size = p - *str;
                    329:        *val = alloc(size + 1);
1.10      deraadt   330:        if (val == NULL)
                    331:                error("alloc failed");
1.1       deraadt   332:        (void) strncpy(*val, *str, size);
                    333:        (*val)[size] = 0;
                    334:        *str = p;
                    335: }
                    336:
1.10      deraadt   337: static void
1.1       deraadt   338: findchrconst(str, val)
                    339:        char **str;
                    340:        char **val;
                    341: {
                    342:        char *p;
                    343:        int size;
                    344:
                    345:        p = *str;
                    346:        do {
1.10      deraadt   347:                p++;
1.1       deraadt   348:        } while (*p && *p != '\'');
                    349:        if (*p == 0) {
                    350:                error("unterminated string constant");
                    351:        }
                    352:        p++;
                    353:        size = p - *str;
                    354:        if (size != 3) {
                    355:                error("empty char string");
                    356:        }
                    357:        *val = alloc(size + 1);
1.10      deraadt   358:        if (val == NULL)
                    359:                error("alloc failed");
1.1       deraadt   360:        (void) strncpy(*val, *str, size);
                    361:        (*val)[size] = 0;
                    362:        *str = p;
                    363: }
                    364:
1.10      deraadt   365: static void
1.1       deraadt   366: findconst(str, val)
                    367:        char **str;
                    368:        char **val;
                    369: {
                    370:        char *p;
                    371:        int size;
                    372:
                    373:        p = *str;
                    374:        if (*p == '0' && *(p + 1) == 'x') {
                    375:                p++;
                    376:                do {
                    377:                        p++;
                    378:                } while (isxdigit(*p));
                    379:        } else {
                    380:                do {
                    381:                        p++;
                    382:                } while (isdigit(*p));
                    383:        }
                    384:        size = p - *str;
                    385:        *val = alloc(size + 1);
1.10      deraadt   386:        if (val == NULL)
                    387:                error("alloc failed");
1.1       deraadt   388:        (void) strncpy(*val, *str, size);
                    389:        (*val)[size] = 0;
                    390:        *str = p;
                    391: }
                    392:
                    393: static token symbols[] = {
1.7       deraadt   394:        {TOK_CONST, "const"},
                    395:        {TOK_UNION, "union"},
                    396:        {TOK_SWITCH, "switch"},
                    397:        {TOK_CASE, "case"},
                    398:        {TOK_DEFAULT, "default"},
                    399:        {TOK_STRUCT, "struct"},
                    400:        {TOK_TYPEDEF, "typedef"},
                    401:        {TOK_ENUM, "enum"},
                    402:        {TOK_OPAQUE, "opaque"},
                    403:        {TOK_BOOL, "bool"},
                    404:        {TOK_VOID, "void"},
                    405:        {TOK_CHAR, "char"},
                    406:        {TOK_INT, "int"},
                    407:        {TOK_UNSIGNED, "unsigned"},
                    408:        {TOK_SHORT, "short"},
                    409:        {TOK_LONG, "long"},
                    410:        {TOK_FLOAT, "float"},
                    411:        {TOK_DOUBLE, "double"},
                    412:        {TOK_STRING, "string"},
                    413:        {TOK_PROGRAM, "program"},
                    414:        {TOK_VERSION, "version"},
                    415:        {TOK_EOF, "??????"},
1.1       deraadt   416: };
                    417:
1.10      deraadt   418: static void
1.1       deraadt   419: findkind(mark, tokp)
                    420:        char **mark;
                    421:        token *tokp;
                    422: {
                    423:        int len;
                    424:        token *s;
                    425:        char *str;
                    426:
                    427:        str = *mark;
                    428:        for (s = symbols; s->kind != TOK_EOF; s++) {
                    429:                len = strlen(s->str);
                    430:                if (strncmp(str, s->str, len) == 0) {
                    431:                        if (!isalnum(str[len]) && str[len] != '_') {
                    432:                                tokp->kind = s->kind;
                    433:                                tokp->str = s->str;
                    434:                                *mark = str + len;
                    435:                                return;
                    436:                        }
                    437:                }
                    438:        }
                    439:        tokp->kind = TOK_IDENT;
                    440:        for (len = 0; isalnum(str[len]) || str[len] == '_'; len++);
                    441:        tokp->str = alloc(len + 1);
1.10      deraadt   442:        if (tokp->str == NULL)
                    443:                error("alloc failed");
1.1       deraadt   444:        (void) strncpy(tokp->str, str, len);
                    445:        tokp->str[len] = 0;
                    446:        *mark = str + len;
                    447: }
                    448:
1.10      deraadt   449: static int
1.1       deraadt   450: cppline(line)
                    451:        char *line;
                    452: {
                    453:        return (line == curline && *line == '#');
                    454: }
                    455:
1.10      deraadt   456: static int
1.1       deraadt   457: directive(line)
                    458:        char *line;
                    459: {
                    460:        return (line == curline && *line == '%');
                    461: }
                    462:
1.10      deraadt   463: static void
1.1       deraadt   464: printdirective(line)
                    465:        char *line;
                    466: {
1.9       deraadt   467:        fprintf(fout, "%s", line + 1);
1.1       deraadt   468: }
                    469:
1.10      deraadt   470: static void
1.1       deraadt   471: docppline(line, lineno, fname)
                    472:        char *line;
                    473:        int *lineno;
                    474:        char **fname;
                    475: {
                    476:        char *file;
                    477:        int num;
                    478:        char *p;
                    479:
                    480:        line++;
                    481:        while (isspace(*line)) {
                    482:                line++;
                    483:        }
                    484:        num = atoi(line);
                    485:        while (isdigit(*line)) {
                    486:                line++;
                    487:        }
                    488:        while (isspace(*line)) {
                    489:                line++;
                    490:        }
                    491:        if (*line != '"') {
                    492:                error("preprocessor error");
                    493:        }
                    494:        line++;
                    495:        p = file = alloc(strlen(line) + 1);
1.10      deraadt   496:        if (p == NULL)
                    497:                error("alloc failed");
1.1       deraadt   498:        while (*line && *line != '"') {
                    499:                *p++ = *line++;
                    500:        }
                    501:        if (*line == 0) {
                    502:                error("preprocessor error");
                    503:        }
                    504:        *p = 0;
                    505:        if (*file == 0) {
                    506:                *fname = NULL;
1.12      dhill     507:                free(file);
1.1       deraadt   508:        } else {
                    509:                *fname = file;
                    510:        }
                    511:        *lineno = num - 1;
                    512: }