mparse.c

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

C
1,157
字号
                    !doubleQuote ) {
            break;
        } else if( doubleQuote && intext[*offset] == BACKSLASH ) {
            if( intext[*offset + 1] == DOUBLEQUOTE ) {
                *offset = *offset + 1;
            }
        } else if( doubleQuote && intext[*offset] == DOUBLEQUOTE ) {
            ++(*offset);
            break;
        }
        ++(*offset);
    }

    if( (intext[(*offset) - 1] != DOUBLEQUOTE && doubleQuote) ||
        (*offset == 1                         && doubleQuote) ) {
        /* error */
        PrtMsg( ERR | LOC | NON_MATCHING_QUOTE );
        ret = NULL;
        return( ret );
    }

    if( !doubleQuote && *offset > 0 ||
         doubleQuote && *offset > 1 ) {
        tempStr = StartVec();
        if( doubleQuote ) {
            WriteNVec( tempStr, intext + 1, *offset - 2 );
        } else {
            WriteNVec( tempStr, intext, *offset );
        }
        ret = FinishVec( tempStr );
        return( ret );
    } else {
        // if we need a temporary file then give back << as a filename
        tempStr = StartVec();
        WriteVec( tempStr, INLINE_SYMBOL );
        ret = FinishVec( tempStr );
        return( ret );
    }
}


STATIC void getBody( FLIST *head )
/*********************************
 * get the body of the file from the input stream
 */
{
    FLIST       *current;
    TOKEN_T     t;
    VECSTR      buf;
    VECSTR      bufTemp;
    char        *temp;
    char const  *currChar;

    current = head;
    if( current == NULL ) {
        return;
    }

    /* Inlinelevel == the number of inline files we need to create */
    while( inlineLevel > 0 && current != NULL ) {
        buf = StartVec();
        WriteVec( buf, "" );
        for( ;; ) {
            t = PreGetCH();
            if( t == STRM_END ) {
                UnGetCH( t );
                PrtMsg( ERR | LOC | UNEXPECTED_EOF );
                return;
            }
            UnGetCH( t );
            temp = ignoreWSDeMacro( TRUE, ForceDeMacro() );
            if( temp[0] == LESSTHAN ) {
                if( temp[1] == LESSTHAN ) {
                    /* terminator of inline file is found when first
                     * two characters are <<
                     */
                     currChar = temp + 2;
                     while( *currChar != NULLCHAR && isws( *currChar ) ) {
                         ++currChar;
                     }
                     if( *currChar == NULLCHAR ) {
                         current->keep = FALSE;
                     } else if( strnicmp( currChar, NOKEEP, 6 ) == 0 ) {
                         current->keep = FALSE;
                     } else if( strnicmp( currChar, KEEP, 4 ) == 0 ) {
                         current->keep = TRUE;
                     } else {
                         /* error only expecting (NO)KEEP */
                         PrtMsg( ERR | LOC | NOKEEP_ONLY );
                     }

                     FreeSafe( temp );
                     break;
                }
            }
            bufTemp = StartVec();
            WriteVec( bufTemp, temp );
            FreeSafe( temp );
            CatVec( buf, bufTemp );
            bufTemp = StartVec();
            WriteVec( bufTemp, "\n" );
            CatVec( buf, bufTemp );
        }
        current->body = FinishVec( buf );
        current       = current->next;
        --inlineLevel;
    }
    if( inlineLevel > 0 ) {
        PrtMsg( ERR | LOC | UNEXPECTED_EOF );
    }
}


STATIC FLIST *GetInlineFile( char **commandIn )
/**********************************************
 * this returns the head of the flist and modifies the command text to
 * change << to the actual file name to be used
 * also returns an offset so that the calling program would know
 * how long the command is in cmdText
 * cmdText is also modified it removes the file name information and
 * substitutes it with the actual file name that is going to be used
 */
{
    size_t  offset;
    size_t  index;
    FLIST   *head;
    FLIST   *current;
    char    *cmdText;
    size_t  start;       // start of cmdText to copy into newCommand
    VECSTR  newCommand;  // stores the new command built by replacing << with
                         // the actual file name

    /* inlinelevel must be initially zero when processing */
    assert( inlineLevel == 0 && commandIn != NULL );

    cmdText = *commandIn;
    head    = NULL;
    current = NULL;

    newCommand = StartVec();

    index = 0;
    start = 0;
    /*
     * check for << in the cmdText if found then substitute this
     * with a new name the syntax is <<[filename] it is delimited with
     * a space/tab or <
     * note: the << cannot be part of any macro or else it would not
     * be recognized
     * this part will remove the << from the command text if the inline file
     * is explicitly defined
     */
    while( cmdText[index] != NULLCHAR ) {
        if( cmdText[index] == LESSTHAN ) {
            if( cmdText[index + 1] == LESSTHAN ) {
                // Add the current vector into the new command
                WriteNVec( newCommand, cmdText + start, index - start );

                ++inlineLevel;
                if( head == NULL ) {
                    current = NewFList();
                    head    = current;
                } else {
                    assert( current != NULL );
                    current->next = NewFList();
                    current       = current->next;
                }

                // Add file Name into new command text
                current->fileName = getFileName( cmdText + 2 + index, &offset );

                // Check for long file name
                if( *(cmdText + 2 + index) == DOUBLEQUOTE ) {
                    WriteVec( newCommand, "\"" );
                    WriteVec( newCommand, current->fileName );
                    WriteVec( newCommand, "\"" );
                } else {
                    WriteVec( newCommand, current->fileName );
                }

                current->body = NULL;
                current->next = NULL;
                index = index + offset;
                start = index + 2;
            }
            ++index;
        }
        ++index;
    }
    WriteNVec( newCommand, cmdText + start, index - start );
    FreeSafe( cmdText );
    *commandIn = FinishVec( newCommand );
    getBody( head );
    return( head );
}

STATIC char *formatPathName( const char *inPath )
/***********************************************/
{
    char    buf[_MAX_PATH];

    if( inPath != NULL ) {
        _makepath( buf, NULL, inPath, NULL, NULL );
        return( StrDupSafe( buf ) );
    } else {
        return( NULL );
    }
}


STATIC void getCurTargDepPath( char **cur_targ_path, char **cur_dep_path )
/*************************************************************************
 * this is to get the current target path and dependent path
 * when sufsuf is created
 */
{
    if( *cur_targ_path != NULL ) {
        FreeSafe( *cur_targ_path );
    }
    if( *cur_dep_path != NULL ) {
        FreeSafe( *cur_dep_path );
    }
    if( targ_path != NULL ) {
        *cur_targ_path = formatPathName( targ_path );
    } else {
        *cur_targ_path = StrDupSafe( "" );
    }
    if( dep_path != NULL ) {
        *cur_dep_path  = formatPathName( dep_path );
    } else {
        *cur_dep_path = StrDupSafe( "" );
    }

    FreeSafe( targ_path );
    FreeSafe( dep_path );
    targ_path = NULL;
    dep_path  = NULL;
}


TLIST *Parse( void )
/*******************
 * Call LexToken, and dispatch to appropriate routine
 */
{
    TOKEN_T t;
    CLIST   *newclist;
    CLIST   *bclist;
    TLIST   *btlist;
    BOOLEAN clist_warning_given;
    BOOLEAN token_filename;
    char    *cur_depend_path;
    char    *cur_target_path;

    firstTarget = NULL;

    bclist = NULL;
    btlist = NULL;

    cur_depend_path = NULL;
    cur_target_path = NULL;

    clist_warning_given = FALSE;
    token_filename      = FALSE;

    for( ;; ) {
        /*
         * If the current target is a sufsuf then
         * we must demacro the text later
         * when the actual filenames are resolved
         */
        if( btlist != NULL ) {
            ImplicitDeMacro = (Glob.microsoft | Glob.unix) && btlist->target->sufsuf;
        }
        t = LexToken( LEX_PARSER );
        ImplicitDeMacro = FALSE;

        if( t != TOK_CMD && t != EOL ) {
            if( btlist != NULL ) {
                    /* link the commands to the targets */
                linkCList( btlist, bclist, cur_target_path, cur_depend_path );
                bclist = NULL;
                btlist = NULL;
                if( cur_depend_path != NULL ) {
                    FreeSafe( cur_depend_path );
                }
                if( cur_target_path != NULL ) {
                    FreeSafe(cur_target_path);
                }
                cur_target_path = NULL;
                cur_depend_path = NULL;
                if( (Glob.microsoft | Glob.unix) && token_filename == TRUE ) {
                    exPop();
                    token_filename = FALSE;
                }
            }
            clist_warning_given = FALSE;
        }

        if( t == STRM_END ) {
            break;
        }

        switch( t ) {
        case EOL:
            break;
        case TOK_CMD:
            if( *CurAttr.ptr == NULLCHAR ) {
                    /* discard blank lines */
                FreeSafe( CurAttr.ptr );
            } else {
                if( btlist == NULL ) {
                    if( !clist_warning_given ) {
                        PrtMsg( WRN | LOC | CLIST_HAS_NO_OWNER );
                        clist_warning_given = TRUE;
                    }
                    FreeSafe( CurAttr.ptr );
                } else {
                    newclist = NewCList();
                    newclist->text       = CurAttr.ptr;
                    /* stack in reverse order */
                    newclist->next       = bclist;
                    /* look at the command text to see if we need
                     * to get inline file if we do then create inline
                     * file information in memory
                     * note: that if the clist pertains to a implicit
                     *       rule we must deMacro the text the same
                     *       way as wmake does for microsoft option
                     */
                    ImplicitDeMacro = (Glob.microsoft | Glob.unix) &&
                        btlist->target->sufsuf;
                    newclist->inlineHead = GetInlineFile( &(newclist->text) );
                    ImplicitDeMacro = FALSE;
                    bclist = newclist;
                }
            }
            break;
        case TOK_SUF:
            parseSuf();
            break;
        case TOK_SUFSUF:
            parseTargDep( t, &btlist );
            getCurTargDepPath( &cur_target_path, &cur_depend_path );
            if( btlist != NULL ) {
                btlist->target->sufsuf = TRUE;
            }
            break;
        case TOK_FILENAME:
            parseTargDep( t, &btlist );
            if( (Glob.microsoft | Glob.unix) && btlist != NULL ) {
                if( btlist->target != NULL && btlist->target->depend != NULL ) {
                    exPush( btlist->target, btlist->target->depend, NULL );
                    token_filename = TRUE;
                }
            }
            break;
        case TOK_DOTNAME:
            parseDotName( t, &btlist );
            break;
        default:
#ifdef DEVELOPMENT
            PrtMsg( FTL | INVALID_TOKEN_IN, "Parse" );
#else
            PrtMsg( WRN | LOC | IGNORE_OUT_OF_PLACE_M, M_UNKNOWN_TOKEN );
#endif
        }
    }

    return( firstTarget );
}


void ParseInit( void )
/********************/
{
    inlineLevel   = 0;
    DoingUpdate = FALSE;
}


void ParseFini( void )
/********************/
{
}

⌨️ 快捷键说明

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