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

Generated by: LCOV version 1.10