ifdef/ifndef/else/endif
This commit is contained in:
parent
b963bc91e6
commit
34dfc3238d
3 changed files with 143 additions and 1 deletions
|
@ -142,6 +142,9 @@
|
||||||
:str_else
|
:str_else
|
||||||
string else
|
string else
|
||||||
byte 0
|
byte 0
|
||||||
|
:str_endif
|
||||||
|
string endif
|
||||||
|
byte 0
|
||||||
:str___FILE__
|
:str___FILE__
|
||||||
string __FILE__
|
string __FILE__
|
||||||
byte 0
|
byte 0
|
||||||
|
|
|
@ -9,6 +9,13 @@ F(2
|
||||||
|
|
||||||
#include INC_FILE /* include macro test */
|
#include INC_FILE /* include macro test */
|
||||||
|
|
||||||
|
a
|
||||||
|
#ifndef INC_FILEd
|
||||||
|
|
||||||
xglue(LINE_,NUMBER)
|
xglue(LINE_,NUMBER)
|
||||||
|
#else
|
||||||
|
Hello
|
||||||
|
#endif
|
||||||
|
b
|
||||||
|
|
||||||
#pragma
|
#pragma
|
||||||
|
|
134
05/preprocess.b
134
05/preprocess.b
|
@ -531,6 +531,14 @@ function translation_phase_4
|
||||||
if b != 0 goto pp_directive_line
|
if b != 0 goto pp_directive_line
|
||||||
b = str_equals(in, .str_include)
|
b = str_equals(in, .str_include)
|
||||||
if b != 0 goto pp_directive_include
|
if b != 0 goto pp_directive_include
|
||||||
|
b = str_equals(in, .str_ifdef)
|
||||||
|
if b != 0 goto pp_directive_ifdef
|
||||||
|
b = str_equals(in, .str_ifndef)
|
||||||
|
if b != 0 goto pp_directive_ifndef
|
||||||
|
b = str_equals(in, .str_else)
|
||||||
|
if b != 0 goto pp_directive_else
|
||||||
|
b = str_equals(in, .str_endif)
|
||||||
|
if b != 0 goto pp_directive_endif
|
||||||
goto unrecognized_directive
|
goto unrecognized_directive
|
||||||
:pp_directive_error
|
:pp_directive_error
|
||||||
fputs(2, filename)
|
fputs(2, filename)
|
||||||
|
@ -784,7 +792,43 @@ function translation_phase_4
|
||||||
out += 1
|
out += 1
|
||||||
|
|
||||||
goto process_pptoken
|
goto process_pptoken
|
||||||
|
:pp_directive_ifdef
|
||||||
|
pptoken_skip(&in)
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
|
macro_name = in
|
||||||
|
pptoken_skip(&in)
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
|
if *1in != 10 goto bad_ifdef
|
||||||
|
p = look_up_object_macro(macro_name)
|
||||||
|
if p != 0 goto process_pptoken ; macro is defined; keep processing
|
||||||
|
p = look_up_function_macro(macro_name)
|
||||||
|
if p != 0 goto process_pptoken ; macro is defined; keep processing
|
||||||
|
preprocessor_skip_if(filename, &line_number, &in, &out)
|
||||||
|
goto process_pptoken
|
||||||
|
:pp_directive_ifndef
|
||||||
|
pptoken_skip(&in)
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
|
macro_name = in
|
||||||
|
pptoken_skip(&in)
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
|
if *1in != 10 goto bad_ifdef
|
||||||
|
p = look_up_object_macro(macro_name)
|
||||||
|
if p != 0 goto ifndef_skip ; macro is defined; skip
|
||||||
|
p = look_up_function_macro(macro_name)
|
||||||
|
if p != 0 goto ifndef_skip ; macro is defined; skip
|
||||||
|
goto process_pptoken ; macro not defined; keep processing
|
||||||
|
:ifndef_skip
|
||||||
|
preprocessor_skip_if(filename, &line_number, &in, &out)
|
||||||
|
goto process_pptoken
|
||||||
|
:pp_directive_else
|
||||||
|
; assume we got here from an if, so skip this
|
||||||
|
pptoken_skip(&in)
|
||||||
|
preprocessor_skip_if(filename, &line_number, &in, &out)
|
||||||
|
goto process_pptoken
|
||||||
|
:pp_directive_endif
|
||||||
|
; assume we got here from an if/elif/else, just ignore it.
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto process_pptoken
|
||||||
:unrecognized_directive
|
:unrecognized_directive
|
||||||
compile_error(filename, line_number, .str_unrecognized_directive)
|
compile_error(filename, line_number, .str_unrecognized_directive)
|
||||||
:str_unrecognized_directive
|
:str_unrecognized_directive
|
||||||
|
@ -810,6 +854,11 @@ function translation_phase_4
|
||||||
:str_bad_undef
|
:str_bad_undef
|
||||||
string Bad #undef.
|
string Bad #undef.
|
||||||
byte 0
|
byte 0
|
||||||
|
:bad_ifdef
|
||||||
|
compile_error(filename, line_number, .str_bad_ifdef)
|
||||||
|
:str_bad_ifdef
|
||||||
|
string Bad #ifdef.
|
||||||
|
byte 0
|
||||||
:bad_line_directive
|
:bad_line_directive
|
||||||
compile_error(filename, line_number, .str_bad_line_directive)
|
compile_error(filename, line_number, .str_bad_line_directive)
|
||||||
:str_bad_line_directive
|
:str_bad_line_directive
|
||||||
|
@ -825,6 +874,89 @@ function translation_phase_4
|
||||||
:phase4_end
|
:phase4_end
|
||||||
return out
|
return out
|
||||||
|
|
||||||
|
|
||||||
|
; skip body of #if / #elif / #else. This will advance *p_in to:
|
||||||
|
; - the next unmatched #elif
|
||||||
|
; OR - right after the next #else
|
||||||
|
; OR - right after the next #endif
|
||||||
|
; whichever comes first
|
||||||
|
; @NONSTANDARD: this doesn't properly handle #endif's, etc. which appear in a different file from their corresponding #if's.
|
||||||
|
; NOTE: p_out is needed for newlines
|
||||||
|
function preprocessor_skip_if
|
||||||
|
argument filename
|
||||||
|
argument p_line_number
|
||||||
|
argument p_in
|
||||||
|
argument p_out
|
||||||
|
local in
|
||||||
|
local out
|
||||||
|
local p
|
||||||
|
local b
|
||||||
|
local line_number_start
|
||||||
|
local prev_if_depth
|
||||||
|
local if_depth
|
||||||
|
in = *8p_in
|
||||||
|
out = *8p_out
|
||||||
|
if_depth = 0
|
||||||
|
line_number_start = *8p_line_number
|
||||||
|
:preprocessor_skip_if_loop
|
||||||
|
prev_if_depth = if_depth
|
||||||
|
if *1in == 0 goto no_matching_endif
|
||||||
|
if *1in == 10 goto skip_if_newline
|
||||||
|
if *1in == '# goto skip_if_hash
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto preprocessor_skip_if_loop
|
||||||
|
:skip_if_newline
|
||||||
|
*8p_line_number += 1
|
||||||
|
pptoken_copy_and_advance(&in, &out)
|
||||||
|
goto preprocessor_skip_if_loop
|
||||||
|
:skip_if_hash
|
||||||
|
p = in + 1
|
||||||
|
if *1p != '# goto skip_if_directive
|
||||||
|
; it's ##, not #
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto preprocessor_skip_if_loop
|
||||||
|
:skip_if_directive
|
||||||
|
pptoken_skip(&in) ; skip #
|
||||||
|
b = str_equals(in, .str_else)
|
||||||
|
if b != 0 goto skip_if_else
|
||||||
|
b = str_equals(in, .str_endif)
|
||||||
|
if b != 0 goto skip_if_endif
|
||||||
|
b = str_equals(in, .str_elif)
|
||||||
|
if b != 0 goto skip_if_elif
|
||||||
|
b = str_equals(in, .str_if)
|
||||||
|
if b != 0 goto skip_if_inc_depth
|
||||||
|
b = str_equals(in, .str_ifdef)
|
||||||
|
if b != 0 goto skip_if_inc_depth
|
||||||
|
b = str_equals(in, .str_ifndef)
|
||||||
|
if b != 0 goto skip_if_inc_depth
|
||||||
|
goto preprocessor_skip_if_loop ; some unimportant directive
|
||||||
|
:skip_if_elif
|
||||||
|
if if_depth > 0 goto preprocessor_skip_if_loop
|
||||||
|
in -= 2 ; return to #
|
||||||
|
goto preprocessor_skip_if_loop_end
|
||||||
|
:skip_if_inc_depth
|
||||||
|
if_depth += 1
|
||||||
|
goto preprocessor_skip_if_loop
|
||||||
|
:skip_if_endif
|
||||||
|
if_depth -= 1
|
||||||
|
; (fallthrough)
|
||||||
|
:skip_if_else
|
||||||
|
pptoken_skip(&in) ; skip endif/else
|
||||||
|
if prev_if_depth > 0 goto preprocessor_skip_if_loop
|
||||||
|
goto preprocessor_skip_if_loop_end
|
||||||
|
:preprocessor_skip_if_loop_end
|
||||||
|
|
||||||
|
*8p_in = in
|
||||||
|
*8p_out = out
|
||||||
|
return
|
||||||
|
|
||||||
|
:no_matching_endif
|
||||||
|
compile_error(filename, line_number_start, .str_no_matching_endif)
|
||||||
|
:str_no_matching_endif
|
||||||
|
string #if/#elif/#else without matching #endif.
|
||||||
|
byte 0
|
||||||
|
|
||||||
|
|
||||||
; returns a pointer to the replacement pptokens, or 0 if this macro is not defined
|
; returns a pointer to the replacement pptokens, or 0 if this macro is not defined
|
||||||
function look_up_macro
|
function look_up_macro
|
||||||
argument macros
|
argument macros
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue