[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.15

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