LCOV - code coverage report
Current view: top level - libreoffice/soltools/cpp - _macro.c (source / functions) Hit Total Coverage
Test: libreoffice_filtered.info Lines: 256 377 67.9 %
Date: 2012-12-27 Functions: 9 10 90.0 %
Legend: Lines: hit not hit

          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             : #ifdef _MSC_VER
      21             : #   define _POSIX_
      22             : #endif
      23             : #include <stdio.h>
      24             : #include <stdlib.h>
      25             : #include <string.h>
      26             : #if defined(__IBMC__) || defined(__EMX__)
      27             : #   define PATH_MAX _MAX_PATH
      28             : #endif
      29             : #include <limits.h>
      30             : 
      31             : #include "cpp.h"
      32             : 
      33             : #define NCONCAT 16384
      34             : 
      35             : /*
      36             :  * do a macro definition.  tp points to the name being defined in the line
      37             :  */
      38             : void
      39        7446 :     dodefine(Tokenrow * trp)
      40             : {
      41             :     Token *tp;
      42             :     Nlist *np;
      43             :     Source *s;
      44             :     Tokenrow *def, *args;
      45             :     static uchar location[(PATH_MAX + 8) * NINC], *cp;
      46             : 
      47        7446 :     tp = trp->tp + 1;
      48        7446 :     if (tp >= trp->lp || tp->type != NAME)
      49             :     {
      50           0 :         error(ERROR, "#defined token is not a name");
      51           0 :         return;
      52             :     }
      53        7446 :     np = lookup(tp, 1);
      54        7446 :     if (np->flag & ISUNCHANGE)
      55             :     {
      56           0 :         error(ERROR, "#defined token %t can't be redefined", tp);
      57           0 :         return;
      58             :     }
      59             :     /* collect arguments */
      60        7446 :     tp += 1;
      61        7446 :     args = NULL;
      62        7446 :     if (tp < trp->lp && tp->type == LP && tp->wslen == 0)
      63             :     {
      64        5913 :         tp += 1;
      65        5913 :         args = new(Tokenrow);
      66        5913 :         maketokenrow(2, args);
      67        5913 :         if (tp->type != RP)
      68             :         {
      69             :             /* macro with args */
      70        5913 :             size_t narg = 0;
      71        5913 :             int err = 0;
      72             : 
      73             :             for (;;)
      74             :             {
      75             :                 Token *atp;
      76             : 
      77       17155 :                 if (tp->type != NAME)
      78             :                 {
      79           0 :                     err++;
      80           0 :                     break;
      81             :                 }
      82       17155 :                 if (narg >= args->max)
      83        4015 :                     growtokenrow(args);
      84       47304 :                 for (atp = args->bp; atp < args->lp; atp++)
      85       30149 :                     if (atp->len == tp->len
      86       19053 :                         && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0)
      87           0 :                         error(ERROR, "Duplicate macro argument");
      88       17155 :                 *args->lp++ = *tp;
      89       17155 :                 narg++;
      90       17155 :                 tp += 1;
      91       17155 :                 if (tp->type == RP)
      92        5913 :                     break;
      93       11242 :                 if (tp->type != COMMA)
      94             :                 {
      95           0 :                     err++;
      96           0 :                     break;
      97             :                 }
      98       11242 :                 tp += 1;
      99       11242 :             }
     100        5913 :             if (err)
     101             :             {
     102           0 :                 error(ERROR, "Syntax error in macro parameters");
     103           0 :                 return;
     104             :             }
     105             :         }
     106        5913 :         tp += 1;
     107             :     }
     108        7446 :     trp->tp = tp;
     109        7446 :     if (((trp->lp) - 1)->type == NL)
     110        7446 :         trp->lp -= 1;
     111        7446 :     def = normtokenrow(trp);
     112        7446 :     if (np->flag & ISDEFINED)
     113             :     {
     114           0 :         if (comparetokens(def, np->vp)
     115           0 :             || (np->ap == NULL) != (args == NULL)
     116           0 :             || (np->ap && comparetokens(args, np->ap)))
     117             :         {
     118           0 :             if ( np->loc )
     119           0 :                 error(ERROR,
     120             :                     "Macro redefinition of %t (already defined at %s)",
     121           0 :                     trp->bp + 2, np->loc);
     122             :             else
     123           0 :                 error(ERROR,
     124             :                     "Macro redefinition of %t (already defined at %s)",
     125           0 :                     trp->bp + 2, "commandline" );
     126             :         }
     127             :     }
     128        7446 :     if (args)
     129             :     {
     130             :         Tokenrow *tap;
     131             : 
     132        5913 :         tap = normtokenrow(args);
     133        5913 :         dofree(args->bp);
     134        5913 :         args = tap;
     135             :     }
     136        7446 :     np->ap = args;
     137        7446 :     np->vp = def;
     138        7446 :     np->flag |= ISDEFINED;
     139             : 
     140             :     /* build location string of macro definition */
     141       23506 :     for (cp = location, s = cursource; s; s = s->next)
     142       16060 :         if (*s->filename)
     143             :         {
     144       16060 :             if (cp != location)
     145        8614 :                 *cp++ = ' ';
     146       16060 :             sprintf((char *)cp, "%s:%d", s->filename, s->line);
     147       16060 :             cp += strlen((char *)cp);
     148             :         }
     149             : 
     150        7446 :     np->loc = newstring(location, strlen((char *)location), 0);
     151             : 
     152        7446 :     if (Mflag)
     153             :     {
     154           0 :         if (np->ap)
     155           0 :             error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp);
     156             :         else
     157           0 :             error(INFO, "Macro definition of %s [%r]", np->name, np->vp);
     158             :     }
     159             : }
     160             : 
     161             : /*
     162             :  * Definition received via -D or -U
     163             :  */
     164             : void
     165        2740 :     doadefine(Tokenrow * trp, int type)
     166             : {
     167             :     Nlist *np;
     168             :     static uchar onestr[2] = "1";
     169             :     static Token onetoken[1] = {{NUMBER, 0, 0, 1, onestr, 0}};
     170             :     static Tokenrow onetr = {onetoken, onetoken, onetoken + 1, 1};
     171             : 
     172        2740 :     trp->tp = trp->bp;
     173        2740 :     if (type == 'U')
     174             :     {
     175           0 :         if (trp->lp - trp->tp != 2 || trp->tp->type != NAME)
     176             :             goto syntax;
     177           0 :         if ((np = lookup(trp->tp, 0)) == NULL)
     178           0 :             return;
     179           0 :         np->flag &= ~ISDEFINED;
     180           0 :         return;
     181             :     }
     182             : 
     183        2740 :     if (type == 'A')
     184             :     {
     185           0 :         if (trp->tp >= trp->lp || trp->tp->type != NAME)
     186             :             goto syntax;
     187           0 :         trp->tp->type = ARCHITECTURE;
     188           0 :         np = lookup(trp->tp, 1);
     189           0 :         np->flag |= ISARCHITECTURE;
     190           0 :         trp->tp += 1;
     191           0 :         if (trp->tp >= trp->lp || trp->tp->type == END)
     192             :         {
     193           0 :             np->vp = &onetr;
     194           0 :             return;
     195             :         }
     196             :         else
     197           0 :             error(FATAL, "Illegal -A argument %r", trp);
     198             :     }
     199             : 
     200        2740 :     if (trp->tp >= trp->lp || trp->tp->type != NAME)
     201             :         goto syntax;
     202        2740 :     np = lookup(trp->tp, 1);
     203        2740 :     np->flag |= ISDEFINED;
     204        2740 :     trp->tp += 1;
     205        2740 :     if (trp->tp >= trp->lp || trp->tp->type == END)
     206             :     {
     207        2265 :         np->vp = &onetr;
     208        2265 :         return;
     209             :     }
     210         475 :     if (trp->tp->type != ASGN)
     211           0 :         goto syntax;
     212         475 :     trp->tp += 1;
     213         475 :     if ((trp->lp - 1)->type == END)
     214         475 :         trp->lp -= 1;
     215         475 :     np->vp = normtokenrow(trp);
     216         475 :     return;
     217             : syntax:
     218           0 :     error(FATAL, "Illegal -D or -U argument %r", trp);
     219             : }
     220             : 
     221             : 
     222             : 
     223             : /*
     224             :  * Do macro expansion in a row of tokens.
     225             :  * Flag is NULL if more input can be gathered.
     226             :  */
     227             : void
     228      214184 :     expandrow(Tokenrow * trp, char *flag)
     229             : {
     230             :     Token * tp;
     231             :     Nlist * np;
     232             : 
     233             :     MacroValidatorList  validators;
     234      214184 :     mvl_init(&validators);
     235             :     /* Sets all token-identifiers to 0 because tokens may not be initialised (never use C!) */
     236      214184 :     tokenrow_zeroTokenIdentifiers(trp);
     237             : 
     238      214184 :     if (flag)
     239      202773 :         setsource(flag, -1, -1, "", 0);
     240     1336959 :     for (tp = trp->tp; tp < trp->lp;)
     241             :     {
     242      908591 :         mvl_check(&validators, tp);
     243             : 
     244      908591 :         if (tp->type != NAME
     245      516885 :             || quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0) == 0
     246      216007 :             || (np = lookup(tp, 0)) == NULL
     247       49630 :             || (np->flag & (ISDEFINED | ISMAC)) == 0
     248       49630 :             || (np->flag & ISACTIVE) != 0)
     249             :         {
     250      858961 :             tp++;
     251      858961 :             continue;
     252             :         }
     253       49630 :         trp->tp = tp;
     254       49630 :         if (np->val == KDEFINED)
     255             :         {
     256         429 :             tp->type = DEFINED;
     257         429 :             if ((tp + 1) < trp->lp && (tp + 1)->type == NAME)
     258         366 :                 (tp + 1)->type = NAME1;
     259             :             else
     260          63 :                 if ((tp + 3) < trp->lp && (tp + 1)->type == LP
     261          63 :                     && (tp + 2)->type == NAME && (tp + 3)->type == RP)
     262          63 :                     (tp + 2)->type = NAME1;
     263             :                 else
     264           0 :                     error(ERROR, "Incorrect syntax for `defined'");
     265         429 :             tp++;
     266         429 :             continue;
     267             :         }
     268             :         else
     269       49201 :             if (np->val == KMACHINE)
     270             :             {
     271           0 :                 if (((tp - 1) >= trp->bp) && ((tp - 1)->type == SHARP))
     272             :                 {
     273           0 :                     tp->type = ARCHITECTURE;
     274           0 :                     if ((tp + 1) < trp->lp && (tp + 1)->type == NAME)
     275           0 :                         (tp + 1)->type = NAME2;
     276             :                     else
     277           0 :                         if ((tp + 3) < trp->lp && (tp + 1)->type == LP
     278           0 :                             && (tp + 2)->type == NAME && (tp + 3)->type == RP)
     279           0 :                             (tp + 2)->type = NAME2;
     280             :                         else
     281           0 :                             error(ERROR, "Incorrect syntax for `#machine'");
     282             :                 }
     283           0 :                 tp++;
     284           0 :                 continue;
     285             :             }
     286             : 
     287       49201 :         if (np->flag & ISMAC)
     288           0 :             builtin(trp, np->val);
     289             :         else
     290       49201 :             expand(trp, np, &validators);
     291       49201 :         tp = trp->tp;
     292             :     }   // end for
     293      214184 :     if (flag)
     294      202773 :         unsetsource();
     295             : 
     296      214184 :     mvl_destruct(&validators);
     297      214184 : }
     298             : 
     299             : /*
     300             :  * Expand the macro whose name is np, at token trp->tp, in the tokenrow.
     301             :  * Return trp->tp at the first token next to be expanded
     302             :  * (ordinarily the beginning of the expansion)
     303             :  * I.e.: the same position as before!
     304             :  * Only one expansion is performed, then we return to the expandrow()
     305             :  * loop and start at same position.
     306             :  */
     307             : void
     308       49201 :     expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators)
     309             : {
     310             :     Tokenrow ntr;
     311             :     int ntokc, narg;
     312             :     Tokenrow *atr[NARG + 1];
     313             : 
     314       49201 :     if (Mflag == 2)
     315             :     {
     316           0 :         if (np->ap)
     317           0 :             error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap);
     318             :         else
     319           0 :             error(INFO, "Macro expansion of %t with %s", trp->tp, np->name);
     320             :     }
     321             : 
     322       49201 :     copytokenrow(&ntr, np->vp);         /* copy macro value */
     323       49201 :     if (np->ap == NULL)                 /* parameterless */
     324        1711 :         ntokc = 1;
     325             :     else
     326             :     {
     327             :         int i;
     328             : 
     329       47490 :         ntokc = gatherargs(trp, atr, &narg);
     330       47490 :         if (narg < 0)
     331             :         {                               /* not actually a call (no '(') */
     332           0 :             trp->tp++;
     333             :             return;
     334             :         }
     335       47490 :         if (narg != rowlen(np->ap))
     336             :         {
     337           0 :             error(ERROR, "Disagreement in number of macro arguments");
     338           0 :             trp->tp += ntokc;
     339             :             return;
     340             :         }
     341             : 
     342             :         /** If gatherargs passed a macro validating token, this token
     343             :             must become valid here.
     344             :             trp->tp+0 was checked in expandrow(), so we dont need to do it
     345             :             again here:
     346             :         */
     347      392638 :         for (i = 1; i < ntokc; i++)
     348             :         {
     349      345148 :             mvl_check(pValidators,trp->tp+i);
     350             :         }
     351             : 
     352       47490 :         substargs(np, &ntr, atr);       /* put args into replacement */
     353      140414 :         for (i = 0; i < narg; i++)
     354             :         {
     355       92924 :             dofree(atr[i]->bp);
     356       92924 :             dofree(atr[i]);
     357             :         }
     358             :     }
     359             : 
     360       49201 :     doconcat(&ntr);                     /* execute ## operators */
     361       49201 :     ntr.tp = ntr.bp;
     362       49201 :     makespace(&ntr, trp->tp);
     363             : 
     364       49201 :     tokenrow_zeroTokenIdentifiers(&ntr);
     365       49201 :     insertrow(trp, ntokc, &ntr);
     366             : 
     367             :         /* add validator for just invalidated macro:
     368             :         */
     369       49201 :     np->flag |= ISACTIVE;
     370       49201 :     if (trp->tp != trp->lp)
     371             :     {   /* tp is a valid pointer: */
     372       31286 :         mvl_add(pValidators,np,trp->tp);
     373             :     }
     374             :     else
     375             :     {   /* tp is == lp, therefore does not point to valid memory: */
     376       17915 :         mvl_add(pValidators,np,0);
     377             :     }
     378             :         /* reset trp->tp to original position:
     379             :         */
     380       49201 :     trp->tp -= ntr.lp - ntr.bp;         /* so the result will be tested for macros from the same position again */
     381             : 
     382       49201 :     dofree(ntr.bp);
     383             : 
     384             :     return;
     385             : }
     386             : 
     387             : /*
     388             :  * Gather an arglist, starting in trp with tp pointing at the macro name.
     389             :  * Return total number of tokens passed, stash number of args found.
     390             :  * trp->tp is not changed relative to the tokenrow.
     391             :  */
     392             : int
     393       47490 :     gatherargs(Tokenrow * trp, Tokenrow ** atr, int *narg)
     394             : {
     395       47490 :     int parens = 1;
     396       47490 :     int ntok = 0;
     397             :     Token *bp, *lp;
     398             :     Tokenrow ttr;
     399             :     int ntokp;
     400             :     int needspace;
     401             : 
     402       47490 :     *narg = -1;                         /* means that there is no macro
     403             :                                          * call */
     404             :     /* look for the ( */
     405             :     for (;;)
     406             :     {
     407       47490 :         trp->tp++;
     408       47490 :         ntok++;
     409       47490 :         if (trp->tp >= trp->lp)
     410             :         {
     411           0 :             gettokens(trp, 0);
     412           0 :             if ((trp->lp - 1)->type == END)
     413             :             {
     414           0 :                 trp->lp -= 1;
     415           0 :                 trp->tp -= ntok;
     416           0 :                 return ntok;
     417             :             }
     418             :         }
     419       47490 :         if (trp->tp->type == LP)
     420       47490 :             break;
     421           0 :         if (trp->tp->type != NL)
     422           0 :             return ntok;
     423           0 :     }
     424       47490 :     *narg = 0;
     425       47490 :     ntok++;
     426       47490 :     ntokp = ntok;
     427       47490 :     trp->tp++;
     428             :     /* search for the terminating ), possibly extending the row */
     429       47490 :     needspace = 0;
     430      392642 :     while (parens > 0)
     431             :     {
     432      297662 :         if (trp->tp >= trp->lp)
     433           4 :             gettokens(trp, 0);
     434      297662 :         if (needspace)
     435             :         {
     436           4 :             needspace = 0;
     437             :             /* makespace(trp); [rh] */
     438             :         }
     439      297662 :         if (trp->tp->type == END)
     440             :         {
     441           0 :             trp->lp -= 1;
     442           0 :             trp->tp -= ntok;
     443           0 :             error(ERROR, "EOF in macro arglist");
     444           0 :             return ntok;
     445             :         }
     446      297662 :         if (trp->tp->type == NL)
     447             :         {
     448           4 :             trp->tp += 1;
     449           4 :             adjustrow(trp, -1);
     450           4 :             trp->tp -= 1;
     451             :             /* makespace(trp); [rh] */
     452           4 :             needspace = 1;
     453           4 :             continue;
     454             :         }
     455      297658 :         if (trp->tp->type == LP)
     456        8729 :             parens++;
     457             :         else
     458      288929 :             if (trp->tp->type == RP)
     459       56219 :                 parens--;
     460      297658 :         trp->tp++;
     461      297658 :         ntok++;
     462             :     }
     463       47490 :     trp->tp -= ntok;
     464             :     /* Now trp->tp won't move underneath us */
     465       47490 :     lp = bp = trp->tp + ntokp;
     466      345148 :     for (; parens >= 0; lp++)
     467             :     {
     468      297658 :         if (lp->type == LP)
     469             :         {
     470        8729 :             parens++;
     471        8729 :             continue;
     472             :         }
     473      288929 :         if (lp->type == RP)
     474       56219 :             parens--;
     475      288929 :         if (lp->type == DSHARP)
     476           0 :             lp->type = DSHARP1;         /* ## not special in arg */
     477      288929 :         if ((lp->type == COMMA && parens == 0) ||
     478       47490 :                 ( parens < 0 && ((lp - 1)->type != LP)))
     479             :         {
     480       92924 :             if (*narg >= NARG - 1)
     481           0 :                 error(FATAL, "Sorry, too many macro arguments");
     482       92924 :             ttr.bp = ttr.tp = bp;
     483       92924 :             ttr.lp = lp;
     484       92924 :             atr[(*narg)++] = normtokenrow(&ttr);
     485       92924 :             bp = lp + 1;
     486             :         }
     487             :     }
     488       47490 :     return ntok;
     489             : }
     490             : 
     491             : /*
     492             :  * substitute the argument list into the replacement string
     493             :  *  This would be simple except for ## and #
     494             :  */
     495             : void
     496       47490 :     substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr)
     497             : {
     498             :     Tokenrow tatr;
     499             :     Token *tp;
     500             :     int ntok, argno;
     501             : 
     502      983876 :     for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;)
     503             :     {
     504      888896 :         if (rtr->tp->type == SHARP)
     505             :         {                               /* string operator */
     506        9983 :             tp = rtr->tp;
     507        9983 :             rtr->tp += 1;
     508        9983 :             if ((argno = lookuparg(np, rtr->tp)) < 0)
     509             :             {
     510           0 :                 error(ERROR, "# not followed by macro parameter");
     511           0 :                 continue;
     512             :             }
     513        9983 :             ntok = 1 + (int)(rtr->tp - tp);
     514        9983 :             rtr->tp = tp;
     515        9983 :             insertrow(rtr, ntok, stringify(atr[argno]));
     516        9983 :             continue;
     517             :         }
     518      878913 :         if (rtr->tp->type == NAME
     519      391678 :             && (argno = lookuparg(np, rtr->tp)) >= 0)
     520             :         {
     521      229476 :             if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP)
     522      211762 :                 || (rtr->tp != rtr->bp  && (rtr->tp - 1)->type == DSHARP))
     523             :             {
     524       27060 :                 copytokenrow(&tatr, atr[argno]);
     525       27060 :                 makespace(&tatr, rtr->tp);
     526       27060 :                 insertrow(rtr, 1, &tatr);
     527       27060 :                 dofree(tatr.bp);
     528             :             }
     529             :             else
     530             :             {
     531      202416 :                 copytokenrow(&tatr, atr[argno]);
     532      202416 :                 makespace(&tatr, rtr->tp);
     533      202416 :                 expandrow(&tatr, "<macro>");
     534      202416 :                 insertrow(rtr, 1, &tatr);
     535      202416 :                 dofree(tatr.bp);
     536             :             }
     537      229476 :             continue;
     538             :         }
     539      649437 :         rtr->tp++;
     540             :     }
     541       47490 : }
     542             : 
     543             : /*
     544             :  * Evaluate the ## operators in a tokenrow
     545             :  */
     546             : void
     547       67531 :     doconcat(Tokenrow * trp)
     548             : {
     549             :     Token *ltp, *ntp;
     550             :     Tokenrow ntr;
     551             :     size_t len;
     552             : 
     553     1014885 :     for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++)
     554             :     {
     555      947354 :         if (trp->tp->type == DSHARP1)
     556           0 :             trp->tp->type = DSHARP;
     557             :         else
     558      947354 :             if (trp->tp->type == DSHARP)
     559             :             {
     560             :                 int  i;
     561             :                 char tt[NCONCAT];
     562             : 
     563       18330 :                 ltp = trp->tp - 1;
     564       18330 :                 ntp = trp->tp + 1;
     565             : 
     566       18330 :                 if (ltp < trp->bp || ntp >= trp->lp)
     567             :                 {
     568           0 :                     error(ERROR, "## occurs at border of replacement");
     569           0 :                     continue;
     570             :                 }
     571             : 
     572       18330 :                 ntp = ltp;
     573       18330 :                 i   = 1;
     574       18330 :                 len = 0;
     575             : 
     576             :                 do
     577             :                 {
     578       77000 :                     if (len + ntp->len + ntp->wslen > sizeof(tt))
     579             :                     {
     580           0 :                         error(ERROR, "## string concatination buffer overrun");
     581           0 :                         break;
     582             :                     }
     583             : 
     584       77000 :                     if (ntp != trp->tp + 1)
     585             :                     {
     586       58670 :                         strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen,
     587       58670 :                                 ntp->len + ntp->wslen);
     588       58670 :                         len += ntp->len + ntp->wslen;
     589             :                     }
     590             :                     else    // Leerzeichen um ## herum entfernen:
     591             :                     {
     592       18330 :                         strncpy((char *) tt + len, (char *) ntp->t, ntp->len);
     593       18330 :                         len += ntp->len;
     594             :                     }
     595             : 
     596       77000 :                     ntp = trp->tp + i;
     597       77000 :                     i++;
     598             :                 }
     599       77000 :                 while (ntp < trp->lp);
     600             : 
     601       18330 :                 tt[len] = '\0';
     602       18330 :                 setsource("<##>", -1, -1, tt, 0);
     603       18330 :                 maketokenrow(3, &ntr);
     604       18330 :                 gettokens(&ntr, 1);
     605       18330 :                 unsetsource();
     606       18330 :                 if (ntr.bp->type == UNCLASS)
     607           0 :                     error(WARNING, "Bad token %r produced by ##", &ntr);
     608       54990 :                 while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp)
     609       18330 :                     ntr.lp--;
     610             : 
     611       18330 :                 doconcat(&ntr);
     612       18330 :                 trp->tp = ltp;
     613       18330 :                 makespace(&ntr, ltp);
     614       18330 :                 insertrow(trp, (int)(ntp - ltp), &ntr);
     615       18330 :                 dofree(ntr.bp);
     616       18330 :                 trp->tp--;
     617             :             }
     618             :     }
     619       67531 : }
     620             : 
     621             : /*
     622             :  * tp is a potential parameter name of macro mac;
     623             :  * look it up in mac's arglist, and if found, return the
     624             :  * corresponding index in the argname array.  Return -1 if not found.
     625             :  */
     626             : int
     627      401661 :     lookuparg(Nlist * mac, Token * tp)
     628             : {
     629             :     Token *ap;
     630             : 
     631      401661 :     if (tp->type != NAME || mac->ap == NULL)
     632           0 :         return -1;
     633      822992 :     for (ap = mac->ap->bp; ap < mac->ap->lp; ap++)
     634             :     {
     635      660790 :         if (ap->len == tp->len && strncmp((char *) ap->t, (char *) tp->t, ap->len) == 0)
     636      239459 :             return (int)(ap - mac->ap->bp);
     637             :     }
     638      162202 :     return -1;
     639             : }
     640             : 
     641             : /*
     642             :  * Return a quoted version of the tokenrow (from # arg)
     643             :  */
     644             : #define STRLEN  512
     645             : Tokenrow *
     646        9983 :     stringify(Tokenrow * vp)
     647             : {
     648             :     static Token t = {STRING, 0, 0, 0, NULL, 0};
     649             :     static Tokenrow tr = {&t, &t, &t + 1, 1};
     650             :     Token *tp;
     651             :     uchar s[STRLEN];
     652        9983 :     uchar *sp = s, *cp;
     653             :     int i, instring;
     654             : 
     655        9983 :     *sp++ = '"';
     656       38969 :     for (tp = vp->bp; tp < vp->lp; tp++)
     657             :     {
     658       28986 :         instring = tp->type == STRING || tp->type == CCON;
     659       28986 :         if (sp + 2 * tp->len + tp->wslen  >= &s[STRLEN - 10])
     660             :         {
     661           0 :             error(ERROR, "Stringified macro arg is too long");
     662           0 :             break;
     663             :         }
     664             : 
     665             :         // Change by np 31.10.2001, #93725 - begin
     666       28986 :         if ( tp->wslen > 0 )
     667           0 :             *sp++ = ' ';
     668             :         // change end.
     669             : 
     670      141125 :         for (i = 0, cp = tp->t; (unsigned int)i < tp->len; i++)
     671             :         {
     672      112139 :             if (instring && (*cp == '"' || *cp == '\\'))
     673           0 :                 *sp++ = '\\';
     674      112139 :             *sp++ = *cp++;
     675             :         }
     676             :     }
     677        9983 :     *sp++ = '"';
     678        9983 :     *sp = '\0';
     679        9983 :     sp = s;
     680        9983 :     t.len = strlen((char *) sp);
     681        9983 :     t.t = newstring(sp, t.len, 0);
     682        9983 :     return &tr;
     683             : }
     684             : 
     685             : /*
     686             :  * expand a builtin name
     687             :  */
     688             : void
     689           0 :     builtin(Tokenrow * trp, int biname)
     690             : {
     691             :     char *op;
     692             :     Token *tp;
     693             :     Source *s;
     694             : 
     695           0 :     tp = trp->tp;
     696           0 :     trp->tp++;
     697             :     /* need to find the real source */
     698           0 :     s = cursource;
     699           0 :     while (s && s->fd == -1)
     700           0 :         s = s->next;
     701           0 :     if (s == NULL)
     702           0 :         s = cursource;
     703             :     /* most are strings */
     704           0 :     tp->type = STRING;
     705           0 :     if (tp->wslen)
     706             :     {
     707           0 :         *outptr++ = ' ';
     708           0 :         tp->wslen = 1;
     709             :     }
     710           0 :     op = outptr;
     711           0 :     *op++ = '"';
     712           0 :     switch (biname)
     713             :     {
     714             : 
     715             :         case KLINENO:
     716           0 :             tp->type = NUMBER;
     717           0 :             op = outnum(op - 1, s->line);
     718           0 :             break;
     719             : 
     720             :         case KFILE:
     721             :             {
     722           0 :                 char *src = s->filename;
     723             : 
     724           0 :                 while ((*op++ = *src++) != 0)
     725           0 :                     if (src[-1] == '\\')
     726           0 :                         *op++ = '\\';
     727           0 :                 op--;
     728           0 :                 break;
     729             :             }
     730             : 
     731             :         case KDATE:
     732           0 :             strncpy(op, curtime + 4, 7);
     733           0 :             strncpy(op + 7, curtime + 20, 4);
     734           0 :             op += 11;
     735           0 :             break;
     736             : 
     737             :         case KTIME:
     738           0 :             strncpy(op, curtime + 11, 8);
     739           0 :             op += 8;
     740           0 :             break;
     741             : 
     742             :         default:
     743           0 :             error(ERROR, "cpp botch: unknown internal macro");
     744           0 :             return;
     745             :     }
     746           0 :     if (tp->type == STRING)
     747           0 :         *op++ = '"';
     748           0 :     tp->t = (uchar *) outptr;
     749           0 :     tp->len = op - outptr;
     750           0 :     outptr = op;
     751             : }
     752             : 
     753             : /* vim:set shiftwidth=4 softtabstop=4 expandtab: */

Generated by: LCOV version 1.10