Annotation of 42BSD/ucb/indent/lexi.c, revision 1.1.1.1

1.1       root        1: static char sccsid[] = "@(#)lexi.c     4.1     (Berkeley)      10/21/82";
                      2: 
                      3: /*
                      4: 
                      5:                          Copyright (C) 1976
                      6:                                by the
                      7:                          Board of Trustees
                      8:                                of the
                      9:                        University of Illinois
                     10: 
                     11:                         All rights reserved
                     12: 
                     13: 
                     14: NAME:
                     15:        lexi
                     16: 
                     17: FUNCTION:
                     18:        This is the token scanner for indent
                     19: 
                     20: ALGORITHM:
                     21:        1) Strip off intervening blanks and/or tabs.
                     22:        2) If it is an alphanumeric token, move it to the token buffer "token".
                     23:           Check if it is a special reserved word that indent will want to
                     24:           know about.
                     25:        3) Non-alphanumeric tokens are handled with a big switch statement.  A
                     26:           flag is kept to remember if the last token was a "unary delimiter",
                     27:           which forces a following operator to be unary as opposed to binary.
                     28: 
                     29: PARAMETERS:
                     30:        None
                     31: 
                     32: RETURNS:
                     33:        An integer code indicating the type of token scanned.
                     34: 
                     35: GLOBALS:
                     36:        buf_ptr =
                     37:        had_eof
                     38:        last_u_d =      Set to true iff this token is a "unary delimiter"
                     39: 
                     40: CALLS:
                     41:        fill_buffer
                     42:        printf (lib)
                     43: 
                     44: CALLED BY:
                     45:        main
                     46: 
                     47: NOTES:
                     48:        Start of comment is passed back so that the comment can be scanned by
                     49:        pr_comment.
                     50: 
                     51:        Strings and character literals are returned just like identifiers.
                     52: 
                     53: HISTORY:
                     54:        initial coding  November 1976   D A Willcox of CAC
                     55:        1/7/77          D A Willcox of CAC      Fix to provide proper handling
                     56:                                                of "int a -1;"
                     57: 
                     58: */
                     59: 
                     60: /* Here we have the token scanner for indent.  It scans off one token and
                     61:    puts it in the global variable "token".  It returns a code, indicating the
                     62:    type of token scanned. */
                     63: 
                     64: #include "indent_globs.h";
                     65: #include "indent_codes.h";
                     66: 
                     67: 
                     68: 
                     69: #define alphanum 1
                     70: #define opchar 3
                     71: 
                     72: struct templ {
                     73:     char   *rwd;
                     74:     int     rwcode;
                     75: };
                     76: 
                     77: struct templ    specials[] =
                     78: {
                     79:     "switch", 1,
                     80:     "case", 2,
                     81:     "struct", 3,
                     82:     "default", 2,
                     83:     "int", 4,
                     84:     "char", 4,
                     85:     "float", 4,
                     86:     "double", 4,
                     87:     "long", 4,
                     88:     "short", 4,
                     89:     "typdef", 4,
                     90:     "unsigned", 4,
                     91:     "register", 4,
                     92:     "static", 4,
                     93:     "global", 4,
                     94:     "extern", 4,
                     95:     "if", 5,
                     96:     "while", 5,
                     97:     "for", 5,
                     98:     "else", 6,
                     99:     "do", 6,
                    100:     "sizeof", 0,
                    101:     0, 0
                    102: };
                    103: 
                    104: char    chartype[128] =
                    105: {                 /* this is used to facilitate the decision of what type
                    106:                      (alphanumeric, operator) each character is */
                    107:     0, 0, 0, 0, 0, 0, 0, 0,
                    108:     0, 0, 0, 0, 0, 0, 0, 0,
                    109:     0, 0, 0, 0, 0, 0, 0, 0,
                    110:     0, 0, 0, 0, 0, 0, 0, 0,
                    111:     0, 3, 0, 0, 0, 3, 3, 0,
                    112:     0, 0, 3, 3, 0, 3, 3, 3,
                    113:     1, 1, 1, 1, 1, 1, 1, 1,
                    114:     1, 1, 0, 0, 3, 3, 3, 3,
                    115:     0, 1, 1, 1, 1, 1, 1, 1,
                    116:     1, 1, 1, 1, 1, 1, 1, 1,
                    117:     1, 1, 1, 1, 1, 1, 1, 1,
                    118:     1, 1, 1, 0, 0, 0, 3, 1,
                    119:     0, 1, 1, 1, 1, 1, 1, 1,
                    120:     1, 1, 1, 1, 1, 1, 1, 1,
                    121:     1, 1, 1, 1, 1, 1, 1, 1,
                    122:     1, 1, 1, 0, 3, 0, 3, 0
                    123: };
                    124: 
                    125: int     last_nl = true;
                    126:  /* this is true if the last thing scanned was a newline */
                    127: 
                    128: 
                    129: 
                    130: int     lexi () {
                    131:     register char  *tok;
                    132:  /* local pointer to next char in token */
                    133:     register int    i;
                    134:  /* local loop counter */
                    135:     register char  *j;
                    136:  /* used for searching thru list of reserved words */
                    137:     int     unary_delim;
                    138:  /* this is set to 1 if the current token forces a following operator to be
                    139:     unary */
                    140:     static int  last_code;
                    141:  /* the last token type returned */
                    142:     static int  l_struct;
                    143:  /* set to 1 if the last token was 'struct' */
                    144:     int     found_it;
                    145:     int     code;  /* internal code to be returned */
                    146:     char    qchar; /* the delimiter character for a string */
                    147: 
                    148:     tok = token;              /* point to start of place to save token */
                    149:     unary_delim = false;
                    150:     col_1 = last_nl;          /* tell world that this token started in column
                    151:                                  1 iff the last thing scanned was nl */
                    152:     last_nl = false;
                    153: 
                    154:     while (*buf_ptr == ' ' || *buf_ptr == '\t') {
                    155:     /* get rid of blanks */
                    156:        col_1 = false;         /* leading blanks imply token is not in column 1
                    157:                                  */
                    158:        if (++buf_ptr >= buf_end)
                    159:            fill_buffer ();
                    160:     }
                    161: 
                    162: /*----------------------------------------------------------*\ 
                    163: |    Scan an alphanumeric token
                    164: \*----------------------------------------------------------*/
                    165: 
                    166:     if (chartype[*buf_ptr & 0177] == alphanum) {
                    167:     /* we have a character or number */
                    168:        while (chartype[*buf_ptr & 0177] == alphanum) {
                    169:        /* copy it over */
                    170:            *tok++ = *buf_ptr++;
                    171:            if (buf_ptr >= buf_end)
                    172:                fill_buffer ();
                    173:        }
                    174: 
                    175:        *tok++ = '\0';
                    176: 
                    177:        if (l_struct) {        /* if last token was 'struct', then this token
                    178:                                  should be treated as a declaration */
                    179:            l_struct = false;
                    180:            last_code = ident;
                    181:            last_u_d = true;
                    182:            return (decl);
                    183:        }
                    184: 
                    185:        last_u_d = false;      /* operator after indentifier is binary */
                    186: 
                    187:        for (i = 0; specials[i].rwd != 0; ++i) {
                    188:        /* this loop will check if the token is a keyword.  if so, a following
                    189:           operator is unary */
                    190:            last_code = ident; /* remember that this is the code we will return
                    191:                                  */
                    192:            j = specials[i].rwd;
                    193:        /* point at ith reserved word */
                    194:            tok = token;       /* point at scanned toekn */
                    195:            found_it = true;   /* set to false if not found */
                    196:            do {
                    197:                if (*tok++ != *j) {
                    198:                    found_it = false;
                    199:                    break;
                    200:                }
                    201:            } while (*j++);
                    202: 
                    203:            if (found_it) {    /* we have a keyword */
                    204:                last_u_d = true;
                    205:                switch (specials[i].rwcode) {
                    206:                    case 1:    /* it is a switch */
                    207:                        return (swstmt);
                    208:                    case 2:    /* a case or default */
                    209:                        return (casestmt);
                    210: 
                    211:                    case 3:    /* a "struct" */
                    212:                        l_struct = true;
                    213:                    /* Next time around, we will want to know that we have had
                    214:                       a 'struct' */
                    215:                    case 4:    /* one of the declaration keywords */
                    216:                        if(p_l_follow) break;   /* inside parens: cast */
                    217:                        last_code = decl;
                    218:                        return (decl);
                    219: 
                    220:                    case 5:    /* if, while, for */
                    221:                        return (sp_paren);
                    222: 
                    223:                    case 6:    /* do, else */
                    224:                        return (sp_nparen);
                    225: 
                    226:                    default:   /* all others are treated like any other
                    227:                                  identifier */
                    228:                        return (ident);
                    229:                }              /* end of switch */
                    230:            }                  /* end of if (found_it) */
                    231: 
                    232:        }
                    233: 
                    234:        if (last_code == decl) /* if this is a declared variable, then
                    235:                                  following sign is unary */
                    236:            last_u_d = true;   /* will make "int a -1" work */
                    237:        last_code = ident;
                    238:        return (ident);        /* the ident is not in the list */
                    239:     }                         /* end of procesing for alpanum character */
                    240: 
                    241: 
                    242: 
                    243: /*----------------------------------------------------------*\ 
                    244: |   Scan a non-alphanumeric token
                    245: \*----------------------------------------------------------*/
                    246: 
                    247:     *tok++ = *buf_ptr;        /* if it is only a one-character token, it is
                    248:                                  moved here */
                    249:     *tok = '\0';
                    250:     if (++buf_ptr >= buf_end)
                    251:        fill_buffer ();
                    252: 
                    253:     switch (*token) {
                    254:        case '\n': 
                    255:            unary_delim = last_u_d;
                    256:            last_nl = true;    /* remember that we just had a newline */
                    257:            code = (had_eof ? 0 : newline);
                    258:        /* if data has been exausted, the newline is a dummy, and we should
                    259:           return code to stop */
                    260:            break;
                    261: 
                    262:        case '\'':             /* start of quoted character */
                    263:            qchar = '\'';      /* remember final delimiter */
                    264:            goto copy_lit;     /* and go to common literal code */
                    265: 
                    266:        case '"':              /* start of string */
                    267:            qchar = '"';
                    268: 
                    269:     copy_lit: 
                    270:            do {               /* copy the string */
                    271:                while (1) {    /* move one character or [/<char>]<char> */
                    272:                    if (*buf_ptr == '\n') {
                    273:                    /* check for unterminated literal */
                    274:                        printf ("%d: Unterminated literal\n", line_no);
                    275:                        goto stop_lit;
                    276:                    /* Don't copy any more */
                    277:                    }
                    278: 
                    279:                    *tok = *buf_ptr++;
                    280:                    if (buf_ptr >= buf_end)
                    281:                        fill_buffer ();
                    282:                    if (had_eof || ((tok - token) > (bufsize - 2))) {
                    283:                        printf ("Unterminated literal\n");
                    284:                        ++tok;
                    285:                        goto stop_lit;
                    286:                    /* get outof literal copying loop */
                    287:                    }
                    288: 
                    289:                    if (*tok == '\\') {
                    290:                    /* if escape, copy extra char */
                    291:                        if (*buf_ptr == '\n')
                    292:                               /* check for escaped newline */
                    293:                            ++line_no;
                    294:                        *(++tok) = *buf_ptr++;
                    295:                        ++tok; /* we must increment this again because we
                    296:                                  copied two chars */
                    297:                        if (buf_ptr >= buf_end)
                    298:                            fill_buffer ();
                    299:                    }
                    300:                    else
                    301:                        break; /* we copied one character */
                    302:                }              /* end of while (1) */
                    303:            } while (*tok++ != qchar);
                    304: 
                    305:     stop_lit: 
                    306:            code = ident;
                    307:            break;
                    308: 
                    309:        case ('('): 
                    310:        case ('['): 
                    311:            unary_delim = true;
                    312:            code = lparen;
                    313:            break;
                    314: 
                    315:        case (')'): 
                    316:        case (']'): 
                    317:            code = rparen;
                    318:            break;
                    319: 
                    320:        case '#': 
                    321:            unary_delim = last_u_d;
                    322:            code = preesc;
                    323:            break;
                    324: 
                    325:        case '?': 
                    326:            unary_delim = true;
                    327:            code = question;
                    328:            break;
                    329: 
                    330:        case (':'): 
                    331:            code = colon;
                    332:            unary_delim = true;
                    333:            break;
                    334: 
                    335:        case (';'): 
                    336:            unary_delim = true;
                    337:            code = semicolon;
                    338:            break;
                    339: 
                    340:        case ('{'): 
                    341:            unary_delim = true;
                    342:            code = lbrace;
                    343:            break;
                    344: 
                    345:        case ('}'): 
                    346:            unary_delim = true;
                    347:            code = rbrace;
                    348:            break;
                    349: 
                    350:        case 014:              /* a form feed */
                    351:            unary_delim = last_u_d;
                    352:            last_nl = true;    /* remember this so we can set 'col_1' right */
                    353:            code = form_feed;
                    354:            break;
                    355: 
                    356:        case (','): 
                    357:            unary_delim = true;
                    358:            code = comma;
                    359:            break;
                    360: 
                    361:        case '.': 
                    362:            unary_delim = false;
                    363:            code = period;
                    364:            break;
                    365: 
                    366:        case '-': 
                    367:        case '+':              /* check for -, +, --, ++ */
                    368:            code = (last_u_d ? unary_op : binary_op);
                    369:            unary_delim = true;
                    370: 
                    371:            if (*buf_ptr == token[0]) {
                    372:            /* check for doubled character */
                    373:                *tok++ = *buf_ptr++;
                    374:            /* buffer overflow will be checked at end of loop */
                    375:                if (last_code == ident || last_code == rparen) {
                    376:                    code = (last_u_d ? unary_op : postop);
                    377:                /* check for following ++ or -- */
                    378:                    unary_delim = false;
                    379:                }
                    380:            }
                    381:            else
                    382:                if (*buf_ptr == '>' || *buf_ptr == '=')
                    383:                               /* check for operator -> or += */
                    384:                    *tok++ = *buf_ptr++;
                    385:        /* buffer overflow will be checked at end of switch */
                    386: 
                    387:            break;
                    388: 
                    389:        case '=': 
                    390:            if (chartype[*buf_ptr] == opchar) {
                    391:            /* we have two char assignment */
                    392:                *tok++ = *buf_ptr;
                    393:            /* move second character */
                    394:                if (++buf_ptr >= buf_end)
                    395:                    fill_buffer ();
                    396:            }
                    397: 
                    398:            code = binary_op;
                    399:            unary_delim = true;
                    400:            if (token[1] != '<' && token[1] != '>')
                    401:                               /* check for possible 3 char operator */
                    402:                break;
                    403:        /* can drop thru!!! */
                    404: 
                    405:        case '>': 
                    406:        case '<': 
                    407:        case '!':              /* ops like <, <<, <=, !=, etc */
                    408:            if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
                    409:                *tok++ = *buf_ptr;
                    410:                if (++buf_ptr >= buf_end)
                    411:                    fill_buffer ();
                    412:            }
                    413: 
                    414:            if (*buf_ptr == '=')
                    415:                 *tok++ = *buf_ptr++;
                    416:            code = (last_u_d ? unary_op : binary_op);
                    417:            unary_delim = true;
                    418:            break;
                    419: 
                    420:        default: 
                    421:            if (token[0] == '/' && *buf_ptr == '*') {
                    422:            /* it is start of comment */
                    423:                *tok++ = '*';
                    424: 
                    425:                if (++buf_ptr >= buf_end)
                    426:                    fill_buffer ();
                    427: 
                    428:                code = comment;
                    429:                unary_delim = last_u_d;
                    430:                break;
                    431:            }
                    432: 
                    433:            while (*(tok - 1) == *buf_ptr || *buf_ptr=='=') {
                    434:            /* handle ||, &&, etc, and also things as in int *****i */
                    435:                *tok++ = *buf_ptr;
                    436:                if (++buf_ptr >= buf_end)
                    437:                    fill_buffer ();
                    438:            }
                    439: 
                    440: 
                    441:            code = (last_u_d ? unary_op : binary_op);
                    442:            unary_delim = true;
                    443: 
                    444: 
                    445:     }                         /* end of switch */
                    446: 
                    447:     if (code != newline) {
                    448:        l_struct = false;
                    449:        last_code = code;
                    450:     }
                    451: 
                    452:     if (buf_ptr >= buf_end)    /* check for input buffer empty */
                    453:        fill_buffer ();
                    454:     last_u_d = unary_delim;
                    455:     *tok = '\0';              /* null terminate the token */
                    456:     return (code);
                    457: };

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.