macros.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 1,398 行 · 第 1/3 页

C
1,398
字号

    space = 0;
    t = v;
    for( p = v; *p != '\0'; ++p ) {
        if( !isws( *p ) ) {
            if( space ) {
                *t = ' ';
                ++t;
            }
            *t = *p;
            ++t;
            space = 0;
        } else {
            space = 1;
        }
    }
    *t = '\0';
    return( v );
}


#ifdef __WATCOMC__
#pragma on (check_stack);
#endif
STATIC void addMacro( const char *name, char *value )
/****************************************************
 * post:    new macro possibly allocated, copy of name made
 */
{
    char    macro[MAX_MAC_NAME];
    MACRO   *new;

    assert( *name != ENVVAR );

    value = trimMacroValue( value );
    makeMacroName( macro, name ); // Does assert( IsMacroName( name ) );

    new = getMacroNode( macro );     /* check if redefinition */

    if( new != NULL && !new->readonly ) {   /* reuse old node */
        FreeSafe( (void *)new->value );
        new->value = value;
        new->readonly = Glob.macreadonly;
    } else if( new == NULL ) {
        new = MallocSafe( sizeof( *new ) ); /* get memory for new node */
        new->node.name = StrDupSafe( macro );
        AddHashNode( macTab, (HASHNODE *)new );
        new->value = value;
        new->readonly = Glob.macreadonly;
    } else {
        FreeSafe( value );  /* read only macro - don't change */
    }
}
#ifdef __WATCOMC__
#pragma off(check_stack);
#endif


extern BOOLEAN IsMacroName( const char *inName )
/***********************************************
 * returns: TRUE if name is a valid macro name, otherwise FALSE and print
 * an error message
 */
{
    char const  *current = inName;
    int         pos = 0;

    assert( inName != NULL );

    while( pos < MAX_MAC_NAME && *current != NULLCHAR && *current != COLON ) {
        if( !ismacc( *current ) ) {
            PrtMsg( ERR | LOC | INVALID_MACRO_NAME, inName );
            return( FALSE );
        }
        pos++, current++;
    }
    if( pos == 0 ) {
        PrtMsg( ERR | LOC | INVALID_MACRO_NAME, inName );
        return( FALSE );
    }
    if( pos >= MAX_MAC_NAME ) {
        PrtMsg( ERR | LOC | MAXIMUM_TOKEN_IS, MAX_MAC_NAME - 1 );
        return( FALSE );
    }

    return( TRUE );
}


#ifdef __WATCOMC__
#pragma on (check_stack);
#endif
extern void UnDefMacro( const char *name )
/*****************************************
 * pre:     IsMacroName( name ); getMacroNode( name ) != NULL
 * post:    MACRO node deallocated
 */
{
    char    macro[MAX_MAC_NAME];
    MACRO   *dead;

    makeMacroName( macro, name ); // Does assert( IsMacroName( name ) );

    if( *macro == ENVVAR ) {
        ENV_TRACKER     *env;

        env = MallocSafe( sizeof( ENV_TRACKER ) + strlen( macro ) + 1 );
        FmtStr( env->value, "%s=", macro + 1 );
        PutEnvSafe( env );
        return;
    }

    dead = (MACRO *)RemHashNode( macTab, macro, TRUE );

    assert( dead != NULL );

    FreeSafe( dead->node.name );
    FreeSafe( (void *)dead->value );
    FreeSafe( dead );
}
#ifdef __WATCOMC__
#pragma off(check_stack);
#endif


extern char *WrnGetMacroValue( const char *name )
/***********************************************/
{
    const char  *p;

    p = GetMacroValue( name );
    if( p == NULL ) {
        PrtMsg( DBG | WRN | LOC | MACRO_UNDEFINED, name );   /* 13-Dec-90 DJG */
        // we did this to minimize the number of debugging messages but
        // it causes problems when it defines a macro for the user
        //UnGetCH( EOL );
        //DefMacro( name );                             /* 12-jul-93 AFS */
    }
    return( (char *)p );
    /* note we return NULL if it was undefined! */
}


extern char *DeMacroSpecial( char *InString)
/*******************************************
 * This function is to specially handle the special macros
 * in the dependencies
 */
{
    char    *old;
    char    *current;
    VECSTR  outString;
    char    *tempString;
    char    buffer[6];
    int     pos;

    assert( InString != NULL );
    current = InString;
    old     = InString;

    outString = StartVec();

    while( *current != NULLCHAR ) {
        if( *current == SPECIAL_TMP_DOL_C ) {
            CatNStrToVec( outString, old, current - old );
            pos = 0;
            UnGetCH( STRM_MAGIC );
            buffer[pos++] = *(current++);
            if( ismsspecial( *current ) && !ismsmodifier( *(current + 1) ) ) {
                buffer[pos++] = *(current++);
            } else {
                assert( ismsspecial( *current ) );
                buffer[pos++] = *(current++);
                if( ismsmodifier( *current ) ) {
                    buffer[pos++] = *(current++);
                }
            }
            old = current;
            buffer[pos] = NULLCHAR;
            InsString( buffer, FALSE );
            tempString = DeMacro( STRM_MAGIC );
            PreGetCH();   // eat STRM_MAGIC
            CatStrToVec( outString, tempString );
            FreeSafe( tempString);
        }
        ++current;
    }
    CatNStrToVec( outString, old, current - old + 1 );
    return( FinishVec( outString ) );
}


/*
 * end1 is what the caller passed to DeMacro - it is pushed back into the
 * input stream.
 * end2 is for our own purposes
 *
 * deMacroText calls deMacroToEnd, and deMacroToEnd might call deMacroText.
 *
 * deMacroToEnd does a single pass of substitution.  It calls deMacroText to
 * handle constructs such as $(text); thus allowing $(text$(subtext)).  All
 * other constructs are written with their current value.
 *
 * deMacroText scans the string that deMacroToEnd returned for DOLLARs.  If
 * it doesn't find one it returns the string.  If a DOLLAR is found, a
 * STRM_MAGIC is pushed, the string is pushed, and deMacroToEnd is called
 * again (ending at STRM_MAGIC).  This process is repeated until no DOLLARs
 * remain.
 *
 * This pair always stops at EOL, STRM_MAGIC, or STRM_END.
 *
 * Note that if a MAC_PUNC is passed for one of the end tokens, it is
 * assumed to imply MAC_WS as well.  This is used in mpreproc.c to find the
 * end of a macro name for things such as !ifdef, !undef, etc.
 */
STATIC char *deMacroText( int depth, TOKEN_T end1, TOKEN_T end2 );


STATIC char *ProcessToken( int depth, TOKEN_T end1, TOKEN_T end2, TOKEN_T t )
/****************************************************************************
 * Processes the tokens returned from lexToken in deMacroToEnd
 */
{
    STRM_T      temp;
    char        temp_str[2];
    char        macname[MAX_TOK_SIZE];
    int         pos;
    char        *p;
    char        *p2;
    char const  *cp2;

    switch( t ) {
    case MAC_START:                     /* recurse, get macro name */
        /*
         * in microsoft nmake and in POSIX mode,
         * $HELLO is considered as $(H)ELLO
         * if there are no parentheses then it takes only first char.
         * after the $
         */
        if( !Glob.microsoft && !Glob.posix ) {
            p = deMacroText( depth + 1, end1, MAC_PUNC );
        } else {
            temp = PreGetCH ();
            if( ismacc( temp ) ) {
                temp_str[1] = NULLCHAR;
                temp_str[0] = temp;
                p = StrDupSafe( temp_str );
            } else {
                p = StrDupSafe( "" );
            }
        }

        if( IsMacroName( p ) ) {
            p2 =  WrnGetMacroValue( p );
            FreeSafe( p );
            if( p2 != NULL ) {
                return( p2 );
            }
            return( NULL );
        }
        FreeSafe( p );
        break;

    case MAC_DOLLAR:
        return( StrDupSafe( TMP_DOL_S ) );      /* write a place holder */

    case MAC_COMMENT:
        return( StrDupSafe( TMP_COMMENT_S ) );  /* write a place holder */

    case MAC_OPEN:                      /* recurse, get macro name */
        if( !Glob.microsoft && !Glob.posix ) {
            p = deMacroText( depth + 1, end1, MAC_CLOSE );
            if( IsMacroName( p ) ) {
                p2 =  WrnGetMacroValue( p );
                FreeSafe( p );
                if( p2 != NULL ) {
                    return( p2 );
                }
                return( NULL );
            }
            FreeSafe( p );
        } else {
            pos = 0;
            temp   = PreGetCH();
            if( ismsspecial( temp ) ) {
                UnGetCH( temp );
                // This is to invoke LexDollar
                t = LexToken( LEX_MS_MAC );
                // This is the only time to get the modifier
                GetModifier();
                p = ProcessToken( depth, end1, end2, t );
                temp = PreGetCH();
                if( temp != ')' ) {
                    PrtMsg( ERR | LOC | ILLEGAL_CHARACTER_IN_MAC, temp );
                    break;
                }
                return( p );
            } else {
                for( ;; ) {
                    if( temp == ')' ) {
                        break;
                    } else if( temp == STRM_MAGIC ||
                               temp == STRM_END   ||
                               temp == EOL ) {
                        UnGetCH( temp );
                        break;
                    }
                    if( pos < MAX_TOK_SIZE -1 ) {
                        macname[pos++] = temp;
                    }
                    temp = PreGetCH();
                }
                macname[pos] = NULLCHAR;
                if( IsMacroName( macname ) ) {
                    p2 =  WrnGetMacroValue( macname );
                    if( p2 != NULL ) {
                        return( p2 );
                    }
                    return( NULL );
                }
            }
        }
        break;

    case MAC_EXPAND_ON:                 /* fall through */
    case MAC_EXPAND_OFF:
        /* do nothing */
        break;

    case MAC_CUR:                       /* fall through */
    case MAC_FIRST:
    case MAC_LAST:
        /* static pointer returned so we need to duplicate string */
        cp2 = specialValue( t );
        if( cp2 != NULL ) {
            return( StrDupSafe( cp2 ) );
        }
        return( NULL );

    case MAC_ALL_DEP:
        p = GetCurDeps( FALSE, FALSE );
        massageDollarOctothorpe( p );
        return( p );

    case MAC_INF_DEP:
        p = GetCurDeps( FALSE, TRUE );
        massageDollarOctothorpe( p );
        return( p );

    case MAC_YOUNG_DEP:
        p = GetCurDeps( TRUE, FALSE );
        massageDollarOctothorpe( p );
        return( p );

    case MAC_NAME:                      /* fall through */
    case MAC_WS:
    case MAC_PUNC:
        p = CurAttr.ptr;
        CurAttr.ptr  = NULL;
        return( p );

    default:
#ifdef DEVELOPMENT
        PrtMsg( FTL | LOC | INVALID_TOKEN_IN, t, "deMacroToEnd()" );
#else
        PrtMsg( WRN | LOC | IGNORE_OUT_OF_PLACE_M, M_UNKNOWN_TOKEN );
        break;
#endif
    }

    return( NULL );
}


STATIC char *deMacroToEnd( int depth, TOKEN_T end1, TOKEN_T end2 )
/*****************************************************************
 * post:    0 or more characters removed from input; next character of
 *          input is STRM_END || STRM_MAGIC || EOL || end1 || end2
 * returns: pointer to demacro'd string (caller must FreeSafe)
 */
{
    TOKEN_T t;
    VECSTR  vec;            /* we build expansion here  */
    char    *p;             /* temp str */

    assert(     end1 == EOL
            ||  end1 == MAC_PUNC
            ||  end1 == STRM_MAGIC
            ||  end1 == STRM_END
            ||  end1 == MAC_WS
    );

    assert(     end2 == EOL
            ||  end2 == MAC_PUNC
            ||  end2 == STRM_MAGIC
            ||  end2 == STRM_END
            ||  end2 == MAC_EXPAND_OFF
            ||  end2 == MAC_CLOSE
    );

    vec = StartVec();

    for( ;; ) {
        t = LexToken( LEX_MAC_SUBST );

        assert( t != MAC_TEXT );            /* should never recv this tok */

        if( t == MAC_CLOSE && end2 != MAC_CLOSE ) {
            t = MAC_PUNC;
            CurAttr.ptr = StrDupSafe( ")" );
        }

        if(     t == STRM_END               /* always stops at these */
            ||  t == STRM_MAGIC
            ||  t == EOL
            ||  t == end2
            ||  t == end1
            ||  ( t == MAC_WS && ( end2 == MAC_PUNC || end1 == MAC_PUNC ) )
                ) {
            break;
        }

        p = ProcessToken( depth, end1, end2, t );
        if( p != NULL ) {
            CatStrToVec( vec, p );
            FreeSafe( p );
        }
    }

    /* put back the token we demacro'd until */
    switch( t ) {
    case MAC_PUNC:
    case MAC_WS:
        InsString( CurAttr.ptr, TRUE );
        break;
    case EOL:               /* fall through */
    case STRM_END:
    case STRM_MAGIC:
        UnGetCH( t );
        break;
    }

    return( FinishVec( vec ) );
}


STATIC char *deMacroText( int depth, TOKEN_T end1, TOKEN_T end2 )
/****************************************************************
 * post:    same as deMacroToEnd
 * returns: same as deMacroToEnd
 */
{
    char    *result;
    char    *p;

    if( depth > MAX_MAC_NEST ) {
        PrtMsg( FTL | LOC | CANNOT_NEST_FURTHER );
    }

    result = deMacroToEnd( depth, end1, end2 );
    while( strchr( result, DOLLAR ) != NULL ) {
        UnGetCH( STRM_MAGIC );
        InsString( result, TRUE );

        ++depth;
        if( depth > MAX_MAC_NEST ) {

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?