scanc.c

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

C
673
字号
/****************************************************************************
*
*                            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 <stdio.h>
#include <ctype.h>
#include <string.h>
#include "ctags.h"

static int      acceptOnlyEndif;
static int      structStack[MAX_STRUCT_DEPTH];
static int      structStackDepth;

/*
 * eatWhiteSpace - eat white space in the file
 */
static int eatWhiteSpace( void )
{
    int ch;

    while( 1 ) {
        ch = GetChar();
        if( ch == EOF ) {
            break;
        }
        if( !isspace( ch ) ) {
            break;
        }
        if( ch == '\n' ) {
            NewFileLine();
        }
    }
    return( ch );

} /* eatWhiteSpace */

/*
 * eatCommment - skip over a comment
 */
static void eatComment( void )
{
    int         ch;
    int         nesting_level;
    bool        done=FALSE;

    nesting_level = 1;
    while( !done ) {
        ch = GetChar();
        switch( ch ) {
        case EOF:
            done = TRUE;
            break;
        case '*':
            ch = GetChar();
            if( ch == '/' ) {
                nesting_level--;
                if( nesting_level == 0 ) {
                    return;
                }
            } else {
                UnGetChar( ch );
            }
            break;
        case '/':
            ch = GetChar();
            if( ch == '*' ) {
                nesting_level++;
            } else {
                UnGetChar( ch );
            }
            break;
        case '\n':
            NewFileLine();
            break;
        }
    }

} /* eatComment */

/*
 * eatUntilChar - skip through file until a matching char is found
 *                this allows for lines ending in '\' (continuation)
 */
static void eatUntilChar( int match )
{
    char        escape;
    int         ch;

    escape = FALSE;

    while( 1 ) {
        ch = GetChar();
        if( ch == EOF ) {
            break;
        }
        if( escape ) {
            escape = FALSE;
            continue;
        }
        if( ch == '\n' ) {
            NewFileLine();
            if( match == '\n' ) {
                return;
            }
        } else if( ch == '\\' ) {
            escape = TRUE;
        } else if( ch == match ) {
            return;
        }
    }
} /* eatUntilChar */

/*
 * doPreProcessorDirective - handle a pre-processor directive
 */
static void doPreProcessorDirective( void )
{
    char        *buffptr;
    char        buff[MAX_STR];
    int         ch;

    /*
     * eat leading whitespace
     */
    while( 1 ) {
        ch = GetChar();
        if( ch == EOF ) {
            return;
        }
        if( !isspace( ch ) ) {
            UnGetChar( ch );
            break;
        }
    }

    /*
     * get token
     */
    buffptr = buff;
    while( 1 ) {
        ch = GetChar();
        if( ch == EOF ) {
            return;
        }
        if( isspace( ch ) ) {
            break;
        }
        *buffptr++ = ch;
    }
    *buffptr = 0;

    /*
     * swallow #else and #elif shit
     */
    if( !acceptOnlyEndif ) {
        if( !stricmp( buff,"else" ) || !stricmp( buff, "elif" ) ) {
            acceptOnlyEndif = 1;
        }
    } else {
        if( !stricmp( buff,"endif" ) ) {
            acceptOnlyEndif--;
        } else if( !strnicmp( buff, "if", 2 ) ) {
            acceptOnlyEndif++;
        }
    }

    /*
     * if it is a #define, and we want macros, then get macro
     */
    if( !stricmp( buff,"define" ) && (WantMacros || WantAllDefines) &&
                !acceptOnlyEndif ) {
        ch = eatWhiteSpace();
        buffptr = buff;
        while( 1 ) {
            *buffptr++ = ch;
            ch = GetChar();
            if( ch == EOF ) {
                return;
            }
            if( !IsTokenChar( ch ) ) {
                *buffptr = 0;
                break;
            }
        }
        if( WantAllDefines || ch == '(' ) {
            RecordCurrentLineData();
            AddTag( buff );
        }
    }

    /*
     * if the last thing we were on was a '\n', then go to
     * the next line.  if the previous line ended in a '\',
     * then eat following line(s)
     */
    if( ch == '\n' ) {
        NewFileLine();
        if( buffptr > buff ) {
            if( *(buffptr-1) != '\\' ) {
                return;
            }
        }
    }
    eatUntilChar( '\n' );

} /* doPreProcessorDirective */

/*
 * eatUntilClosingBracket - eat all chars until final ')' is found
 */
static void eatUntilClosingBracket( void )
{
    char        escape;
    int         ch;
    int         brace_level=1;

    escape = FALSE;

    while( 1 ) {
        ch = GetChar();
        if( ch == EOF ) {
            break;
        }
        if( escape ) {
            escape = FALSE;
            continue;
        }
        switch( ch ) {
        case '\n':
            NewFileLine();
            break;
        case '\\':
            escape = TRUE;
            break;
        case '(':
            brace_level++;
            break;
        case ')':
            brace_level--;
            if( brace_level == 0 ) {
                return;
            }
            break;
        }
    }

} /* eatUntilClosingBracket */

/*
 * eatStuffBeforeOpenBrace - eat allowable stuff before an opening brace
 *                           (#stuff, comments, '\')
 */
bool eatStuffBeforeOpenBrace( int ch )
{
    if( ch == '#' ) {
        doPreProcessorDirective();
        return( TRUE );
    }
    if( ch == '\\' ) {
        eatUntilChar( '\n' );
        return( TRUE );
    }
    if( ch == '/' ) {
        ch = GetChar();
        if( ch == '*' ) {
            eatComment();
            return( TRUE );
        } else if( ch == '/' ) {
            eatUntilChar( '\n' );
            return( TRUE );
        } else {
            UnGetChar( ch );
        }
    }
    return( FALSE );

} /* eatStuffBeforeOpenBrace */

typedef enum {
    TAG_FUNC,
    TAG_PROTO,
    TAG_NOTHING
} tag_type;

/*
 * doFunction - handle a function declaration or prototype
 */
static tag_type doFunction( int *brace_level )
{
    char        ch;

    eatUntilClosingBracket();
    while( 1 ) {
        ch = eatWhiteSpace();
        if( IsTokenChar( ch ) || ch == '{' ) break;
        if( WantProtos && ch == ';' ) return( TAG_PROTO );
        if( eatStuffBeforeOpenBrace( ch ) ) continue;
        return( TAG_NOTHING );
    }
    if( ch != '{' ) {
        eatUntilChar( '{' );
    }
    *brace_level += 1;
    return( TAG_FUNC );

} /* doFunction */

/*
 * doCUSE - handle structures, enums, unions and classes

⌨️ 快捷键说明

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