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 + -
显示快捷键?