LCOV - code coverage report
Current view: top level - soltools/cpp - _macro.c (source / functions) Hit Total Coverage
Test: commit c8344322a7af75b84dd3ca8f78b05543a976dfd5 Lines: 251 381 65.9 %
Date: 2015-06-13 12:38:46 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        5617 :     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        5617 :     tp = trp->tp + 1;
      50        5617 :     if (tp >= trp->lp || tp->type != NAME)
      51             :     {
      52           0 :         error(ERROR, "#defined token is not a name");
      53           0 :         return;
      54             :     }
      55        5617 :     np = lookup(tp, 1);
      56        5617 :     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        5617 :     tp += 1;
      63        5617 :     args = NULL;
      64        5617 :     if (tp < trp->lp && tp->type == LP && tp->wslen == 0)
      65             :     {
      66        4437 :         tp += 1;
      67        4437 :         args = new(Tokenrow);
      68        4437 :         maketokenrow(2, args);
      69        4437 :         if (tp->type != RP)
      70             :         {
      71             :             /* macro with args */
      72        4437 :             size_t narg = 0;
      73        4437 :             int err = 0;
      74             : 
      75             :             for (;;)
      76             :             {
      77             :                 Token *atp;
      78             : 
      79       13158 :                 if (tp->type != NAME)
      80             :                 {
      81           0 :                     err++;
      82           0 :                     break;
      83             :                 }
      84       13158 :                 if (narg >= args->max)
      85        3060 :                     growtokenrow(args);
      86       35445 :                 for (atp = args->bp; atp < args->lp; atp++)
      87       22287 :                     if (atp->len == tp->len
      88       13668 :                         && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0)
      89           0 :                         error(ERROR, "Duplicate macro argument");
      90       13158 :                 *args->lp++ = *tp;
      91       13158 :                 narg++;
      92       13158 :                 tp += 1;
      93       13158 :                 if (tp->type == RP)
      94        4437 :                     break;
      95        8721 :                 if (tp->type != COMMA)
      96             :                 {
      97           0 :                     err++;
      98           0 :                     break;
      99             :                 }
     100        8721 :                 tp += 1;
     101        8721 :             }
     102        4437 :             if (err)
     103             :             {
     104           0 :                 error(ERROR, "Syntax error in macro parameters");
     105           0 :                 return;
     106             :             }
     107             :         }
     108        4437 :         tp += 1;
     109             :     }
     110        5617 :     trp->tp = tp;
     111        5617 :     if (((trp->lp) - 1)->type == NL)
     112        5617 :         trp->lp -= 1;
     113        5617 :     def = normtokenrow(trp);
     114        5617 :     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        5617 :     if (args)
     131             :     {
     132             :         Tokenrow *tap;
     133             : 
     134        4437 :         tap = normtokenrow(args);
     135        4437 :         dofree(args->bp);
     136        4437 :         dofree(args);
     137        4437 :         args = tap;
     138             :     }
     139        5617 :     np->ap = args;
     140        5617 :     np->vp = def;
     141        5617 :     np->flag |= ISDEFINED;
     142             : 
     143             :     /* build location string of macro definition */
     144       17616 :     for (cp = location, s = cursource; s; s = s->next)
     145       11999 :         if (*s->filename)
     146             :         {
     147       11999 :             if (cp != location)
     148        6382 :                 *cp++ = ' ';
     149       11999 :             sprintf((char *)cp, "%s:%d", s->filename, s->line);
     150       11999 :             cp += strlen((char *)cp);
     151             :         }
     152             : 
     153        5617 :     np->loc = newstring(location, strlen((char *)location), 0);
     154             : 
     155        5617 :     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        1100 :     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        1100 :     trp->tp = trp->bp;
     176        1100 :     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        1100 :     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        1100 :     if (trp->tp >= trp->lp || trp->tp->type != NAME)
     204             :         goto syntax;
     205        1100 :     np = lookup(trp->tp, 1);
     206        1100 :     np->flag |= ISDEFINED;
     207        1100 :     trp->tp += 1;
     208        1100 :     if (trp->tp >= trp->lp || trp->tp->type == END)
     209             :     {
     210         867 :         np->vp = &onetr;
     211         867 :         return;
     212             :     }
     213         233 :     if (trp->tp->type != ASGN)
     214           0 :         goto syntax;
     215         233 :     trp->tp += 1;
     216         233 :     if ((trp->lp - 1)->type == END)
     217         233 :         trp->lp -= 1;
     218         233 :     np->vp = normtokenrow(trp);
     219         233 :     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      205717 :     expandrow(Tokenrow * trp, char *flag)
     232             : {
     233             :     Token * tp;
     234             :     Nlist * np;
     235             : 
     236             :     MacroValidatorList  validators;
     237      205717 :     mvl_init(&validators);
     238             :     /* Sets all token-identifiers to 0 because tokens may not be initialised (never use C!) */
     239      205717 :     tokenrow_zeroTokenIdentifiers(trp);
     240             : 
     241      205717 :     if (flag)
     242      197988 :         setsource(flag, -1, -1, "", 0);
     243     1339648 :     for (tp = trp->tp; tp < trp->lp;)
     244             :     {
     245      928214 :         mvl_check(&validators, tp);
     246             : 
     247      928214 :         if (tp->type != NAME
     248      529006 :             || quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0) == 0
     249      207794 :             || (np = lookup(tp, 0)) == NULL
     250       49796 :             || (np->flag & (ISDEFINED | ISMAC)) == 0
     251       49796 :             || (np->flag & ISACTIVE) != 0)
     252             :         {
     253      878418 :             tp++;
     254      878418 :             continue;
     255             :         }
     256       49796 :         trp->tp = tp;
     257       49796 :         if (np->val == KDEFINED)
     258             :         {
     259         415 :             tp->type = DEFINED;
     260         415 :             if ((tp + 1) < trp->lp && (tp + 1)->type == NAME)
     261         345 :                 (tp + 1)->type = NAME1;
     262             :             else
     263          70 :                 if ((tp + 3) < trp->lp && (tp + 1)->type == LP
     264          70 :                     && (tp + 2)->type == NAME && (tp + 3)->type == RP)
     265          70 :                     (tp + 2)->type = NAME1;
     266             :                 else
     267           0 :                     error(ERROR, "Incorrect syntax for `defined'");
     268         415 :             tp++;
     269         415 :             continue;
     270             :         }
     271             :         else
     272       49381 :             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       49381 :         if (np->flag & ISMAC)
     291           0 :             builtin(trp, np->val);
     292             :         else
     293       49381 :             expand(trp, np, &validators);
     294       49381 :         tp = trp->tp;
     295             :     }   // end for
     296      205717 :     if (flag)
     297      197988 :         unsetsource();
     298             : 
     299      205717 :     mvl_destruct(&validators);
     300      205717 : }
     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       49381 :     expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators)
     312             : {
     313             :     Tokenrow ntr;
     314             :     int ntokc, narg;
     315             :     Tokenrow *atr[NARG + 1];
     316             : 
     317       49381 :     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       49381 :     copytokenrow(&ntr, np->vp);         /* copy macro value */
     326       49381 :     if (np->ap == NULL)                 /* parameterless */
     327        1573 :         ntokc = 1;
     328             :     else
     329             :     {
     330             :         int i;
     331             : 
     332       47808 :         ntokc = gatherargs(trp, atr, &narg);
     333       47808 :         if (narg < 0)
     334             :         {                               /* not actually a call (no '(') */
     335           0 :             trp->tp++;
     336           0 :             return;
     337             :         }
     338       47808 :         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      472292 :         for (i = 1; i < ntokc; i++)
     351             :         {
     352      424484 :             mvl_check(pValidators,trp->tp+i);
     353             :         }
     354             : 
     355       47808 :         substargs(np, &ntr, atr);       /* put args into replacement */
     356      138316 :         for (i = 0; i < narg; i++)
     357             :         {
     358       90508 :             dofree(atr[i]->bp);
     359       90508 :             dofree(atr[i]);
     360             :         }
     361             :     }
     362             : 
     363       49381 :     doconcat(&ntr);                     /* execute ## operators */
     364       49381 :     ntr.tp = ntr.bp;
     365       49381 :     makespace(&ntr, trp->tp);
     366             : 
     367       49381 :     tokenrow_zeroTokenIdentifiers(&ntr);
     368       49381 :     insertrow(trp, ntokc, &ntr);
     369             : 
     370             :         /* add validator for just invalidated macro:
     371             :         */
     372       49381 :     np->flag |= ISACTIVE;
     373       49381 :     if (trp->tp != trp->lp)
     374             :     {   /* tp is a valid pointer: */
     375       29829 :         mvl_add(pValidators,np,trp->tp);
     376             :     }
     377             :     else
     378             :     {   /* tp is == lp, therefore does not point to valid memory: */
     379       19552 :         mvl_add(pValidators,np,0);
     380             :     }
     381             :         /* reset trp->tp to original position:
     382             :         */
     383       49381 :     trp->tp -= ntr.lp - ntr.bp;         /* so the result will be tested for macros from the same position again */
     384             : 
     385       49381 :     dofree(ntr.bp);
     386             : 
     387       49381 :     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       47808 :     gatherargs(Tokenrow * trp, Tokenrow ** atr, int *narg)
     397             : {
     398       47808 :     int parens = 1;
     399       47808 :     int ntok = 0;
     400             :     Token *bp, *lp;
     401             :     Tokenrow ttr;
     402             :     int ntokp;
     403             :     int needspace;
     404             : 
     405       47808 :     *narg = -1;                         /* means that there is no macro
     406             :                                          * call */
     407             :     /* look for the ( */
     408             :     for (;;)
     409             :     {
     410       47808 :         trp->tp++;
     411       47808 :         ntok++;
     412       47808 :         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       47808 :         if (trp->tp->type == LP)
     423       47808 :             break;
     424           0 :         if (trp->tp->type != NL)
     425           0 :             return ntok;
     426           0 :     }
     427       47808 :     *narg = 0;
     428       47808 :     ntok++;
     429       47808 :     ntokp = ntok;
     430       47808 :     trp->tp++;
     431             :     /* search for the terminating ), possibly extending the row */
     432       47808 :     needspace = 0;
     433      472292 :     while (parens > 0)
     434             :     {
     435      376676 :         if (trp->tp >= trp->lp)
     436           0 :             gettokens(trp, 0);
     437      376676 :         if (needspace)
     438             :         {
     439           0 :             needspace = 0;
     440             :             /* makespace(trp); [rh] */
     441             :         }
     442      376676 :         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      376676 :         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      376676 :         if (trp->tp->type == LP)
     459        9776 :             parens++;
     460             :         else
     461      366900 :             if (trp->tp->type == RP)
     462       57584 :                 parens--;
     463      376676 :         trp->tp++;
     464      376676 :         ntok++;
     465             :     }
     466       47808 :     trp->tp -= ntok;
     467             :     /* Now trp->tp won't move underneath us */
     468       47808 :     lp = bp = trp->tp + ntokp;
     469      424484 :     for (; parens >= 0; lp++)
     470             :     {
     471      376676 :         if (lp->type == LP)
     472             :         {
     473        9776 :             parens++;
     474        9776 :             continue;
     475             :         }
     476      366900 :         if (lp->type == RP)
     477       57584 :             parens--;
     478      366900 :         if (lp->type == DSHARP)
     479           0 :             lp->type = DSHARP1;         /* ## not special in arg */
     480      366900 :         if ((lp->type == COMMA && parens == 0) ||
     481       47808 :                 ( parens < 0 && ((lp - 1)->type != LP)))
     482             :         {
     483       90508 :             if (*narg >= NARG - 1)
     484           0 :                 error(FATAL, "Sorry, too many macro arguments");
     485       90508 :             ttr.bp = ttr.tp = bp;
     486       90508 :             ttr.lp = lp;
     487       90508 :             atr[(*narg)++] = normtokenrow(&ttr);
     488       90508 :             bp = lp + 1;
     489             :         }
     490             :     }
     491       47808 :     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       47808 :     substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr)
     500             : {
     501             :     Tokenrow tatr;
     502             :     Token *tp;
     503             :     int ntok, argno;
     504             : 
     505      995309 :     for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;)
     506             :     {
     507      899693 :         if (rtr->tp->type == SHARP)
     508             :         {                               /* string operator */
     509        9776 :             tp = rtr->tp;
     510        9776 :             rtr->tp += 1;
     511        9776 :             if ((argno = lookuparg(np, rtr->tp)) < 0)
     512             :             {
     513           0 :                 error(ERROR, "# not followed by macro parameter");
     514           0 :                 continue;
     515             :             }
     516        9776 :             ntok = 1 + (int)(rtr->tp - tp);
     517        9776 :             rtr->tp = tp;
     518        9776 :             insertrow(rtr, ntok, stringify(atr[argno]));
     519        9776 :             continue;
     520             :         }
     521      889917 :         if (rtr->tp->type == NAME
     522      397224 :             && (argno = lookuparg(np, rtr->tp)) >= 0)
     523             :         {
     524      225118 :             if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP)
     525      208069 :                 || (rtr->tp != rtr->bp  && (rtr->tp - 1)->type == DSHARP))
     526             :             {
     527       27510 :                 copytokenrow(&tatr, atr[argno]);
     528       27510 :                 makespace(&tatr, rtr->tp);
     529       27510 :                 insertrow(rtr, 1, &tatr);
     530       27510 :                 dofree(tatr.bp);
     531             :             }
     532             :             else
     533             :             {
     534      197608 :                 copytokenrow(&tatr, atr[argno]);
     535      197608 :                 makespace(&tatr, rtr->tp);
     536      197608 :                 expandrow(&tatr, "<macro>");
     537      197608 :                 insertrow(rtr, 1, &tatr);
     538      197608 :                 dofree(tatr.bp);
     539             :             }
     540      225118 :             continue;
     541             :         }
     542      664799 :         rtr->tp++;
     543             :     }
     544       47808 : }
     545             : 
     546             : /*
     547             :  * Evaluate the ## operators in a tokenrow
     548             :  */
     549             : void
     550       67054 :     doconcat(Tokenrow * trp)
     551             : {
     552             :     Token *ltp, *ntp;
     553             :     Tokenrow ntr;
     554             :     size_t len;
     555             : 
     556     1090380 :     for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++)
     557             :     {
     558     1023326 :         if (trp->tp->type == DSHARP1)
     559           0 :             trp->tp->type = DSHARP;
     560             :         else
     561     1023326 :             if (trp->tp->type == DSHARP)
     562             :             {
     563             :                 int  i;
     564             :                 char tt[NCONCAT];
     565             : 
     566       17673 :                 ltp = trp->tp - 1;
     567       17673 :                 ntp = trp->tp + 1;
     568             : 
     569       17673 :                 if (ltp < trp->bp || ntp >= trp->lp)
     570             :                 {
     571           0 :                     error(ERROR, "## occurs at border of replacement");
     572           0 :                     continue;
     573             :                 }
     574             : 
     575       17673 :                 ntp = ltp;
     576       17673 :                 i   = 1;
     577       17673 :                 len = 0;
     578             : 
     579             :                 do
     580             :                 {
     581       88534 :                     if (len + ntp->len + ntp->wslen > sizeof(tt))
     582             :                     {
     583           0 :                         error(ERROR, "## string concatination buffer overrun");
     584           0 :                         break;
     585             :                     }
     586             : 
     587       88534 :                     if (ntp != trp->tp + 1)
     588             :                     {
     589       70861 :                         strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen,
     590       70861 :                                 ntp->len + ntp->wslen);
     591       70861 :                         len += ntp->len + ntp->wslen;
     592             :                     }
     593             :                     else    // Leerzeichen um ## herum entfernen:
     594             :                     {
     595       17673 :                         strncpy((char *) tt + len, (char *) ntp->t, ntp->len);
     596       17673 :                         len += ntp->len;
     597             :                     }
     598             : 
     599       88534 :                     ntp = trp->tp + i;
     600       88534 :                     i++;
     601             :                 }
     602       88534 :                 while (ntp < trp->lp);
     603             : 
     604       17673 :                 tt[len] = '\0';
     605       17673 :                 setsource("<##>", -1, -1, tt, 0);
     606       17673 :                 maketokenrow(3, &ntr);
     607       17673 :                 gettokens(&ntr, 1);
     608       17673 :                 unsetsource();
     609       17673 :                 if (ntr.bp->type == UNCLASS)
     610           0 :                     error(WARNING, "Bad token %r produced by ##", &ntr);
     611       53019 :                 while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp)
     612       17673 :                     ntr.lp--;
     613             : 
     614       17673 :                 doconcat(&ntr);
     615       17673 :                 trp->tp = ltp;
     616       17673 :                 makespace(&ntr, ltp);
     617       17673 :                 insertrow(trp, (int)(ntp - ltp), &ntr);
     618       17673 :                 dofree(ntr.bp);
     619       17673 :                 trp->tp--;
     620             :             }
     621             :     }
     622       67054 : }
     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      407000 :     lookuparg(Nlist * mac, Token * tp)
     631             : {
     632             :     Token *ap;
     633             : 
     634      407000 :     if (tp->type != NAME || mac->ap == NULL)
     635           0 :         return -1;
     636      824943 :     for (ap = mac->ap->bp; ap < mac->ap->lp; ap++)
     637             :     {
     638      652837 :         if (ap->len == tp->len && strncmp((char *) ap->t, (char *) tp->t, ap->len) == 0)
     639      234894 :             return (int)(ap - mac->ap->bp);
     640             :     }
     641      172106 :     return -1;
     642             : }
     643             : 
     644             : /*
     645             :  * Return a quoted version of the tokenrow (from # arg)
     646             :  */
     647             : #define STRLEN  512
     648             : Tokenrow *
     649        9776 :     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        9776 :     uchar *sp = s, *cp;
     656             :     int i, instring;
     657             : 
     658        9776 :     *sp++ = '"';
     659       59512 :     for (tp = vp->bp; tp < vp->lp; tp++)
     660             :     {
     661       49736 :         instring = tp->type == STRING || tp->type == CCON;
     662       49736 :         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       49736 :         if ( tp->wslen > 0 )
     670           0 :             *sp++ = ' ';
     671             :         // change end.
     672             : 
     673      197430 :         for (i = 0, cp = tp->t; (unsigned int)i < tp->len; i++)
     674             :         {
     675      147694 :             if (instring && (*cp == '"' || *cp == '\\'))
     676           0 :                 *sp++ = '\\';
     677      147694 :             *sp++ = *cp++;
     678             :         }
     679             :     }
     680        9776 :     *sp++ = '"';
     681        9776 :     *sp = '\0';
     682        9776 :     sp = s;
     683        9776 :     t.len = strlen((char *) sp);
     684        9776 :     t.t = newstring(sp, t.len, 0);
     685        9776 :     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.11