jwasm/preproc.c
Ilya V. Matveychikov 3b4ec5258f Fix notes produced by clang compiler
note: use '==' to turn this assignment into an equality comparison
2015-07-30 19:11:43 +03:00

183 lines
6.1 KiB
C

/****************************************************************************
*
* This code is Public Domain.
*
* ========================================================================
*
* Description: preprocessor
*
****************************************************************************/
#include <ctype.h>
#include <stdarg.h>
#include "globals.h"
#include "memalloc.h"
#include "parser.h"
#include "condasm.h"
#include "tokenize.h"
#include "equate.h"
#include "macro.h"
#include "input.h"
#include "fastpass.h"
#include "listing.h"
#define REMOVECOMENT 0 /* 1=remove comments from source */
extern ret_code (* const directive_tab[])( int, struct asm_tok[] );
#ifdef DEBUG_OUT
int_32 cntppl0; /* count preprocessed lines 1 */
int_32 cntppl1; /* count preprocessed lines 2 */
int_32 cntppl2; /* count lines NOT handled by preprocessor */
#endif
/* preprocessor directive or macro procedure is preceded
* by a code label.
*/
ret_code WriteCodeLabel( char *line, struct asm_tok tokenarray[] )
/****************************************************************/
{
int oldcnt;
int oldtoken;
char oldchar;
if ( tokenarray[0].token != T_ID ) {
return( EmitErr( SYNTAX_ERROR_EX, tokenarray[0].string_ptr ) );
}
/* ensure the listing is written with the FULL source line */
if ( CurrFile[LST] ) LstWrite( LSTTYPE_LABEL, 0, NULL );
/* v2.04: call ParseLine() to parse the "label" part of the line */
oldcnt = Token_Count;
oldtoken = tokenarray[2].token;
oldchar = *tokenarray[2].tokpos;
Token_Count = 2;
tokenarray[2].token = T_FINAL;
*tokenarray[2].tokpos = NULLC;
ParseLine( tokenarray );
if ( Options.preprocessor_stdout == TRUE )
WritePreprocessedLine( line );
Token_Count = oldcnt;
tokenarray[2].token = oldtoken;
*tokenarray[2].tokpos = oldchar;
return( NOT_ERROR );
}
/* PreprocessLine() is the "preprocessor".
* 1. the line is tokenized with Tokenize(), Token_Count set
* 2. (text) macros are expanded by ExpandLine()
* 3. "preprocessor" directives are executed
*/
int PreprocessLine( char *line, struct asm_tok tokenarray[] )
/***********************************************************/
{
int i;
/* v2.11: GetTextLine() removed - this is now done in ProcessFile() */
/* v2.08: moved here from GetTextLine() */
ModuleInfo.CurrComment = NULL;
/* v2.06: moved here from Tokenize() */
ModuleInfo.line_flags = 0;
/* Token_Count is the number of tokens scanned */
Token_Count = Tokenize( line, 0, tokenarray, TOK_DEFAULT );
#ifdef DEBUG_OUT
cntppl0++;
if ( ModuleInfo.GeneratedCode )
DebugMsg1(("PreprocessLine: >%s<\n", line ));
else
DebugMsg1(("PreprocessLine(%s): >%s< cmt=%s\n", GetTopSrcName(), line, ModuleInfo.CurrComment ? ModuleInfo.CurrComment : "" ));
#endif
#if REMOVECOMENT == 0
if ( Token_Count == 0 && ( CurrIfState == BLOCK_ACTIVE || ModuleInfo.listif ) )
LstWriteSrcLine();
#endif
if ( Token_Count == 0 )
return( 0 );
#ifdef DEBUG_OUT
/* option -np, skip preprocessor? */
if ( Options.skip_preprocessor )
return( Token_Count );
#endif
/* CurrIfState != BLOCK_ACTIVE && Token_Count == 1 | 3 may happen
* if a conditional assembly directive has been detected by Tokenize().
* However, it's important NOT to expand then */
if ( CurrIfState == BLOCK_ACTIVE ) {
if ( ( tokenarray[Token_Count].bytval & TF3_EXPANSION ? ExpandText( line, tokenarray, TRUE ) : ExpandLine( line, tokenarray ) ) < NOT_ERROR )
return( 0 );
}
DebugCmd( cntppl1++ );
i = 0;
if ( Token_Count > 2 && ( tokenarray[1].token == T_COLON || tokenarray[1].token == T_DBL_COLON ) )
i = 2;
/* handle "preprocessor" directives:
* IF, ELSE, ENDIF, ...
* FOR, REPEAT, WHILE, ...
* PURGE
* INCLUDE
* since v2.05, error directives are no longer handled here!
*/
if ( tokenarray[i].token == T_DIRECTIVE &&
tokenarray[i].dirtype <= DRT_INCLUDE ) {
/* if i != 0, then a code label is located before the directive */
if ( i > 1 ) {
if ( ERROR == WriteCodeLabel( line, tokenarray ) )
return( 0 );
}
directive_tab[tokenarray[i].dirtype]( i, tokenarray );
return( 0 );
}
/* handle preprocessor directives which need a label */
if ( tokenarray[0].token == T_ID && tokenarray[1].token == T_DIRECTIVE ) {
struct asym *sym;
switch ( tokenarray[1].dirtype ) {
case DRT_EQU:
/*
* EQU is a special case:
* If an EQU directive defines a text equate
* it MUST be handled HERE and 0 must be returned to the caller.
* This will prevent further processing, nothing will be stored
* if FASTPASS is on.
* Since one cannot decide whether EQU defines a text equate or
* a number before it has scanned its argument, we'll have to
* handle it in ANY case and if it defines a number, the line
* must be stored and, if -EP is set, written to stdout.
*/
if ( (sym = CreateConstant( tokenarray )) != NULL ) {
if ( sym->state != SYM_TMACRO ) {
#if FASTPASS
if ( StoreState ) FStoreLine( 0 );
#endif
if ( Options.preprocessor_stdout == TRUE )
WritePreprocessedLine( line );
}
/* v2.03: LstWrite() must be called AFTER StoreLine()! */
if ( ModuleInfo.list == TRUE ) {
LstWrite( sym->state == SYM_INTERNAL ? LSTTYPE_EQUATE : LSTTYPE_TMACRO, 0, sym );
}
}
return( 0 );
case DRT_MACRO:
case DRT_CATSTR: /* CATSTR + TEXTEQU directives */
case DRT_SUBSTR:
directive_tab[tokenarray[1].dirtype]( 1, tokenarray );
return( 0 );
}
}
DebugCmd( cntppl2++ );
return( Token_Count );
}