-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpreproc.c
182 lines (159 loc) · 5.93 KB
/
preproc.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
/****************************************************************************
*
* 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 ) ) {
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 );
}