macro.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 337 行

C
337
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  WHEN YOU FIGURE OUT WHAT THIS FILE DOES, PLEASE
*               DESCRIBE IT HERE!
*
****************************************************************************/


#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "error.h"
#include "macro.h"
#include "memory.h"

#define DEFINE          1
#define UNDEFINE        2

#define PURGE_ALL       1
#define PURGE_DEFINE    2
#define PURGE_NOACTION  0x0000
#define PURGE_PURGED    0x0001
#define PURGE_SKIPPED   0x0002

static int      purge_from_list( int purgeOnly, const char *name );
static void     append_list( struct ListElem *elem );
static void     delete_item( struct ListElem *elem );
static char *   validate_define_str( const char *str );


/*
 * Define the ListElem and UndefItem structures.
 */
struct ListElem {
    int                 type;       /* DEFINE or UNDEFINE */
    char *              name;       /* the macro's name */
    char *              value;      /* NULL if no expansion */
    struct ListElem *   next;       /* next macro in the list */
};

static struct ListElem *macroList;


/*
 * Initialize the macro list.
 */
void InitMacro( void )
/********************/
{
    macroList = NULL;
}


/*
 * Add one more macro definition.  The macro must be of the form NAME[=VALUE].
 * Returns non-zero on success, or zero if the string is incorrectly formed.
 */
int DefineMacro( const char *defineStr )
/**************************************/
{
    struct ListElem *   newElem;
    const char *        p;
    char *              name;
    char *              value;
    size_t              len;
    const char *        str;
    int                 freeStrFlag = 0;

    /*** Validate the string ***/
    str = validate_define_str( defineStr );
    if( str != NULL ) {
        freeStrFlag = 1;
    } else {
        str = defineStr;
    }

    /*** Extract the macro name from str ***/
    for( p=str,len=0; *p!='\0'; p++,len++ ) {
        if( *p == '=' )  break;
    }
    if( len == 0 )  return( 0 );
    name = AllocMem( len + 1 );
    memcpy( name, str, len );
    name[len] = '\0';
    if( *p != '\0' )  p++;

    /*** Extract the macro value from str ***/
    while( isspace( *p ) )  p++;
    if( *p != '\0' ) {
        value = AllocMem( strlen( p ) + 1 );
        strcpy( value, p );
    } else {
        value = NULL;
    }

    /*** Initialize a new list element ***/
    newElem = AllocMem( sizeof(struct ListElem) );
    newElem->type = DEFINE;
    newElem->name = name;
    newElem->value = value;
    newElem->next = NULL;

    /*** Add it to the list ***/
    purge_from_list( PURGE_ALL, name ); /* so we don't have any duplicates */
    append_list( newElem );

    if( freeStrFlag )  FreeMem( (char*)str );
    return( 1 );
}


/*
 * Remove a macro definition.
 */
void UndefineMacro( const char *name )
/************************************/
{
    struct ListElem *   newElem;

    /*** Add an undefine directive if needed ***/
    if( purge_from_list( PURGE_DEFINE, name )  ==  PURGE_NOACTION ) {
        newElem = AllocMem( sizeof(struct ListElem) );
        newElem->type = UNDEFINE;
        newElem->name = (char*)name;
        newElem->value = NULL;
        newElem->next = NULL;
        append_list( newElem );
    }
}


/*
 * Get the next define string in the list.  Returns NULL if nothing to get.
 */
char *GetNextDefineMacro( void )
/******************************/
{
    struct ListElem *   curElem = macroList;
    char *              str;
    size_t              len;

    while( curElem != NULL ) {
        if( curElem->type == DEFINE ) {
            /*** Allocate a buffer to hold it ***/
            len = strlen( curElem->name );      /* room for NAME */
            if( curElem->value != NULL ) {
                len++;                          /* room for = */
                len += strlen( curElem->value );/* room for VALUE */
            }
            len++;                              /* room for '\0' */
            str = AllocMem( len );

            /*** Fill in the buffer ***/
            strcpy( str, curElem->name );
            if( curElem->value != NULL ) {
                strcat( str, "=" );
                strcat( str, curElem->value );
            }

            /*** Clean up and go home ***/
            delete_item( curElem );
            return( str );
        }
        curElem = curElem->next;
    }

    return( NULL );
}


/*
 * Get the next undefine string in the list.  Returns NULL if nothing to get.
 */
char *GetNextUndefineMacro( void )
/********************************/
{
    struct ListElem *   curElem = macroList;
    char *              str;
    size_t              len;

    while( curElem != NULL ) {
        if( curElem->type == UNDEFINE ) {
            /*** Copy the macro name ***/
            len = strlen( curElem->name ) + 1;  /* room for NAME\0 */
            str = AllocMem( len );
            strcpy( str, curElem->name );

            /*** Clean up and go home ***/
            delete_item( curElem );
            return( str );
        }
        curElem = curElem->next;
    }

    return( NULL );
}


/*
 * Removes items from the macro list; use purgeOnly to specify which items
 * to purge.  Returns PURGE_NOACTION if nothing was done, PURGE_PURGED if
 * a matching item was purged, or PURGE_SKIPPED if an item with the correct
 * name was found but which wasn't allowed to be purged due to purgeOnly.
 */
static int purge_from_list( int purgeOnly, const char *name )
/***********************************************************/
{
    struct ListElem *   curElem = macroList;
    int                 retcode = PURGE_NOACTION;

    /*** Try to find the item ***/
    while( curElem != NULL ) {
        if( !strcmp( name, curElem->name ) ) {
            if( (purgeOnly==PURGE_ALL)  ||  (purgeOnly==PURGE_DEFINE && curElem->type==DEFINE) ) {
                /*** Found one we're allowed to delete ***/
                delete_item( curElem );
                retcode = PURGE_PURGED;
                break;
            } else {
                /*** Found one we're not allowed to delete ***/
                retcode = PURGE_SKIPPED;
                break;
            }
        }
        curElem = curElem->next;
    }

    return( retcode );
}


/*
 * Append an item to the list.
 */
void append_list( struct ListElem *elem )
/***************************************/
{
    struct ListElem *   curElem = macroList;
    struct ListElem *   prevElem = NULL;

    while( curElem != NULL ) {
        prevElem = curElem;
        curElem = curElem->next;
    }

    if( prevElem == NULL ) {
        macroList = elem;
    } else {
        prevElem->next = elem;
    }
}


/*
 * Remove the specified item from the list, and free all its memory.
 */
static void delete_item( struct ListElem *elem )
/**********************************************/
{
    struct ListElem *   curElem = macroList;
    struct ListElem *   prevElem = NULL;

    while( curElem != NULL ) {
        if( curElem == elem ) {
            if( prevElem == NULL ) {
                macroList = curElem->next;
            } else {
                prevElem->next = curElem->next;
            }
            FreeMem( curElem->name );
            if( curElem->value != NULL )  FreeMem( curElem->value );
            FreeMem( curElem );
        }
        prevElem = curElem;
        curElem = curElem->next;
    }
}


/*
 * Ensure that the given define string is valid, changing it if necessary.
 * Returns NULL if no changes must be made, or otherwise a pointer to a new
 * buffer containing the modified string.
 */
static char *validate_define_str( const char *str )
/*************************************************/
{
    char *              buf;
    int                 madeChange = 0;
    int                 count;

    /*** Make a new buffer ***/
    buf = AllocMem( strlen( str ) + 1 );
    strcpy( buf, str );

    /*** Transform "NAME=VALUE" to NAME=VALUE ***/
    if( str[0] == '"'  &&  str[strlen(str)-1] == '"' ) {
        for( count=0; count<=strlen(str)-2 ; count++ ) {
            buf[count] = str[count+1];
        }
        buf[count-1] = '\0';
        madeChange = 1;
    }

    if( madeChange ) {
        return( buf );
    } else {
        FreeMem( buf );
        return( NULL );
    }
}

⌨️ 快捷键说明

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