LCOV - code coverage report
Current view: top level - rsc/source/rscpp - cpp4.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 166 233 71.2 %
Date: 2012-08-25 Functions: 10 10 100.0 %
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 101 164 61.6 %

           Branch data     Line data    Source code
       1                 :            : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
       2                 :            : /*
       3                 :            :  * This file is part of the LibreOffice project.
       4                 :            :  *
       5                 :            :  * This Source Code Form is subject to the terms of the Mozilla Public
       6                 :            :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       7                 :            :  * file, You can obtain one at http://mozilla.org/MPL/2.0/.
       8                 :            :  *
       9                 :            :  * This file incorporates work covered by the following license notice:
      10                 :            :  *
      11                 :            :  *   Licensed to the Apache Software Foundation (ASF) under one or more
      12                 :            :  *   contributor license agreements. See the NOTICE file distributed
      13                 :            :  *   with this work for additional information regarding copyright
      14                 :            :  *   ownership. The ASF licenses this file to you under the Apache
      15                 :            :  *   License, Version 2.0 (the "License"); you may not use this file
      16                 :            :  *   except in compliance with the License. You may obtain a copy of
      17                 :            :  *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
      18                 :            :  */
      19                 :            : 
      20                 :            : #include        <sal/types.h>
      21                 :            : #include        <stdio.h>
      22                 :            : #include        <ctype.h>
      23                 :            : #include        "cppdef.h"
      24                 :            : #include        "cpp.h"
      25                 :            : /*
      26                 :            :  * parm[], parmp, and parlist[] are used to store #define() argument
      27                 :            :  * lists.  nargs contains the actual number of parameters stored.
      28                 :            :  */
      29                 :            : static char     parm[NPARMWORK + 1];    /* define param work buffer     */
      30                 :            : static char     *parmp;                 /* Free space in parm           */
      31                 :            : static char     *parlist[LASTPARM];     /* -> start of each parameter   */
      32                 :            : static int      nargs;                  /* Parameters for this macro    */
      33                 :            : 
      34                 :       1320 : void InitCpp4()
      35                 :            : {
      36                 :            :     int i;
      37         [ +  + ]:  337921320 :     for( i = 0; i < NPARMWORK; i++ )
      38                 :  337920000 :         parm[ i ] = 0;
      39         [ +  + ]:     335280 :     for( i = 0; i < LASTPARM; i++ )
      40                 :     333960 :         parlist[ i ] = NULL;
      41                 :            : 
      42                 :       1320 :     nargs = 0;
      43                 :       1320 : }
      44                 :            : 
      45                 :            : 
      46                 :    2229068 : void dodefine()
      47                 :            : /*
      48                 :            :  * Called from control when a #define is scanned.  This module
      49                 :            :  * parses formal parameters and the replacement string.  When
      50                 :            :  * the formal parameter name is encountered in the replacement
      51                 :            :  * string, it is replaced by a character in the range 128 to
      52                 :            :  * 128+NPARAM (this allows up to 32 parameters within the
      53                 :            :  * Dec Multinational range).  If cpp is ported to an EBCDIC
      54                 :            :  * machine, you will have to make other arrangements.
      55                 :            :  *
      56                 :            :  * There is some special case code to distinguish
      57                 :            :  *      #define foo     bar
      58                 :            :  * from #define foo()   bar
      59                 :            :  *
      60                 :            :  * Also, we make sure that
      61                 :            :  *      #define foo     foo
      62                 :            :  * expands to "foo" but doesn't put cpp into an infinite loop.
      63                 :            :  *
      64                 :            :  * A warning message is printed if you redefine a symbol to a
      65                 :            :  * different text.  I.e,
      66                 :            :  *      #define foo     123
      67                 :            :  *      #define foo     123
      68                 :            :  * is ok, but
      69                 :            :  *      #define foo     123
      70                 :            :  *      #define foo     +123
      71                 :            :  * is not.
      72                 :            :  *
      73                 :            :  * The following subroutines are called from define():
      74                 :            :  * checkparm    called when a token is scanned.  It checks through the
      75                 :            :  *              array of formal parameters.  If a match is found, the
      76                 :            :  *              token is replaced by a control byte which will be used
      77                 :            :  *              to locate the parameter when the macro is expanded.
      78                 :            :  * textput      puts a string in the macro work area (parm[]), updating
      79                 :            :  *              parmp to point to the first free byte in parm[].
      80                 :            :  *              textput() tests for work buffer overflow.
      81                 :            :  * charput      puts a single character in the macro work area (parm[])
      82                 :            :  *              in a manner analogous to textput().
      83                 :            :  */
      84                 :            : {
      85                 :            :         register int            c;
      86                 :            :         register DEFBUF         *dp;            /* -> new definition    */
      87                 :            :         int                     isredefine;     /* TRUE if redefined    */
      88                 :    2229068 :         char                    *old = 0;       /* Remember redefined   */
      89                 :            : 
      90         [ -  + ]:    2229068 :         if (type[(c = skipws())] != LET)
      91                 :          0 :             goto bad_define;
      92                 :    2229068 :         isredefine = FALSE;                     /* Set if redefining    */
      93         [ +  + ]:    2229068 :         if ((dp = lookid(c)) == NULL)           /* If not known now     */
      94                 :    2201218 :             dp = defendel(token, FALSE);        /* Save the name        */
      95                 :            :         else {                                  /* It's known:          */
      96                 :      27850 :             isredefine = TRUE;                  /* Remember this fact   */
      97                 :      27850 :             old = dp->repl;                     /* Remember replacement */
      98                 :      27850 :             dp->repl = NULL;                    /* No replacement now   */
      99                 :            :         }
     100                 :    2229068 :         parlist[0] = parmp = parm;              /* Setup parm buffer    */
     101         [ +  + ]:    2229068 :         if ((c = get()) == '(') {               /* With arguments?      */
     102                 :       2900 :             nargs = 0;                          /* Init formals counter */
     103                 :            :             do {                                /* Collect formal parms */
     104         [ -  + ]:       3302 :                 if (nargs >= LASTPARM)
     105                 :          0 :                     cfatal("Too many arguments for macro", NULLST);
     106         [ +  + ]:       3302 :                 else if ((c = skipws()) == ')')
     107                 :          4 :                     break;                      /* Got them all         */
     108         [ -  + ]:       3298 :                 else if (type[c] != LET)        /* Bad formal syntax    */
     109                 :          0 :                     goto bad_define;
     110                 :       3298 :                 scanid(c);                      /* Get the formal param */
     111                 :       3298 :                 parlist[nargs++] = parmp;       /* Save its start       */
     112                 :       3298 :                 textput(token);                 /* Save text in parm[]  */
     113         [ +  + ]:       3298 :             } while ((c = skipws()) == ',');    /* Get another argument */
     114         [ -  + ]:       2900 :             if (c != ')')                       /* Must end at )        */
     115                 :          0 :                 goto bad_define;
     116                 :       2900 :             c = ' ';                            /* Will skip to body    */
     117                 :            :         }
     118                 :            :         else {
     119                 :            :             /*
     120                 :            :              * DEF_NOARGS is needed to distinguish between
     121                 :            :              * "#define foo" and "#define foo()".
     122                 :            :              */
     123                 :    2226168 :             nargs = DEF_NOARGS;                 /* No () parameters     */
     124                 :            :         }
     125         [ +  + ]:    2229068 :         if (type[c] == SPA)                     /* At whitespace?       */
     126                 :    2216750 :             c = skipws();                       /* Not any more.        */
     127                 :    2229068 :         workp = work;                           /* Replacement put here */
     128                 :    2229068 :         inmacro = TRUE;                         /* Keep \<newline> now  */
     129 [ +  - ][ +  + ]:   15662932 :         while (c != EOF_CHAR && c != '\n') {    /* Compile macro body   */
     130                 :            : #if OK_CONCAT
     131                 :            : #if COMMENT_INVISIBLE
     132                 :            :             if (c == COM_SEP) {                 /* Token concatenation? */
     133                 :            :                 save(TOK_SEP);                  /* Stuff a delimiter    */
     134                 :            :                 c = get();
     135                 :            : #else
     136         [ +  + ]:   13433864 :             if (c == '#') {                     /* Token concatenation? */
     137 [ +  + ][ -  + ]:       1108 :                 while (workp > work && type[(int)workp[-1]] == SPA)
     138                 :          0 :                     --workp;                    /* Erase leading spaces */
     139                 :       1108 :                 save(TOK_SEP);                  /* Stuff a delimiter    */
     140                 :       1108 :                 c = skipws();                   /* Eat whitespace       */
     141                 :            : #endif
     142         [ -  + ]:       1108 :                 if (type[c] == LET)             /* Another token here?  */
     143                 :            :                     ;                           /* Stuff it normally    */
     144         [ #  # ]:          0 :                 else if (type[c] == DIG) {      /* Digit string after?  */
     145         [ #  # ]:          0 :                     while (type[c] == DIG) {    /* Stuff the digits     */
     146                 :          0 :                         save(c);
     147                 :          0 :                         c = get();
     148                 :            :                     }
     149                 :          0 :                     save(TOK_SEP);              /* Delimit 2nd token    */
     150                 :            :                 }
     151                 :            :                 else {
     152                 :            : #if ! COMMENT_INVISIBLE
     153                 :          0 :                     ciwarn("Strange character after # (%d.)", c);
     154                 :            : #endif
     155                 :            :                 }
     156                 :       1108 :                 continue;
     157                 :            :             }
     158                 :            : #endif
     159   [ +  +  +  +  :   13432756 :             switch (type[c]) {
                   +  + ]
     160                 :            :             case LET:
     161                 :    1700580 :                 checkparm(c, dp);               /* Might be a formal    */
     162                 :    1700580 :                 break;
     163                 :            : 
     164                 :            :             case DIG:                           /* Number in mac. body  */
     165                 :            :             case DOT:                           /* Maybe a float number */
     166                 :    1763636 :                 scannumber(c, save);            /* Scan it off          */
     167                 :    1763636 :                 break;
     168                 :            : 
     169                 :            :             case QUO:                           /* String in mac. body  */
     170                 :            : #if STRING_FORMAL
     171                 :            :                 stparmscan(c, dp);              /* Do string magic      */
     172                 :            : #else
     173                 :     414144 :                 stparmscan(c);
     174                 :            : #endif
     175                 :     414144 :                 break;
     176                 :            : 
     177                 :            :             case BSH:                           /* Backslash            */
     178                 :      37902 :                 save('\\');
     179         [ +  - ]:      37902 :                 if ((c = get()) == '\n')
     180                 :      37902 :                     wrongline = TRUE;
     181                 :      37902 :                 save(c);
     182                 :      37902 :                 break;
     183                 :            : 
     184                 :            :             case SPA:                           /* Absorb whitespace    */
     185                 :            :                 /*
     186                 :            :                  * Note: the "end of comment" marker is passed on
     187                 :            :                  * to allow comments to separate tokens.
     188                 :            :                  */
     189         [ +  + ]:    4688984 :                 if (workp[-1] == ' ')           /* Absorb multiple      */
     190                 :     969936 :                     break;                      /* spaces               */
     191         [ -  + ]:    3719048 :                 else if (c == '\t')
     192                 :          0 :                     c = ' ';                    /* Normalize tabs       */
     193                 :            :                 /* Fall through to store character                      */
     194                 :            :             default:                            /* Other character      */
     195                 :    8546558 :                 save(c);
     196                 :    8546558 :                 break;
     197                 :            :             }
     198                 :   13432756 :             c = get();
     199                 :            :         }
     200                 :    2229068 :         inmacro = FALSE;                        /* Stop newline hack    */
     201                 :    2229068 :         unget();                                /* For control check    */
     202 [ +  + ][ +  + ]:    2229068 :         if (workp > work && workp[-1] == ' ')   /* Drop trailing blank  */
     203                 :      52758 :             workp--;
     204                 :    2229068 :         *workp = EOS;                           /* Terminate work       */
     205                 :    2229068 :         dp->repl = savestring(work);            /* Save the string      */
     206                 :    2229068 :         dp->nargs = nargs;                      /* Save arg count       */
     207                 :            : #if OSL_DEBUG_LEVEL > 1
     208                 :            :         if (debug)
     209                 :            :             dumpadef("macro definition", dp);
     210                 :            :         else if (bDumpDefs)
     211                 :            :             dumpadef(NULL, dp);
     212                 :            : #endif
     213         [ +  + ]:    2229068 :         if (isredefine) {                       /* Error if redefined   */
     214 [ +  - ][ +  - ]:      27850 :             if ((old != NULL && dp->repl != NULL && !streq(old, dp->repl))
                 [ +  - ]
     215 [ -  + ][ #  # ]:      27850 :              || (old == NULL && dp->repl != NULL)
     216 [ +  - ][ -  + ]:      27850 :              || (old != NULL && dp->repl == NULL)) {
     217                 :            : #ifdef STRICT_UNDEF
     218                 :            :                 cerror("Redefining defined variable \"%s\"", dp->name);
     219                 :            : #else
     220                 :          0 :                 cwarn("Redefining defined variable \"%s\"", dp->name);
     221                 :            : #endif
     222                 :            :             }
     223         [ +  - ]:      27850 :             if (old != NULL)                    /* We don't need the    */
     224                 :      27850 :                 free(old);                      /* old definition now.  */
     225                 :            :         }
     226                 :    2229068 :         return;
     227                 :            : 
     228                 :            : bad_define:
     229                 :          0 :         cerror("#define syntax error", NULLST);
     230                 :          0 :         inmacro = FALSE;                        /* Stop <newline> hack  */
     231                 :            : }
     232                 :            : 
     233                 :    1700580 : void checkparm(int c, DEFBUF* dp)
     234                 :            : /*
     235                 :            :  * Replace this param if it's defined.  Note that the macro name is a
     236                 :            :  * possible replacement token.  We stuff DEF_MAGIC in front of the token
     237                 :            :  * which is treated as a LETTER by the token scanner and eaten by
     238                 :            :  * the output routine.  This prevents the macro expander from
     239                 :            :  * looping if someone writes "#define foo foo".
     240                 :            :  */
     241                 :            : {
     242                 :            :         register int            i;
     243                 :            :         register char           *cp;
     244                 :            : 
     245                 :    1700580 :         scanid(c);                              /* Get parm to token[]  */
     246         [ +  + ]:    1740338 :         for (i = 0; i < nargs; i++) {           /* For each argument    */
     247         [ +  + ]:      44564 :             if (streq(parlist[i], token)) {     /* If it's known        */
     248                 :            : #ifdef SOLAR
     249                 :       4806 :                 save(DEL);
     250                 :            : #endif
     251                 :       4806 :                 save(i + MAC_PARM);             /* Save a magic cookie  */
     252                 :    1700580 :                 return;                         /* And exit the search  */
     253                 :            :             }
     254                 :            :         }
     255         [ -  + ]:    1695774 :         if (streq(dp->name, token))             /* Macro name in body?  */
     256                 :          0 :             save(DEF_MAGIC);                    /* Save magic marker    */
     257         [ +  + ]:   24773666 :         for (cp = token; *cp != EOS;)           /* And save             */
     258                 :   23077892 :             save(*cp++);                        /* The token itself     */
     259                 :            : }
     260                 :            : 
     261                 :            : #if STRING_FORMAL
     262                 :            : void stparmscan(delim, dp)
     263                 :            : int             delim;
     264                 :            : register DEFBUF *dp;
     265                 :            : /*
     266                 :            :  * Scan the string (starting with the given delimiter).
     267                 :            :  * The token is replaced if it is the only text in this string or
     268                 :            :  * character constant.  The algorithm follows checkparm() above.
     269                 :            :  * Note that scanstring() has approved of the string.
     270                 :            :  */
     271                 :            : {
     272                 :            :         register int            c;
     273                 :            : 
     274                 :            :         /*
     275                 :            :          * Warning -- this code hasn't been tested for a while.
     276                 :            :          * It exists only to preserve compatibility with earlier
     277                 :            :          * implementations of cpp.  It is not part of the Draft
     278                 :            :          * ANSI Standard C language.
     279                 :            :          */
     280                 :            :         save(delim);
     281                 :            :         instring = TRUE;
     282                 :            :         while ((c = get()) != delim
     283                 :            :              && c != '\n'
     284                 :            :              && c != EOF_CHAR) {
     285                 :            :             if (type[c] == LET)                 /* Maybe formal parm    */
     286                 :            :                 checkparm(c, dp);
     287                 :            :             else {
     288                 :            :                 save(c);
     289                 :            :                 if (c == '\\')
     290                 :            :                     save(get());
     291                 :            :             }
     292                 :            :         }
     293                 :            :         instring = FALSE;
     294                 :            :         if (c != delim)
     295                 :            :             cerror("Unterminated string in macro body", NULLST);
     296                 :            :         save(c);
     297                 :            : }
     298                 :            : #else
     299                 :     414144 : void stparmscan(int delim)
     300                 :            : /*
     301                 :            :  * Normal string parameter scan.
     302                 :            :  */
     303                 :            : {
     304                 :            :         register char           *wp;
     305                 :            :         register int            i;
     306                 :            : 
     307                 :     414144 :         wp = workp;                     /* Here's where it starts       */
     308         [ -  + ]:     414144 :         if (!scanstring(delim, save))
     309                 :          0 :             return;                     /* Exit on scanstring error     */
     310                 :     414144 :         workp[-1] = EOS;                /* Erase trailing quote         */
     311                 :     414144 :         wp++;                           /* -> first string content byte */
     312         [ +  + ]:     415984 :         for (i = 0; i < nargs; i++) {
     313         [ -  + ]:       1840 :             if (streq(parlist[i], wp)) {
     314                 :            : #ifdef SOLAR
     315                 :          0 :                 *wp++ = DEL;
     316                 :          0 :                 *wp++ = MAC_PARM + PAR_MAC;     /* Stuff a magic marker */
     317                 :          0 :                 *wp++ = (char)(i + MAC_PARM);   /* Make a formal marker */
     318                 :          0 :                 *wp = wp[-4];                   /* Add on closing quote */
     319                 :          0 :                 workp = wp + 1;                 /* Reset string end     */
     320                 :            : #else
     321                 :            :                 *wp++ = MAC_PARM + PAR_MAC;     /* Stuff a magic marker */
     322                 :            :                 *wp++ = (i + MAC_PARM);         /* Make a formal marker */
     323                 :            :                 *wp = wp[-3];                   /* Add on closing quote */
     324                 :            :                 workp = wp + 1;                 /* Reset string end     */
     325                 :            : #endif
     326                 :          0 :                 return;
     327                 :            :             }
     328                 :            :         }
     329                 :     414144 :         workp[-1] = wp[-1];             /* Nope, reset end quote.       */
     330                 :            : }
     331                 :            : #endif
     332                 :            : 
     333                 :        210 : void doundef()
     334                 :            : /*
     335                 :            :  * Remove the symbol from the defined list.
     336                 :            :  * Called from the #control processor.
     337                 :            :  */
     338                 :            : {
     339                 :            :         register int            c;
     340                 :            : 
     341         [ -  + ]:        210 :         if (type[(c = skipws())] != LET)
     342                 :          0 :             cerror("Illegal #undef argument", NULLST);
     343                 :            :         else {
     344                 :        210 :             scanid(c);                          /* Get name to token[]  */
     345                 :        210 :             if (defendel(token, TRUE) == NULL) {
     346                 :            : #ifdef STRICT_UNDEF
     347                 :            :                 cwarn("Symbol \"%s\" not defined in #undef", token);
     348                 :            : #endif
     349                 :            :             }
     350                 :            :         }
     351                 :        210 : }
     352                 :            : 
     353                 :       3298 : void textput(char* text)
     354                 :            : /*
     355                 :            :  * Put the string in the parm[] buffer.
     356                 :            :  */
     357                 :            : {
     358                 :            :         register int    size;
     359                 :            : 
     360                 :       3298 :         size = strlen(text) + 1;
     361         [ -  + ]:       3298 :         if ((parmp + size) >= &parm[NPARMWORK])
     362                 :          0 :             cfatal("Macro work area overflow", NULLST);
     363                 :            :         else {
     364                 :       3298 :             strcpy(parmp, text);
     365                 :       3298 :             parmp += size;
     366                 :            :         }
     367                 :       3298 : }
     368                 :            : 
     369                 :      38790 : void charput(int c)
     370                 :            : /*
     371                 :            :  * Put the byte in the parm[] buffer.
     372                 :            :  */
     373                 :            : {
     374         [ -  + ]:      38790 :         if (parmp >= &parm[NPARMWORK])
     375                 :          0 :             cfatal("Macro work area overflow", NULLST);
     376                 :            :         else {
     377                 :      38790 :             *parmp++ = (char)c;
     378                 :            :         }
     379                 :      38790 : }
     380                 :            : 
     381                 :            : /*
     382                 :            :  *              M a c r o   E x p a n s i o n
     383                 :            :  */
     384                 :            : 
     385                 :            : static DEFBUF   *macro;         /* Catches start of infinite macro      */
     386                 :            : 
     387                 :     238180 : void expand(DEFBUF* tokenp)
     388                 :            : /*
     389                 :            :  * Expand a macro.  Called from the cpp mainline routine (via subroutine
     390                 :            :  * macroid()) when a token is found in the symbol table.  It calls
     391                 :            :  * expcollect() to parse actual parameters, checking for the correct number.
     392                 :            :  * It then creates a "file" containing a single line containing the
     393                 :            :  * macro with actual parameters inserted appropriately.  This is
     394                 :            :  * "pushed back" onto the input stream.  (When the get() routine runs
     395                 :            :  * off the end of the macro line, it will dismiss the macro itself.)
     396                 :            :  */
     397                 :            : {
     398                 :            :         register int            c;
     399                 :            :         register FILEINFO       *file;
     400                 :            :     extern FILEINFO     *getfile();
     401                 :            : 
     402                 :            : #if OSL_DEBUG_LEVEL > 1
     403                 :            :         if (debug)
     404                 :            :             dumpadef("expand entry", tokenp);
     405                 :            : #endif
     406                 :            :         /*
     407                 :            :          * If no macro is pending, save the name of this macro
     408                 :            :          * for an eventual error message.
     409                 :            :          */
     410         [ +  + ]:     238180 :         if (recursion++ == 0)
     411                 :      75464 :             macro = tokenp;
     412         [ -  + ]:     162716 :         else if (recursion == RECURSION_LIMIT) {
     413                 :          0 :             cerror("Recursive macro definition of \"%s\"", tokenp->name);
     414                 :          0 :             fprintf(stderr, "(Defined by \"%s\")\n", macro->name);
     415         [ #  # ]:          0 :             if (rec_recover) {
     416                 :            :                 do {
     417                 :          0 :                     c = get();
     418 [ #  # ][ #  # ]:          0 :                 } while (infile != NULL && infile->fp == NULL);
     419                 :          0 :                 unget();
     420                 :          0 :                 recursion = 0;
     421                 :          0 :                 return;
     422                 :            :             }
     423                 :            :         }
     424                 :            :         /*
     425                 :            :          * Here's a macro to expand.
     426                 :            :          */
     427                 :     238180 :         nargs = 0;                              /* Formals counter      */
     428                 :     238180 :         parmp = parm;                           /* Setup parm buffer    */
     429   [ -  -  +  + ]:     238180 :         switch (tokenp->nargs) {
     430                 :            :         case (-2):                              /* __LINE__             */
     431                 :          0 :             sprintf(work, "%d", line);
     432                 :          0 :             ungetstring(work);
     433                 :          0 :             break;
     434                 :            : 
     435                 :            :         case (-3):                              /* __FILE__             */
     436         [ #  # ]:          0 :             for (file = infile; file != NULL; file = file->parent) {
     437         [ #  # ]:          0 :                 if (file->fp != NULL) {
     438         [ #  # ]:          0 :                     sprintf(work, "\"%s\"", (file->progname != NULL)
     439                 :            :                         ? file->progname : file->filename);
     440                 :          0 :                     ungetstring(work);
     441                 :          0 :                     break;
     442                 :            :                 }
     443                 :            :             }
     444                 :          0 :             break;
     445                 :            : 
     446                 :            :         default:
     447                 :            :             /*
     448                 :            :              * Nothing funny about this macro.
     449                 :            :              */
     450         [ -  + ]:       2034 :             if (tokenp->nargs < 0)
     451                 :          0 :                 cfatal("Bug: Illegal __ macro \"%s\"", tokenp->name);
     452         [ -  + ]:       2034 :             while ((c = skipws()) == '\n')      /* Look for (, skipping */
     453                 :          0 :                 wrongline = TRUE;               /* spaces and newlines  */
     454         [ -  + ]:       2034 :             if (c != '(') {
     455                 :            :                 /*
     456                 :            :                  * If the programmer writes
     457                 :            :                  *      #define foo() ...
     458                 :            :                  *      ...
     459                 :            :                  *      foo [no ()]
     460                 :            :                  * just write foo to the output stream.
     461                 :            :                  */
     462                 :          0 :                 unget();
     463                 :          0 :                 cwarn("Macro \"%s\" needs arguments", tokenp->name);
     464                 :          0 :                 fputs(tokenp->name, pCppOut );
     465                 :          0 :                 return;
     466                 :            :             }
     467         [ +  - ]:       2034 :             else if (expcollect()) {            /* Collect arguments    */
     468         [ -  + ]:       2034 :                 if (tokenp->nargs != nargs) {   /* Should be an error?  */
     469                 :          0 :                     cwarn("Wrong number of macro arguments for \"%s\"",
     470                 :          0 :                         tokenp->name);
     471                 :            :                 }
     472                 :            : #if OSL_DEBUG_LEVEL > 1
     473                 :            :                 if (debug)
     474                 :            :                     dumpparm("expand");
     475                 :            : #endif
     476                 :            :             }                           /* Collect arguments            */
     477                 :            :         case DEF_NOARGS:                /* No parameters just stuffs    */
     478                 :     238180 :             expstuff(tokenp);           /* Do actual parameters         */
     479                 :            :         }                               /* nargs switch                 */
     480                 :            : }
     481                 :            : 
     482                 :            : FILE_LOCAL int
     483                 :       5106 : expcollect()
     484                 :            : /*
     485                 :            :  * Collect the actual parameters for this macro.  TRUE if ok.
     486                 :            :  */
     487                 :            : {
     488                 :            :         register int    c;
     489                 :            :         register int    paren;                  /* For embedded ()'s    */
     490                 :            :         for (;;) {
     491                 :       5106 :             paren = 0;                          /* Collect next arg.    */
     492         [ -  + ]:       5106 :             while ((c = skipws()) == '\n')      /* Skip over whitespace */
     493                 :          0 :                 wrongline = TRUE;               /* and newlines.        */
     494         [ +  + ]:       5106 :             if (c == ')') {                     /* At end of all args?  */
     495                 :            :                 /*
     496                 :            :                  * Note that there is a guard byte in parm[]
     497                 :            :                  * so we don't have to check for overflow here.
     498                 :            :                  */
     499                 :       2034 :                 *parmp = EOS;                   /* Make sure terminated */
     500                 :       2034 :                 break;                          /* Exit collection loop */
     501                 :            :             }
     502         [ -  + ]:       3072 :             else if (nargs >= LASTPARM)
     503                 :          0 :                 cfatal("Too many arguments in macro expansion", NULLST);
     504                 :       3072 :             parlist[nargs++] = parmp;           /* At start of new arg  */
     505                 :      35718 :             for (;; c = cget()) {               /* Collect arg's bytes  */
     506         [ -  + ]:      38790 :                 if (c == EOF_CHAR) {
     507                 :          0 :                     cerror("end of file within macro argument", NULLST);
     508                 :          0 :                     return (FALSE);             /* Sorry.               */
     509                 :            :                 }
     510         [ -  + ]:      38790 :                 else if (c == '\\') {           /* Quote next character */
     511                 :          0 :                     charput(c);                 /* Save the \ for later */
     512                 :          0 :                     charput(cget());            /* Save the next char.  */
     513                 :          0 :                     continue;                   /* And go get another   */
     514                 :            :                 }
     515         [ -  + ]:      38790 :                 else if (type[c] == QUO) {      /* Start of string?     */
     516                 :          0 :                     scanstring(c, charput);     /* Scan it off          */
     517                 :          0 :                     continue;                   /* Go get next char     */
     518                 :            :                 }
     519         [ +  + ]:      38790 :                 else if (c == '(')              /* Worry about balance  */
     520                 :         10 :                     paren++;                    /* To know about commas */
     521         [ +  + ]:      38780 :                 else if (c == ')') {            /* Other side too       */
     522         [ +  + ]:       1976 :                     if (paren == 0) {           /* At the end?          */
     523                 :       1966 :                         unget();                /* Look at it later     */
     524                 :       1966 :                         break;                  /* Exit arg getter.     */
     525                 :            :                     }
     526                 :         10 :                     paren--;                    /* More to come.        */
     527                 :            :                 }
     528 [ +  + ][ -  + ]:      36804 :                 else if (c == ',' && paren == 0) /* Comma delimits args */
     529                 :            :                     break;
     530         [ -  + ]:      35698 :                 else if (c == '\n')             /* Newline inside arg?  */
     531                 :          0 :                     wrongline = TRUE;           /* We'll need a #line   */
     532                 :      35718 :                 charput(c);                     /* Store this one       */
     533                 :      35718 :             }                                   /* Collect an argument  */
     534                 :       3072 :             charput(EOS);                       /* Terminate argument   */
     535                 :            : #if OSL_DEBUG_LEVEL > 1
     536                 :            :             if (debug)
     537                 :            :             fprintf( pCppOut, "parm[%d] = \"%s\"\n", nargs, parlist[nargs - 1]);
     538                 :            : #endif
     539                 :       3072 :         }                                       /* Collect all args.    */
     540                 :       2034 :         return (TRUE);                          /* Normal return        */
     541                 :            : }
     542                 :            : 
     543                 :            : FILE_LOCAL
     544                 :     238180 : void expstuff(DEFBUF* tokenp)
     545                 :            : /*
     546                 :            :  * Stuff the macro body, replacing formal parameters by actual parameters.
     547                 :            :  */
     548                 :            : {
     549                 :            :         register int    c;                      /* Current character    */
     550                 :            :         register char   *inp;                   /* -> repl string       */
     551                 :            :         register char   *defp;                  /* -> macro output buff */
     552                 :            :         int             size;                   /* Actual parm. size    */
     553                 :            :         char            *defend;                /* -> output buff end   */
     554                 :            :         int             string_magic;           /* String formal hack   */
     555                 :            :         FILEINFO        *file;                  /* Funny #include       */
     556                 :            :     extern FILEINFO *getfile();
     557                 :            : 
     558                 :     238180 :         file = getfile(NBUFF, tokenp->name);
     559                 :     238180 :         inp = tokenp->repl;                     /* -> macro replacement */
     560                 :     238180 :         defp = file->buffer;                    /* -> output buffer     */
     561                 :     238180 :         defend = defp + (NBUFF - 1);            /* Note its end         */
     562         [ +  - ]:     238180 :         if (inp != NULL) {
     563         [ +  + ]:    4491658 :             while ((c = (*inp++ & 0xFF)) != EOS) {
     564                 :            : #ifdef SOLAR
     565         [ +  + ]:    4253478 :                 if (c == DEL) {
     566                 :       4670 :                     c = (*inp++ & 0xFF);
     567                 :            : #else
     568                 :            :                 if (c >= MAC_PARM && c <= (MAC_PARM + PAR_MAC)) {
     569                 :            : #endif
     570                 :       4670 :                     string_magic = (c == (MAC_PARM + PAR_MAC));
     571         [ -  + ]:       4670 :                     if (string_magic)
     572                 :          0 :                         c = (*inp++ & 0xFF);
     573                 :            :                     /*
     574                 :            :                      * Replace formal parameter by actual parameter string.
     575                 :            :                      */
     576         [ +  - ]:       4670 :                     if ((c -= MAC_PARM) < nargs) {
     577                 :       4670 :                         size = strlen(parlist[c]);
     578         [ -  + ]:       4670 :                         if ((defp + size) >= defend)
     579                 :          0 :                             goto nospace;
     580                 :            :                         /*
     581                 :            :                          * Erase the extra set of quotes.
     582                 :            :                          */
     583 [ -  + ][ #  # ]:       4670 :                         if (string_magic && defp[-1] == parlist[c][0]) {
     584                 :          0 :                             strcpy(defp-1, parlist[c]);
     585                 :          0 :                             defp += (size - 2);
     586                 :            :                         }
     587                 :            :                         else {
     588                 :       4670 :                             strcpy(defp, parlist[c]);
     589                 :       4670 :                             defp += size;
     590                 :            :                         }
     591                 :            :                     }
     592                 :            :                 }
     593         [ -  + ]:    4248808 :                 else if (defp >= defend) {
     594                 :          0 : nospace:            cfatal("Out of space in macro \"%s\" arg expansion",
     595                 :          0 :                         tokenp->name);
     596                 :            :                 }
     597                 :            :                 else {
     598                 :    4248808 :                     *defp++ = (char)c;
     599                 :            :                 }
     600                 :            :             }
     601                 :            :         }
     602                 :     238180 :         *defp = EOS;
     603                 :            : #if OSL_DEBUG_LEVEL > 1
     604                 :            :         if (debug > 1)
     605                 :            :             fprintf( pCppOut, "macroline: \"%s\"\n", file->buffer);
     606                 :            : #endif
     607                 :     238180 : }
     608                 :            : 
     609                 :            : #if OSL_DEBUG_LEVEL > 1
     610                 :            : void dumpparm(char* why)
     611                 :            : /*
     612                 :            :  * Dump parameter list.
     613                 :            :  */
     614                 :            : {
     615                 :            :         register int    i;
     616                 :            : 
     617                 :            :     fprintf( pCppOut, "dump of %d parameters (%" SAL_PRI_SIZET "u bytes total) %s\n",
     618                 :            :             nargs, parmp - parm, why);
     619                 :            :         for (i = 0; i < nargs; i++) {
     620                 :            :         fprintf( pCppOut, "parm[%d] (%d) = \"%s\"\n",
     621                 :            :                 i + 1, (int)strlen(parlist[i]), parlist[i]);
     622                 :            :         }
     623                 :            : }
     624                 :            : #endif
     625                 :            : 
     626                 :            : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10