Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/LibreOffice/soltools/cpp/   (Office von Apache Version 25.8.3.2©)  Datei vom 5.10.2025 mit Größe 20 kB image not shown  

Quelle  _macro.c   Sprache: C

 
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
 * This file is part of the LibreOffice project.
 *
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 *
 * This file incorporates work covered by the following license notice:
 *
 *   Licensed to the Apache Software Foundation (ASF) under one or more
 *   contributor license agreements. See the NOTICE file distributed
 *   with this work for additional information regarding copyright
 *   ownership. The ASF licenses this file to you under the Apache
 *   License, Version 2.0 (the "License"); you may not use this file
 *   except in compliance with the License. You may obtain a copy of
 *   the License at http://www.apache.org/licenses/LICENSE-2.0 .
 */


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(__IBMC__) || defined(__EMX__) || defined(_MSC_VER)
#   ifndef PATH_MAX
#       define PATH_MAX _MAX_PATH
#   endif
#endif
#include <limits.h>

#include <sal/types.h>

#include "cpp.h"

#define NCONCAT 16384

/*
 * do a macro definition.  tp points to the name being defined in the line
 */

void
    dodefine(Tokenrow * trp)
{
    Token *tp;
    Nlist *np;
    Source *s;
    Tokenrow *def, *args;
    static uchar location[(PATH_MAX + 8) * NINC], *cp;

    tp = trp->tp + 1;
    if (tp >= trp->lp || tp->type != NAME)
    {
        error(ERROR, "#defined token is not a name");
        return;
    }
    np = lookup(tp, 1);
    if (np->flag & ISUNCHANGE)
    {
        error(ERROR, "#defined token %t can't be redefined", tp);
        return;
    }
    /* collect arguments */
    tp += 1;
    args = NULL;
    if (tp < trp->lp && tp->type == LP && tp->wslen == 0)
    {
        tp += 1;
        args = new(Tokenrow);
        maketokenrow(2, args);
        if (tp->type != RP)
        {
            /* macro with args */
            size_t narg = 0;
            int err = 0;

            for (;;)
            {
                Token *atp;

                if (tp->type != NAME)
                {
                    err++;
                    break;
                }
                if (narg >= args->max)
                    growtokenrow(args);
                for (atp = args->bp; atp < args->lp; atp++)
                    if (atp->len == tp->len
                        && strncmp((char *) atp->t, (char *) tp->t, tp->len) == 0)
                        error(ERROR, "Duplicate macro argument");
                *args->lp++ = *tp;
                narg++;
                tp += 1;
                if (tp->type == RP)
                    break;
                if (tp->type != COMMA)
                {
                    err++;
                    break;
                }
                tp += 1;
            }
            if (err)
            {
                error(ERROR, "Syntax error in macro parameters");
                return;
            }
        }
        tp += 1;
    }
    trp->tp = tp;
    if (((trp->lp) - 1)->type == NL)
        trp->lp -= 1;
    def = normtokenrow(trp);
    if (np->flag & ISDEFINED)
    {
        if (comparetokens(def, np->vp)
            || (np->ap == NULL) != (args == NULL)
            || (np->ap && comparetokens(args, np->ap)))
        {
            if ( np->loc )
                error(ERROR,
                    "Macro redefinition of %t (already defined at %s)",
                    trp->bp + 2, np->loc);
            else
                error(ERROR,
                    "Macro redefinition of %t (already defined at %s)",
                    trp->bp + 2, "commandline" );
        }
    }
    if (args)
    {
        Tokenrow *tap;

        tap = normtokenrow(args);
        dofree(args->bp);
        dofree(args);
        args = tap;
    }
    np->ap = args;
    np->vp = def;
    np->flag |= ISDEFINED;

    /* build location string of macro definition */
    for (cp = location, s = cursource; s; s = s->next)
        if (*s->filename)
        {
            if (cp != location)
                *cp++ = ' ';
            SAL_WNODEPRECATED_DECLARATIONS_PUSH /* sprintf (macOS 13 SDK) */
            sprintf((char *)cp, "%s:%d", s->filename, s->line);
            SAL_WNODEPRECATED_DECLARATIONS_POP
            cp += strlen((char *)cp);
        }

    np->loc = newstring(location, strlen((char *)location), 0);

    if (Mflag)
    {
        if (np->ap)
            error(INFO, "Macro definition of %s(%r) [%r]", np->name, np->ap, np->vp);
        else
            error(INFO, "Macro definition of %s [%r]", np->name, np->vp);
    }
}

/*
 * Definition received via -D or -U
 */

void
    doadefine(Tokenrow * trp, int type)
{
    Nlist *np;
    static uchar onestr[2] = "1";
    static Token onetoken[1] = {{NUMBER, 0, 1, onestr, 0}};
    static Tokenrow onetr = {onetoken, onetoken, onetoken + 1, 1};

    trp->tp = trp->bp;
    if (type == 'U')
    {
        if (trp->lp - trp->tp != 2 || trp->tp->type != NAME)
            goto syntax;
        if ((np = lookup(trp->tp, 0)) == NULL)
            return;
        np->flag &= ~ISDEFINED;
        return;
    }

    if (type == 'A')
    {
        if (trp->tp >= trp->lp || trp->tp->type != NAME)
            goto syntax;
        trp->tp->type = ARCHITECTURE;
        np = lookup(trp->tp, 1);
        np->flag |= ISARCHITECTURE;
        trp->tp += 1;
        if (trp->tp >= trp->lp || trp->tp->type == END)
        {
            np->vp = &onetr;
            return;
        }
        else
            error(FATAL, "Illegal -A argument %r", trp);
    }

    if (trp->tp >= trp->lp || trp->tp->type != NAME)
        goto syntax;
    np = lookup(trp->tp, 1);
    np->flag |= ISDEFINED;
    trp->tp += 1;
    if (trp->tp >= trp->lp || trp->tp->type == END)
    {
        np->vp = &onetr;
        return;
    }
    if (trp->tp->type != ASGN)
        goto syntax;
    trp->tp += 1;
    if ((trp->lp - 1)->type == END)
        trp->lp -= 1;
    np->vp = normtokenrow(trp);
    return;
syntax:
    error(FATAL, "Illegal -D or -U argument %r", trp);
}



/*
 * Do macro expansion in a row of tokens.
 * Flag is NULL if more input can be gathered.
 */

void
    expandrow(Tokenrow * trp, char *flag)
{
    Token * tp;
    Nlist * np;

    MacroValidatorList  validators;
    mvl_init(&validators);
    /* Sets all token-identifiers to 0 because tokens may not be initialised (never use C!) */
    tokenrow_zeroTokenIdentifiers(trp);

    if (flag)
        setsource(flag, -1, -1, "", 0);
    for (tp = trp->tp; tp < trp->lp;)
    {
        mvl_check(&validators, tp);

        if (tp->type != NAME
            || quicklook(tp->t[0], tp->len > 1 ? tp->t[1] : 0) == 0
            || (np = lookup(tp, 0)) == NULL
            || (np->flag & (ISDEFINED | ISMAC)) == 0
            || (np->flag & ISACTIVE) != 0)
        {
            tp++;
            continue;
        }
        trp->tp = tp;
        if (np->val == KDEFINED)
        {
            tp->type = DEFINED;
            if ((tp + 1) < trp->lp && (tp + 1)->type == NAME)
                (tp + 1)->type = NAME1;
            else
                if ((tp + 3) < trp->lp && (tp + 1)->type == LP
                    && (tp + 2)->type == NAME && (tp + 3)->type == RP)
                    (tp + 2)->type = NAME1;
                else
                    error(ERROR, "Incorrect syntax for `defined'");
            tp++;
            continue;
        }
        else
            if (np->val == KMACHINE)
            {
                if (((tp - 1) >= trp->bp) && ((tp - 1)->type == SHARP))
                {
                    tp->type = ARCHITECTURE;
                    if ((tp + 1) < trp->lp && (tp + 1)->type == NAME)
                        (tp + 1)->type = NAME2;
                    else
                        if ((tp + 3) < trp->lp && (tp + 1)->type == LP
                            && (tp + 2)->type == NAME && (tp + 3)->type == RP)
                            (tp + 2)->type = NAME2;
                        else
                            error(ERROR, "Incorrect syntax for `#machine'");
                }
                tp++;
                continue;
            }

        if (np->flag & ISMAC)
            builtin(trp, np->val);
        else
        {
            // coverity[overrun-buffer-arg: FALSE] - a multiple of trp->max is allocated, not trp->max itself
            expand(trp, np, &validators);
        }
        tp = trp->tp;
    }   // end for
    if (flag)
        unsetsource();

    mvl_destruct(&validators);
}

/*
 * Expand the macro whose name is np, at token trp->tp, in the tokenrow.
 * Return trp->tp at the first token next to be expanded
 * (ordinarily the beginning of the expansion)
 * I.e.: the same position as before!
 * Only one expansion is performed, then we return to the expandrow()
 * loop and start at same position.
 */

void
    expand(Tokenrow * trp, Nlist * np, MacroValidatorList * pValidators)
{
    Tokenrow ntr;
    int ntokc, narg;
    Tokenrow *atr[NARG + 1];

    if (Mflag == 2)
    {
        if (np->ap)
            error(INFO, "Macro expansion of %t with %s(%r)", trp->tp, np->name, np->ap);
        else
            error(INFO, "Macro expansion of %t with %s", trp->tp, np->name);
    }

    copytokenrow(&ntr, np->vp);         /* copy macro value */
    if (np->ap == NULL)                 /* parameterless */
        ntokc = 1;
    else
    {
        int i;

        ntokc = gatherargs(trp, atr, &narg);
        if (narg < 0)
        {                               /* not actually a call (no '(') */
            trp->tp++;
            return;
        }
        if (narg != rowlen(np->ap))
        {
            error(ERROR, "Disagreement in number of macro arguments");
            trp->tp += ntokc;
            return;
        }

        /** If gatherargs passed a macro validating token, this token
            must become valid here.
            trp->tp+0 was checked in expandrow(), so we don't need to do it
            again here:
        */

        for (i = 1; i < ntokc; i++)
        {
            mvl_check(pValidators,trp->tp+i);
        }

        substargs(np, &ntr, atr);       /* put args into replacement */
        for (i = 0; i < narg; i++)
        {
            dofree(atr[i]->bp);
            dofree(atr[i]);
        }
    }

    doconcat(&ntr);                     /* execute ## operators */
    ntr.tp = ntr.bp;
    makespace(&ntr, trp->tp);

    tokenrow_zeroTokenIdentifiers(&ntr);
    insertrow(trp, ntokc, &ntr);

        /* add validator for just invalidated macro:
        */

    np->flag |= ISACTIVE;
    if (trp->tp != trp->lp)
    {   /* tp is a valid pointer: */
        mvl_add(pValidators,np,trp->tp);
    }
    else
    {   /* tp is == lp, therefore does not point to valid memory: */
        mvl_add(pValidators,np,NULL);
    }
        /* reset trp->tp to original position:
        */

    trp->tp -= ntr.lp - ntr.bp;         /* so the result will be tested for macros from the same position again */

    dofree(ntr.bp);

    return;
}

/*
 * Gather an arglist, starting in trp with tp pointing at the macro name.
 * Return total number of tokens passed, stash number of args found.
 * trp->tp is not changed relative to the tokenrow.
 */

int
    gatherargs(Tokenrow * trp, Tokenrow ** atr, int *narg)
{
    int parens = 1;
    int ntok = 0;
    Token *bp, *lp;
    Tokenrow ttr;
    int ntokp;
    int needspace;

    *narg = -1;                         /* means that there is no macro
                                         * call */

    /* look for the ( */
    for (;;)
    {
        trp->tp++;
        ntok++;
        if (trp->tp >= trp->lp)
        {
            // coverity[overrun-buffer-arg: FALSE] - a multiple of trp->max is allocated, not trp->max itself
            gettokens(trp, 0);
            if ((trp->lp - 1)->type == END)
            {
                trp->lp -= 1;
                trp->tp -= ntok;
                return ntok;
            }
        }
        if (trp->tp->type == LP)
            break;
        if (trp->tp->type != NL)
            return ntok;
    }
    *narg = 0;
    ntok++;
    ntokp = ntok;
    trp->tp++;
    /* search for the terminating ), possibly extending the row */
    needspace = 0;
    while (parens > 0)
    {
        if (trp->tp >= trp->lp)
        {
            // coverity[overrun-buffer-arg: FALSE] - a multiple of trp->max is allocated, not trp->max itself
            gettokens(trp, 0);
        }
        if (needspace)
        {
            needspace = 0;
            /* makespace(trp); [rh] */
        }
        if (trp->tp->type == END)
        {
            trp->lp -= 1;
            trp->tp -= ntok;
            error(ERROR, "EOF in macro arglist");
            return ntok;
        }
        if (trp->tp->type == NL)
        {
            trp->tp += 1;
            adjustrow(trp, -1);
            trp->tp -= 1;
            /* makespace(trp); [rh] */
            needspace = 1;
            continue;
        }
        if (trp->tp->type == LP)
            parens++;
        else
            if (trp->tp->type == RP)
                parens--;
        trp->tp++;
        ntok++;
    }
    trp->tp -= ntok;
    /* Now trp->tp won't move underneath us */
    lp = bp = trp->tp + ntokp;
    for (; parens >= 0; lp++)
    {
        if (lp->type == LP)
        {
            parens++;
            continue;
        }
        if (lp->type == RP)
            parens--;
        if (lp->type == DSHARP)
            lp->type = DSHARP1;         /* ## not special in arg */
        if ((lp->type == COMMA && parens == 0) ||
                ( parens < 0 && ((lp - 1)->type != LP)))
        {
            if (*narg >= NARG - 1)
                error(FATAL, "Sorry, too many macro arguments");
            ttr.bp = ttr.tp = bp;
            ttr.lp = lp;
            atr[(*narg)++] = normtokenrow(&ttr);
            bp = lp + 1;
        }
    }
    return ntok;
}

/*
 * substitute the argument list into the replacement string
 *  This would be simple except for ## and #
 */

void
    substargs(Nlist * np, Tokenrow * rtr, Tokenrow ** atr)
{
    Tokenrow tatr;
    Token *tp;
    int ntok, argno;

    for (rtr->tp = rtr->bp; rtr->tp < rtr->lp;)
    {
        if (rtr->tp->type == SHARP)
        {                               /* string operator */
            tp = rtr->tp;
            rtr->tp += 1;
            if ((argno = lookuparg(np, rtr->tp)) < 0)
            {
                error(ERROR, "# not followed by macro parameter");
                continue;
            }
            ntok = 1 + (int)(rtr->tp - tp);
            rtr->tp = tp;
            insertrow(rtr, ntok, stringify(atr[argno]));
            continue;
        }
        if (rtr->tp->type == NAME
            && (argno = lookuparg(np, rtr->tp)) >= 0)
        {
            if (((rtr->tp + 1) < rtr->lp && (rtr->tp + 1)->type == DSHARP)
                || (rtr->tp != rtr->bp  && (rtr->tp - 1)->type == DSHARP))
            {
                copytokenrow(&tatr, atr[argno]);
                makespace(&tatr, rtr->tp);
                insertrow(rtr, 1, &tatr);
                dofree(tatr.bp);
            }
            else
            {
                copytokenrow(&tatr, atr[argno]);
                makespace(&tatr, rtr->tp);
                expandrow(&tatr, "");
                insertrow(rtr, 1, &tatr);
                dofree(tatr.bp);
            }
            continue;
        }
        rtr->tp++;
    }
}

/*
 * Evaluate the ## operators in a tokenrow
 */

void
    doconcat(Tokenrow * trp)
{
    Token *ltp, *ntp;
    Tokenrow ntr;
    size_t len;

    for (trp->tp = trp->bp; trp->tp < trp->lp; trp->tp++)
    {
        if (trp->tp->type == DSHARP1)
            trp->tp->type = DSHARP;
        else
            if (trp->tp->type == DSHARP)
            {
                int  i;
                char tt[NCONCAT];

                ltp = trp->tp - 1;
                ntp = trp->tp + 1;

                if (ltp < trp->bp || ntp >= trp->lp)
                {
                    error(ERROR, "## occurs at border of replacement");
                    continue;
                }

                ntp = ltp;
                i   = 1;
                len = 0;

                do
                {
                    if (len + ntp->len + ntp->wslen > sizeof(tt))
                    {
                        error(ERROR, "## string concatenation buffer overrun");
                        break;
                    }

                    if (ntp != trp->tp + 1)
                    {
                        strncpy((char *) tt + len, (char *) ntp->t - ntp->wslen,
                                ntp->len + ntp->wslen);
                        len += ntp->len + ntp->wslen;
                    }
                    else
                    {
                        // remove spaces around ##
                        strncpy((char *) tt + len, (char *) ntp->t, ntp->len);
                        len += ntp->len;
                    }

                    ntp = trp->tp + i;
                    i++;
                }
                while (ntp < trp->lp);

                tt[len] = '\0';
                setsource("<##>", -1, -1, tt, 0);
                maketokenrow(3, &ntr);
                // coverity[overrun-buffer-arg: FALSE] - a multiple of trp->max is allocated, not trp->max itself
                gettokens(&ntr, 1);
                unsetsource();
                if (ntr.bp->type == UNCLASS)
                    error(WARNING, "Bad token %r produced by ##", &ntr);
                while ((ntr.lp-1)->len == 0 && ntr.lp != ntr.bp)
                    ntr.lp--;

                doconcat(&ntr);
                trp->tp = ltp;
                makespace(&ntr, ltp);
                insertrow(trp, (int)(ntp - ltp), &ntr);
                dofree(ntr.bp);
                trp->tp--;
            }
    }
}

/*
 * tp is a potential parameter name of macro mac;
 * look it up in mac's arglist, and if found, return the
 * corresponding index in the argname array.  Return -1 if not found.
 */

int
    lookuparg(Nlist * mac, Token const * tp)
{
    Token *ap;

    if (tp->type != NAME || mac->ap == NULL)
        return -1;
    for (ap = mac->ap->bp; ap < mac->ap->lp; ap++)
    {
        if (ap->len == tp->len && strncmp((char *) ap->t, (char *) tp->t, ap->len) == 0)
            return (int)(ap - mac->ap->bp);
    }
    return -1;
}

/*
 * Return a quoted version of the tokenrow (from # arg)
 */

#define STRLEN  512
Tokenrow *
    stringify(Tokenrow * vp)
{
    static Token t = {STRING, 0, 0, NULL, 0};
    static Tokenrow tr = {&t, &t, &t + 1, 1};
    Token *tp;
    uchar s[STRLEN];
    uchar *sp = s, *cp;
    int i, instring;

    *sp++ = '"';
    for (tp = vp->bp; tp < vp->lp; tp++)
    {
        instring = tp->type == STRING || tp->type == CCON;
        if (sp + 2 * tp->len + tp->wslen  >= &s[STRLEN - 10])
        {
            error(ERROR, "Stringified macro arg is too long");
            break;
        }

        // Change by np 31.10.2001, #93725 - begin
        if ( tp->wslen > 0 )
            *sp++ = ' ';
        // change end.

        for (i = 0, cp = tp->t; (unsigned int)i < tp->len; i++)
        {
            if (instring && (*cp == '"' || *cp == '\\'))
                *sp++ = '\\';
            *sp++ = *cp++;
        }
    }
    *sp++ = '"';
    *sp = '\0';
    sp = s;
    t.len = strlen((char *) sp);
    t.t = newstring(sp, t.len, 0);
    return &tr;
}

/*
 * expand a builtin name
 */

void
    builtin(Tokenrow * trp, int biname)
{
    char *op;
    Token *tp;
    Source *s;

    tp = trp->tp;
    trp->tp++;
    /* need to find the real source */
    s = cursource;
    while (s && s->fd == -1)
        s = s->next;
    if (s == NULL)
        s = cursource;
    /* most are strings */
    tp->type = STRING;
    if (tp->wslen)
    {
        *outptr++ = ' ';
        tp->wslen = 1;
    }
    op = outptr;
    *op++ = '"';
    switch (biname)
    {

        case KLINENO:
            tp->type = NUMBER;
            op = outnum(op - 1, s->line);
            break;

        case KFILE:
            {
                char *src = s->filename;

                while ((*op++ = *src++) != 0)
                    if (src[-1] == '\\')
                        *op++ = '\\';
                op--;
                break;
            }

        case KDATE:
            strncpy(op, curtime + 4, 7);
            strncpy(op + 7, curtime + 20, 4);
            op += 11;
            break;

        case KTIME:
            strncpy(op, curtime + 11, 8);
            op += 8;
            break;

        default:
            error(ERROR, "cpp botch: unknown internal macro");
            return;
    }
    if (tp->type == STRING)
        *op++ = '"';
    tp->t = (uchar *) outptr;
    tp->len = op - outptr;
    outptr = op;
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */

91%


¤ Dauer der Verarbeitung: 0.13 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung ist noch experimentell.