asmline.c

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

C
738
字号
/****************************************************************************
*
*                            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:  processing input line data and line queueing for macros
*
****************************************************************************/


#include "asmglob.h"
#include <ctype.h>

#include "asmins.h"
#include "asmdefs.h"

#if defined( _STANDALONE_ )

#include "directiv.h"
#include "asmalloc.h"
#include "condasm.h"
#include "asmexpnd.h"
#include "macro.h"
#include "asminput.h"

extern int              in_prologue;

typedef struct line_list {
    struct line_list    *next;
    char                *line;
} line_list;

/* NOTE: the line queue is now a STACK of line queues
 *       when a macro is being expanded, we push a new line queue on the stack
 *       thus there is 1 queue on the stack for every level of nesting in macros
 */
typedef struct input_queue {
    struct line_list    *head;
    struct line_list    *tail;
    struct input_queue  *next;
} input_queue;

typedef struct file_list {
    struct file_list    *next;
    union {
        FILE            *file;
        struct input_queue  *lines;
    };
    const FNAME         *srcfile;   /* name of include file */
    unsigned long       line_num;   /* current line in parent file */
    char                is_a_file;
    bool                hidden;
} file_list;

extern void             heap( char * );

extern char             write_to_file;
extern uint_8           CheckSeg;
extern int_8            DefineProc;             // TRUE if the definition of procedure
                                                // has not ended
extern unsigned long    PassTotal;

uint_32                 BufSize;                // size of CodeBuffer

static input_queue      *line_queue  = NULL;    // line queue
static file_list        *file_stack  = NULL;    // top of included file stack
static char             *IncludePath = NULL;

#if defined(__UNIX__)
#define                 INCLUDE_PATH_DELIM  ":"
#define                 DIR_SEPARATOR       '/'
#define                 DIR_SEP_STRING      "/"
#else
#define                 INCLUDE_PATH_DELIM  ";"
#define                 DIR_SEPARATOR       '\\'
#define                 DIR_SEP_STRING      "\\"
#endif

#else

uint_32                 AsmCodeAddress;     // program counter

#endif

int                     Token_Count;        // number of tokens on line
unsigned char           *AsmCodeBuffer;     // code buffer for generated bytes

#if defined( _STANDALONE_ )

static bool get_asmline( char *ptr, unsigned max, FILE *fp )
/**********************************************************/
{
    char        quote = 0;
    bool        skip;
    int         c;
    int         got_something;

    /* blow away any comments -- look for ;'s */
    /* note that ;'s are ok in quoted strings */

    skip = FALSE;
    got_something = FALSE;
    for( ;; ) {
        c = getc( fp );
        /* copy the line until we hit a NULL, newline, or ; not in a quote */
        switch( c ) {
        case '\'':
        case '"':
        case '`':
            if( quote == 0 ) {
                quote = c;
            } else if( c == quote ) {
                quote = 0;
            }
            break;
        case '<':
            if( quote == 0 ) {
                quote = '>';
            }
            break;
        case '>':
            if( c == quote ) {
                quote = 0;
            }
            break;
        case ';':
            if( quote != 0 ) {
                break;
            }
            skip = TRUE;
            break;
        case '\n':
            /* if continuation character found, pass over newline */
            if( (got_something == TRUE) && (*(ptr - 1) == '\\') ) {
                ptr--;
                max++;
                LineNumber++;
                continue; /* don't store character in string */
            }
            *ptr = '\0';
            // fall through
        case '\0':
            /* we have found the end of the line */
            return( TRUE );
        case EOF:
            *ptr = '\0';
            return( got_something );
        }
        if( !skip ) {
            *ptr++ = c;
            if( --max <= 1 )
                skip = TRUE;
            got_something = TRUE;
        }
    }
}

void PushLineQueue( void )
/************************/
{
    input_queue *new;

    DebugMsg(( "PUSHLINEQUEUE\n" ));

    new = AsmAlloc( sizeof( input_queue ) );
    new->next = line_queue;
    new->head = new->tail = NULL;
    line_queue = new;
}

bool PopLineQueue( void )
/***********************/
/* remove a line queue from the top of the stack & throw it away */
{
    input_queue *tmp;

    /* pop the line_queue stack */
    tmp = line_queue;
    in_prologue = FALSE;
    if( tmp == NULL )
        return( FALSE );
    line_queue = line_queue->next;
    AsmFree( tmp );
    return( TRUE );
}

bool GetQueueMacroHidden( void )
/******************************/
{
    if(( file_stack != NULL ) && !file_stack->is_a_file ) {
        return( file_stack->hidden );
    } else {
        return( FALSE );
    }
}

static line_list *enqueue( void )
/*******************************/
{
    line_list   *new;

    new = AsmAlloc( sizeof( line_list ) );
    new->next = NULL;

    if( line_queue == NULL ) {
        line_queue = AsmAlloc( sizeof( input_queue ) );
        line_queue->next = NULL;
        line_queue->tail = NULL;
        line_queue->head = NULL;
    }

    if( line_queue->tail == NULL ) {
        line_queue->head = new;
        line_queue->tail = new;
    } else {
        /* insert at the tail */
        line_queue->tail->next = new;
        line_queue->tail = new;
    }
    return( new );
}

static file_list *push_flist( const char *name, bool is_a_file )
/**************************************************************/
{
    file_list   *new;

    new = AsmAlloc( sizeof( file_list ) );
    new->next = file_stack;
    file_stack = new;
    new->line_num = LineNumber;
    new->is_a_file = is_a_file;
    new->hidden = 0;
    if( !is_a_file ) {
        dir_node *dir;

        dir = (dir_node *)AsmGetSymbol( name );
        LineNumber = dir->line_num;
        new->srcfile = dir->e.macroinfo->srcfile;
    } else {
        new->srcfile = AddFlist( name );
        LineNumber = 0;
    }
    return( new );
}

const FNAME *get_curr_srcfile( void )
/************************************/
{
    return( file_stack == NULL ? ModuleInfo.srcfile : file_stack->srcfile );
}

void print_include_file_nesting_structure( void )
/***********************************************/
{
    file_list       *tmp;
    unsigned        tab = 1;

    tmp = file_stack;
    if( tmp == NULL )
        return;

    for( ; tmp != NULL ; ) {
        if( tmp->next == NULL )
            break;
        if( !tmp->hidden ) {
            if( tmp->is_a_file ) {
                AsmNote( NOTE_INCLUDED_BY, tmp->next->srcfile->name, tmp->line_num );
            } else {
                AsmNote( NOTE_MACRO_CALLED_FROM, tmp->next->srcfile->name, tmp->line_num );
            }
        }
        tmp = tmp->next;
        tab++;
    }

    if( !tmp->hidden ) {
        if( tmp->is_a_file ) {
            AsmNote( NOTE_INCLUDED_BY, ModuleInfo.srcfile->name, tmp->line_num );
        } else {
            AsmNote( NOTE_MACRO_CALLED_FROM, ModuleInfo.srcfile->name, tmp->line_num );
        }
    }
}

void InputQueueLine( char *line )
/*******************************/
{
    line_list   *new;

    DebugMsg(( "QUEUELINE: %s  ( line %lu ) \n", line, LineNumber ));
    new = enqueue();
    new->line = AsmAlloc( strlen( line ) + 1 );
    strcpy( new->line, line );
}

static FILE *open_file_in_include_path( char *name, char *fullpath )
/******************************************************************/
{
    char            *inc_path_list;
    char            *next_path;
    char            buffer[MAX_LINE_LEN];
    FILE            *file = NULL;

    while( isspace( *name ) )
        name++;

    inc_path_list = AsmTmpAlloc( strlen( IncludePath ) + 1 );
    strcpy( inc_path_list, IncludePath );
    next_path = strtok( inc_path_list, INCLUDE_PATH_DELIM ";");

    while( ( file == NULL ) && ( next_path != NULL ) ) {
        strcpy( buffer, next_path );
//NYI: this is no good for DOS - have to check '/', '\\', and ':'
        if( buffer[ strlen( buffer ) - 1] != DIR_SEPARATOR ) {
            strcat( buffer, DIR_SEP_STRING );
        }
        strcat( buffer, name );

        file = fopen( buffer, "r" );
        if( file )
            break;
        next_path = strtok( NULL, INCLUDE_PATH_DELIM ";");
    }
    strcpy( fullpath, buffer );
    return( file );
}

int InputQueueFile( char *path )
/******************************/
{
    FILE        *file;
    file_list   *new;
    char        fullpath[ _MAX_PATH ];
    char        *drive, *dir, *fname, *ext;
    char        buffer[ _MAX_PATH2 ];
    char        *tmp;

    _splitpath2( path, buffer, &drive, &dir, &fname, &ext );
    _makepath( fullpath, drive, dir, fname, ext );
    file = fopen( fullpath, "r" );
    tmp = path;
    if( file == NULL && IncludePath != NULL ) {
        tmp = buffer;
        file = open_file_in_include_path( path, tmp );
    }

    if( file == NULL ) {

⌨️ 快捷键说明

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