LCOV - code coverage report
Current view: top level - src/tools/pg_bsd_indent - lexi.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 273 342 79.8 %
Date: 2024-11-21 08:14:44 Functions: 5 5 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-
       2             :  * Copyright (c) 1985 Sun Microsystems, Inc.
       3             :  * Copyright (c) 1980, 1993
       4             :  *  The Regents of the University of California.  All rights reserved.
       5             :  * All rights reserved.
       6             :  *
       7             :  * Redistribution and use in source and binary forms, with or without
       8             :  * modification, are permitted provided that the following conditions
       9             :  * are met:
      10             :  * 1. Redistributions of source code must retain the above copyright
      11             :  *    notice, this list of conditions and the following disclaimer.
      12             :  * 2. Redistributions in binary form must reproduce the above copyright
      13             :  *    notice, this list of conditions and the following disclaimer in the
      14             :  *    documentation and/or other materials provided with the distribution.
      15             :  * 3. Neither the name of the University nor the names of its contributors
      16             :  *    may be used to endorse or promote products derived from this software
      17             :  *    without specific prior written permission.
      18             :  *
      19             :  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      20             :  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      21             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      22             :  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      23             :  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      24             :  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      25             :  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      26             :  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      27             :  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      28             :  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      29             :  * SUCH DAMAGE.
      30             :  */
      31             : 
      32             : #if 0
      33             : #ifndef lint
      34             : static char sccsid[] = "@(#)lexi.c 8.1 (Berkeley) 6/6/93";
      35             : #endif /* not lint */
      36             : #endif
      37             : 
      38             : #include "c.h"
      39             : 
      40             : /*
      41             :  * Here we have the token scanner for indent.  It scans off one token and puts
      42             :  * it in the global variable "token".  It returns a code, indicating the type
      43             :  * of token scanned.
      44             :  */
      45             : 
      46             : #include <err.h>
      47             : #include <stdio.h>
      48             : #include <ctype.h>
      49             : #include <stdlib.h>
      50             : #include <string.h>
      51             : #include "indent_globs.h"
      52             : #include "indent_codes.h"
      53             : #include "indent.h"
      54             : 
      55             : #define alphanum 1
      56             : #ifdef undef
      57             : #define opchar 3
      58             : #endif
      59             : 
      60             : struct templ {
      61             :     const char *rwd;
      62             :     int         rwcode;
      63             : };
      64             : 
      65             : /*
      66             :  * This table has to be sorted alphabetically, because it'll be used in binary
      67             :  * search. For the same reason, string must be the first thing in struct templ.
      68             :  */
      69             : struct templ specials[] =
      70             : {
      71             :     {"_Bool", 4},
      72             :     {"_Complex", 4},
      73             :     {"_Imaginary", 4},
      74             :     {"auto", 10},
      75             :     {"bool", 4},
      76             :     {"break", 9},
      77             :     {"case", 8},
      78             :     {"char", 4},
      79             :     {"complex", 4},
      80             :     {"const", 4},
      81             :     {"continue", 12},
      82             :     {"default", 8},
      83             :     {"do", 6},
      84             :     {"double", 4},
      85             :     {"else", 6},
      86             :     {"enum", 3},
      87             :     {"extern", 10},
      88             :     {"float", 4},
      89             :     {"for", 5},
      90             :     {"global", 4},
      91             :     {"goto", 9},
      92             :     {"if", 5},
      93             :     {"imaginary", 4},
      94             :     {"inline", 12},
      95             :     {"int", 4},
      96             :     {"long", 4},
      97             :     {"offsetof", 1},
      98             :     {"register", 10},
      99             :     {"restrict", 12},
     100             :     {"return", 9},
     101             :     {"short", 4},
     102             :     {"signed", 4},
     103             :     {"sizeof", 2},
     104             :     {"static", 10},
     105             :     {"struct", 3},
     106             :     {"switch", 7},
     107             :     {"typedef", 11},
     108             :     {"union", 3},
     109             :     {"unsigned", 4},
     110             :     {"void", 4},
     111             :     {"volatile", 4},
     112             :     {"while", 5}
     113             : };
     114             : 
     115             : const char **typenames;
     116             : int         typename_count;
     117             : int         typename_top = -1;
     118             : 
     119             : char        chartype[128] =
     120             : {               /* this is used to facilitate the decision of
     121             :                  * what type (alphanumeric, operator) each
     122             :                  * character is */
     123             :     0, 0, 0, 0, 0, 0, 0, 0,
     124             :     0, 0, 0, 0, 0, 0, 0, 0,
     125             :     0, 0, 0, 0, 0, 0, 0, 0,
     126             :     0, 0, 0, 0, 0, 0, 0, 0,
     127             :     0, 3, 0, 0, 1, 3, 3, 0,
     128             :     0, 0, 3, 3, 0, 3, 0, 3,
     129             :     1, 1, 1, 1, 1, 1, 1, 1,
     130             :     1, 1, 0, 0, 3, 3, 3, 3,
     131             :     0, 1, 1, 1, 1, 1, 1, 1,
     132             :     1, 1, 1, 1, 1, 1, 1, 1,
     133             :     1, 1, 1, 1, 1, 1, 1, 1,
     134             :     1, 1, 1, 0, 0, 0, 3, 1,
     135             :     0, 1, 1, 1, 1, 1, 1, 1,
     136             :     1, 1, 1, 1, 1, 1, 1, 1,
     137             :     1, 1, 1, 1, 1, 1, 1, 1,
     138             :     1, 1, 1, 0, 3, 0, 3, 0
     139             : };
     140             : 
     141             : static int
     142        4460 : strcmp_type(const void *e1, const void *e2)
     143             : {
     144        4460 :     return (strcmp(e1, *(const char * const *)e2));
     145             : }
     146             : 
     147             : /*
     148             :  * Decide whether "foo(..." is a function definition or declaration.
     149             :  *
     150             :  * At call, we are looking at the '('.  Look ahead to find the first
     151             :  * '{', ';' or ',' that is not within parentheses or comments; then
     152             :  * it's a definition if we found '{', otherwise a declaration.
     153             :  * Note that this rule is fooled by K&R-style parameter declarations,
     154             :  * but telling the difference between those and function attributes
     155             :  * seems like more trouble than it's worth.  This code could also be
     156             :  * fooled by mismatched parens or apparent comment starts within string
     157             :  * literals, but that seems unlikely in the context it's used in.
     158             :  */
     159             : static int
     160          64 : is_func_definition(char *tp)
     161             : {
     162          64 :     int     paren_depth = 0;
     163          64 :     int     in_comment = false;
     164          64 :     int     in_slash_comment = false;
     165          64 :     int     lastc = 0;
     166             : 
     167             :     /* We may need to look past the end of the current buffer. */
     168          64 :     lookahead_reset();
     169        1272 :     for (;;) {
     170             :     int     c;
     171             : 
     172             :     /* Fetch next character. */
     173        1336 :     if (tp < buf_end)
     174         724 :         c = *tp++;
     175             :     else {
     176         612 :         c = lookahead();
     177         612 :         if (c == EOF)
     178           0 :         break;
     179             :     }
     180             :     /* Handle comments. */
     181        1336 :     if (in_comment) {
     182           0 :         if (lastc == '*' && c == '/')
     183           0 :         in_comment = false;
     184        1336 :     } else if (lastc == '/' && c == '*' && !in_slash_comment)
     185           0 :         in_comment = true;
     186        1336 :     else if (in_slash_comment) {
     187           0 :         if (c == '\n')
     188           0 :         in_slash_comment = false;
     189        1336 :     } else if (lastc == '/' && c == '/')
     190           0 :         in_slash_comment = true;
     191             :     /* Count nested parens properly. */
     192        1336 :     else if (c == '(')
     193          74 :         paren_depth++;
     194        1262 :     else if (c == ')') {
     195          74 :         paren_depth--;
     196             :         /*
     197             :          * If we find unbalanced parens, we must have started inside a
     198             :          * declaration.
     199             :          */
     200          74 :         if (paren_depth < 0)
     201           0 :         return false;
     202        1188 :     } else if (paren_depth == 0) {
     203             :         /* We are outside any parentheses or comments. */
     204         198 :         if (c == '{')
     205          56 :         return true;
     206         142 :         else if (c == ';' || c == ',')
     207           8 :         return false;
     208             :     }
     209        1272 :     lastc = c;
     210             :     }
     211             :     /* Hit EOF --- for lack of anything better, assume "not a definition". */
     212           0 :     return false;
     213             : }
     214             : 
     215             : int
     216        2642 : lexi(struct parser_state *state)
     217             : {
     218             :     int         unary_delim;    /* this is set to 1 if the current token
     219             :                  * forces a following operator to be unary */
     220             :     int         code;       /* internal code to be returned */
     221             :     char        qchar;      /* the delimiter character for a string */
     222             : 
     223        2642 :     e_token = s_token;      /* point to start of place to save token */
     224        2642 :     unary_delim = false;
     225        2642 :     state->col_1 = state->last_nl;    /* tell world that this token started
     226             :                      * in column 1 iff the last thing
     227             :                      * scanned was a newline */
     228        2642 :     state->last_nl = false;
     229             : 
     230        3536 :     while (*buf_ptr == ' ' || *buf_ptr == '\t') {   /* get rid of blanks */
     231         894 :     state->col_1 = false;    /* leading blanks imply token is not in column
     232             :                  * 1 */
     233         894 :     if (++buf_ptr >= buf_end)
     234          42 :         fill_buffer();
     235             :     }
     236             : 
     237             :     /* Scan an alphanumeric token */
     238        2642 :     if (chartype[*buf_ptr & 127] == alphanum ||
     239        1800 :     (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
     240             :     /*
     241             :      * we have a character or number
     242             :      */
     243             :     struct templ *p;
     244             : 
     245         848 :     if (isdigit((unsigned char)*buf_ptr) ||
     246         854 :         (buf_ptr[0] == '.' && isdigit((unsigned char)buf_ptr[1]))) {
     247         106 :         int         seendot = 0,
     248         106 :                     seenexp = 0,
     249         106 :             seensfx = 0;
     250             : 
     251             :         /*
     252             :          * base 2, base 8, base 16:
     253             :          */
     254         128 :         if (buf_ptr[0] == '0' && buf_ptr[1] != '.') {
     255             :         int len;
     256             : 
     257          22 :         if (buf_ptr[1] == 'b' || buf_ptr[1] == 'B')
     258           4 :             len = strspn(buf_ptr + 2, "01") + 2;
     259          18 :         else if (buf_ptr[1] == 'x' || buf_ptr[1] == 'X')
     260           4 :             len = strspn(buf_ptr + 2, "0123456789ABCDEFabcdef") + 2;
     261             :         else
     262          14 :             len = strspn(buf_ptr + 1, "012345678") + 1;
     263          22 :         if (len > 0) {
     264          22 :             CHECK_SIZE_TOKEN(len);
     265          22 :             memcpy(e_token, buf_ptr, len);
     266          22 :             e_token += len;
     267          22 :             buf_ptr += len;
     268             :         }
     269             :         else
     270           0 :             diag2(1, "Unterminated literal");
     271             :         }
     272             :         else        /* base 10: */
     273             :         while (1) {
     274         120 :             if (*buf_ptr == '.') {
     275          14 :             if (seendot)
     276           0 :                 break;
     277             :             else
     278          14 :                 seendot++;
     279             :             }
     280         120 :             CHECK_SIZE_TOKEN(3);
     281         120 :             *e_token++ = *buf_ptr++;
     282         120 :             if (!isdigit((unsigned char)*buf_ptr) && *buf_ptr != '.') {
     283          84 :             if ((*buf_ptr != 'E' && *buf_ptr != 'e') || seenexp)
     284             :                 break;
     285             :             else {
     286           0 :                 seenexp++;
     287           0 :                 seendot++;
     288           0 :                 *e_token++ = *buf_ptr++;
     289           0 :                 if (*buf_ptr == '+' || *buf_ptr == '-')
     290           0 :                 *e_token++ = *buf_ptr++;
     291             :             }
     292             :             }
     293             :         }
     294             : 
     295             :         while (1) {
     296         134 :         CHECK_SIZE_TOKEN(2);
     297         134 :         if (!(seensfx & 1) && (*buf_ptr == 'U' || *buf_ptr == 'u')) {
     298          12 :             *e_token++ = *buf_ptr++;
     299          12 :             seensfx |= 1;
     300          12 :             continue;
     301             :         }
     302         122 :         if (!(seensfx & 2) && (strchr("fFlL", *buf_ptr) != NULL)) {
     303          16 :             if (buf_ptr[1] == buf_ptr[0])
     304           0 :                 *e_token++ = *buf_ptr++;
     305          16 :             *e_token++ = *buf_ptr++;
     306          16 :             seensfx |= 2;
     307          16 :             continue;
     308             :         }
     309         106 :         break;
     310             :         }
     311             :     }
     312             :     else
     313        4112 :         while (chartype[*buf_ptr & 127] == alphanum || *buf_ptr == BACKSLASH) {
     314             :         /* fill_buffer() terminates buffer with newline */
     315        3370 :         if (*buf_ptr == BACKSLASH) {
     316           0 :             if (*(buf_ptr + 1) == '\n') {
     317           0 :             buf_ptr += 2;
     318           0 :             if (buf_ptr >= buf_end)
     319           0 :                 fill_buffer();
     320             :             } else
     321           0 :                 break;
     322             :         }
     323        3370 :         CHECK_SIZE_TOKEN(1);
     324             :         /* copy it over */
     325        3370 :         *e_token++ = *buf_ptr++;
     326        3370 :         if (buf_ptr >= buf_end)
     327           0 :             fill_buffer();
     328             :         }
     329         848 :     *e_token = '\0';
     330             : 
     331         848 :     if (s_token[0] == 'L' && s_token[1] == '\0' &&
     332           4 :           (*buf_ptr == '"' || *buf_ptr == '\''))
     333           4 :         return (strpfx);
     334             : 
     335        1274 :     while (*buf_ptr == ' ' || *buf_ptr == '\t') {   /* get rid of blanks */
     336         430 :         if (++buf_ptr >= buf_end)
     337          32 :         fill_buffer();
     338             :     }
     339         844 :     state->keyword = 0;
     340         844 :     if (state->last_token == structure && !state->p_l_follow) {
     341             :                 /* if last token was 'struct' and we're not
     342             :                  * in parentheses, then this token
     343             :                  * should be treated as a declaration */
     344          10 :         state->last_u_d = true;
     345          10 :         return (decl);
     346             :     }
     347             :     /*
     348             :      * Operator after identifier is binary unless last token was 'struct'
     349             :      */
     350         834 :     state->last_u_d = (state->last_token == structure);
     351             : 
     352         834 :     p = bsearch(s_token,
     353             :         specials,
     354             :         sizeof(specials) / sizeof(specials[0]),
     355             :         sizeof(specials[0]),
     356             :         strcmp_type);
     357         834 :     if (p == NULL) {    /* not a special keyword... */
     358             :         char *u;
     359             : 
     360             :         /* ... so maybe a type_t or a typedef */
     361         502 :         if ((auto_typedefs && ((u = strrchr(s_token, '_')) != NULL) &&
     362         596 :             strcmp(u, "_t") == 0) || (typename_top >= 0 &&
     363          94 :           bsearch(s_token, typenames, typename_top + 1,
     364             :             sizeof(typenames[0]), strcmp_type))) {
     365           8 :         state->keyword = 4;  /* a type name */
     366           8 :         state->last_u_d = true;
     367           8 :             goto found_typename;
     368             :         }
     369             :     } else {            /* we have a keyword */
     370         332 :         state->keyword = p->rwcode;
     371         332 :         state->last_u_d = true;
     372         332 :         switch (p->rwcode) {
     373           2 :         case 7:     /* it is a switch */
     374           2 :         return (swstmt);
     375           4 :         case 8:     /* a case or default */
     376           4 :         return (casestmt);
     377             : 
     378             :         case 3:     /* a "struct" */
     379             :         /* FALLTHROUGH */
     380             :         case 4:     /* one of the declaration keywords */
     381         256 :         found_typename:
     382         256 :         if (state->p_l_follow) {
     383             :             /* inside parens: cast, param list, offsetof or sizeof */
     384          94 :             state->cast_mask |= (1 << state->p_l_follow) & ~state->not_cast_mask;
     385             :         }
     386         256 :         if (state->last_token == period || state->last_token == unary_op) {
     387           4 :             state->keyword = 0;
     388           4 :             break;
     389             :         }
     390         252 :         if (p != NULL && p->rwcode == 3)
     391          36 :             return (structure);
     392         216 :         if (state->p_l_follow)
     393          74 :             break;
     394         142 :         return (decl);
     395             : 
     396          24 :         case 5:     /* if, while, for */
     397          24 :         return (sp_paren);
     398             : 
     399          14 :         case 6:     /* do, else */
     400          14 :         return (sp_nparen);
     401             : 
     402          18 :         case 10:        /* storage class specifier */
     403          18 :         return (storage);
     404             : 
     405          12 :         case 11:        /* typedef */
     406          12 :         return (type_def);
     407             : 
     408          10 :         default:        /* all others are treated like any other
     409             :                  * identifier */
     410          10 :         return (ident);
     411             :         }           /* end of switch */
     412             :     }           /* end of if (found_it) */
     413         572 :     if (*buf_ptr == '(' && state->tos <= 1 && state->ind_level == 0 &&
     414          68 :         state->in_parameter_declaration == 0 && state->block_init == 0) {
     415          64 :         if (is_func_definition(buf_ptr)) {
     416          56 :         strncpy(state->procname, token, sizeof state->procname - 1);
     417          56 :         if (state->in_decl)
     418          54 :             state->in_parameter_declaration = 1;
     419          56 :         return (funcname);
     420             :         }
     421             :     }
     422             :     /*
     423             :      * The following hack attempts to guess whether or not the current
     424             :      * token is in fact a declaration keyword -- one that has been
     425             :      * typedefd
     426             :      */
     427         508 :     else if (!state->p_l_follow && !state->block_init &&
     428         198 :         !state->in_stmt &&
     429          48 :         ((*buf_ptr == '*' && buf_ptr[1] != '=') ||
     430          42 :         isalpha((unsigned char)*buf_ptr)) &&
     431          12 :         (state->last_token == semicolon || state->last_token == lbrace ||
     432           0 :         state->last_token == rbrace)) {
     433          12 :         state->keyword = 4;  /* a type name */
     434          12 :         state->last_u_d = true;
     435          12 :         return decl;
     436             :     }
     437         504 :     if (state->last_token == decl)   /* if this is a declared variable,
     438             :                      * then following sign is unary */
     439          76 :         state->last_u_d = true;  /* will make "int a -1" work */
     440         504 :     return (ident);     /* the ident is not in the list */
     441             :     }               /* end of processing for alphanum character */
     442             : 
     443             :     /* Scan a non-alphanumeric token */
     444             : 
     445        1794 :     CHECK_SIZE_TOKEN(3);        /* things like "<<=" */
     446        1794 :     *e_token++ = *buf_ptr;      /* if it is only a one-character token, it is
     447             :                  * moved here */
     448        1794 :     *e_token = '\0';
     449        1794 :     if (++buf_ptr >= buf_end)
     450         598 :     fill_buffer();
     451             : 
     452        1794 :     switch (*token) {
     453         686 :     case '\n':
     454         686 :     unary_delim = state->last_u_d;
     455         686 :     state->last_nl = true;   /* remember that we just had a newline */
     456         686 :     code = (had_eof ? 0 : newline);
     457             : 
     458             :     /*
     459             :      * if data has been exhausted, the newline is a dummy, and we should
     460             :      * return code to stop
     461             :      */
     462         686 :     break;
     463             : 
     464           4 :     case '\'':          /* start of quoted character */
     465             :     case '"':          /* start of string */
     466           4 :     qchar = *token;
     467             :     do {            /* copy the string */
     468             :         while (1) {     /* move one character or [/<char>]<char> */
     469          14 :         if (*buf_ptr == '\n') {
     470           0 :             diag2(1, "Unterminated literal");
     471           0 :             goto stop_lit;
     472             :         }
     473          14 :         CHECK_SIZE_TOKEN(2);
     474          14 :         *e_token = *buf_ptr++;
     475          14 :         if (buf_ptr >= buf_end)
     476           0 :             fill_buffer();
     477          14 :         if (*e_token == BACKSLASH) {    /* if escape, copy extra char */
     478           0 :             if (*buf_ptr == '\n')   /* check for escaped newline */
     479           0 :             ++line_no;
     480           0 :             *++e_token = *buf_ptr++;
     481           0 :             ++e_token;  /* we must increment this again because we
     482             :                  * copied two chars */
     483           0 :             if (buf_ptr >= buf_end)
     484           0 :             fill_buffer();
     485             :         }
     486             :         else
     487          14 :             break;  /* we copied one character */
     488             :         }           /* end of while (1) */
     489          14 :     } while (*e_token++ != qchar);
     490           4 : stop_lit:
     491           4 :     code = ident;
     492           4 :     break;
     493             : 
     494         156 :     case ('('):
     495             :     case ('['):
     496         156 :     unary_delim = true;
     497         156 :     code = lparen;
     498         156 :     break;
     499             : 
     500         156 :     case (')'):
     501             :     case (']'):
     502         156 :     code = rparen;
     503         156 :     break;
     504             : 
     505          22 :     case '#':
     506          22 :     unary_delim = state->last_u_d;
     507          22 :     code = preesc;
     508          22 :     break;
     509             : 
     510           0 :     case '?':
     511           0 :     unary_delim = true;
     512           0 :     code = question;
     513           0 :     break;
     514             : 
     515          10 :     case (':'):
     516          10 :     code = colon;
     517          10 :     unary_delim = true;
     518          10 :     break;
     519             : 
     520         148 :     case (';'):
     521         148 :     unary_delim = true;
     522         148 :     code = semicolon;
     523         148 :     break;
     524             : 
     525         114 :     case ('{'):
     526         114 :     unary_delim = true;
     527             : 
     528             :     /*
     529             :      * if (state->in_or_st) state->block_init = 1;
     530             :      */
     531             :     /* ?    code = state->block_init ? lparen : lbrace; */
     532         114 :     code = lbrace;
     533         114 :     break;
     534             : 
     535          82 :     case ('}'):
     536          82 :     unary_delim = true;
     537             :     /* ?    code = state->block_init ? rparen : rbrace; */
     538          82 :     code = rbrace;
     539          82 :     break;
     540             : 
     541           0 :     case 014:           /* a form feed */
     542           0 :     unary_delim = state->last_u_d;
     543           0 :     state->last_nl = true;   /* remember this so we can set 'state->col_1'
     544             :                  * right */
     545           0 :     code = form_feed;
     546           0 :     break;
     547             : 
     548         110 :     case (','):
     549         110 :     unary_delim = true;
     550         110 :     code = comma;
     551         110 :     break;
     552             : 
     553           8 :     case '.':
     554           8 :     unary_delim = false;
     555           8 :     code = period;
     556           8 :     break;
     557             : 
     558          12 :     case '-':
     559             :     case '+':           /* check for -, +, --, ++ */
     560          12 :     code = (state->last_u_d ? unary_op : binary_op);
     561          12 :     unary_delim = true;
     562             : 
     563          12 :     if (*buf_ptr == token[0]) {
     564             :         /* check for doubled character */
     565           0 :         *e_token++ = *buf_ptr++;
     566             :         /* buffer overflow will be checked at end of loop */
     567           0 :         if (state->last_token == ident || state->last_token == rparen) {
     568           0 :         code = (state->last_u_d ? unary_op : postop);
     569             :         /* check for following ++ or -- */
     570           0 :         unary_delim = false;
     571             :         }
     572             :     }
     573          12 :     else if (*buf_ptr == '=')
     574             :         /* check for operator += */
     575           0 :         *e_token++ = *buf_ptr++;
     576          12 :     else if (*buf_ptr == '>') {
     577             :         /* check for operator -> */
     578           4 :         *e_token++ = *buf_ptr++;
     579           4 :         unary_delim = false;
     580           4 :         code = unary_op;
     581           4 :         state->want_blank = false;
     582             :     }
     583          12 :     break;          /* buffer overflow will be checked at end of
     584             :                  * switch */
     585             : 
     586          50 :     case '=':
     587          50 :     if (state->in_or_st)
     588          44 :         state->block_init = 1;
     589             : #ifdef undef
     590             :     if (chartype[*buf_ptr & 127] == opchar) {   /* we have two char assignment */
     591             :         e_token[-1] = *buf_ptr++;
     592             :         if ((e_token[-1] == '<' || e_token[-1] == '>') && e_token[-1] == *buf_ptr)
     593             :         *e_token++ = *buf_ptr++;
     594             :         *e_token++ = '=';   /* Flip =+ to += */
     595             :         *e_token = 0;
     596             :     }
     597             : #else
     598          50 :     if (*buf_ptr == '=') {/* == */
     599           0 :         *e_token++ = '=';   /* Flip =+ to += */
     600           0 :         buf_ptr++;
     601           0 :         *e_token = 0;
     602             :     }
     603             : #endif
     604          50 :     code = binary_op;
     605          50 :     unary_delim = true;
     606          50 :     break;
     607             :     /* can drop thru!!! */
     608             : 
     609           8 :     case '>':
     610             :     case '<':
     611             :     case '!':           /* ops like <, <<, <=, !=, etc */
     612           8 :     if (*buf_ptr == '>' || *buf_ptr == '<' || *buf_ptr == '=') {
     613           8 :         *e_token++ = *buf_ptr;
     614           8 :         if (++buf_ptr >= buf_end)
     615           0 :         fill_buffer();
     616             :     }
     617           8 :     if (*buf_ptr == '=')
     618           0 :         *e_token++ = *buf_ptr++;
     619           8 :     code = (state->last_u_d ? unary_op : binary_op);
     620           8 :     unary_delim = true;
     621           8 :     break;
     622             : 
     623          92 :     case '*':
     624          92 :     unary_delim = true;
     625          92 :     if (!state->last_u_d) {
     626          12 :         if (*buf_ptr == '=')
     627           0 :         *e_token++ = *buf_ptr++;
     628          12 :         code = binary_op;
     629          12 :         break;
     630             :     }
     631         102 :     while (*buf_ptr == '*' || isspace((unsigned char)*buf_ptr)) {
     632          22 :         if (*buf_ptr == '*') {
     633           6 :         CHECK_SIZE_TOKEN(1);
     634           6 :         *e_token++ = *buf_ptr;
     635             :         }
     636          22 :         if (++buf_ptr >= buf_end)
     637           4 :         fill_buffer();
     638             :     }
     639          80 :     code = unary_op;
     640          80 :     break;
     641             : 
     642         136 :     default:
     643         136 :     if (token[0] == '/' && *buf_ptr == '*') {
     644             :         /* it is start of comment */
     645         134 :         *e_token++ = '*';
     646             : 
     647         134 :         if (++buf_ptr >= buf_end)
     648           0 :         fill_buffer();
     649             : 
     650         134 :         code = comment;
     651         134 :         unary_delim = state->last_u_d;
     652         134 :         break;
     653             :     }
     654           2 :     while (*(e_token - 1) == *buf_ptr || *buf_ptr == '=') {
     655             :         /*
     656             :          * handle ||, &&, etc, and also things as in int *****i
     657             :          */
     658           0 :         CHECK_SIZE_TOKEN(1);
     659           0 :         *e_token++ = *buf_ptr;
     660           0 :         if (++buf_ptr >= buf_end)
     661           0 :         fill_buffer();
     662             :     }
     663           2 :     code = (state->last_u_d ? unary_op : binary_op);
     664           2 :     unary_delim = true;
     665             : 
     666             : 
     667             :     }               /* end of switch */
     668        1794 :     if (buf_ptr >= buf_end)  /* check for input buffer empty */
     669           0 :     fill_buffer();
     670        1794 :     state->last_u_d = unary_delim;
     671        1794 :     CHECK_SIZE_TOKEN(1);
     672        1794 :     *e_token = '\0';        /* null terminate the token */
     673        1794 :     return (code);
     674             : }
     675             : 
     676             : void
     677          38 : alloc_typenames(void)
     678             : {
     679             : 
     680          38 :     typenames = (const char **)malloc(sizeof(typenames[0]) *
     681          38 :         (typename_count = 16));
     682          38 :     if (typenames == NULL)
     683           0 :     err(1, NULL);
     684          38 : }
     685             : 
     686             : void
     687           6 : add_typename(const char *key)
     688             : {
     689             :     int comparison;
     690             :     const char *copy;
     691             : 
     692           6 :     if (typename_top + 1 >= typename_count) {
     693           0 :     typenames = realloc((void *)typenames,
     694           0 :         sizeof(typenames[0]) * (typename_count *= 2));
     695           0 :     if (typenames == NULL)
     696           0 :         err(1, NULL);
     697             :     }
     698           6 :     if (typename_top == -1)
     699           4 :     typenames[++typename_top] = copy = strdup(key);
     700           2 :     else if ((comparison = strcmp(key, typenames[typename_top])) >= 0) {
     701             :     /* take advantage of sorted input */
     702           0 :     if (comparison == 0)    /* remove duplicates */
     703           0 :         return;
     704           0 :     typenames[++typename_top] = copy = strdup(key);
     705             :     }
     706             :     else {
     707             :     int p;
     708             : 
     709           2 :     for (p = 0; (comparison = strcmp(key, typenames[p])) > 0; p++)
     710             :         /* find place for the new key */;
     711           2 :     if (comparison == 0)    /* remove duplicates */
     712           0 :         return;
     713           2 :     memmove(&typenames[p + 1], &typenames[p],
     714           2 :         sizeof(typenames[0]) * (++typename_top - p));
     715           2 :     typenames[p] = copy = strdup(key);
     716             :     }
     717             : 
     718           6 :     if (copy == NULL)
     719           0 :     err(1, NULL);
     720             : }

Generated by: LCOV version 1.14