reading function-like macros
This commit is contained in:
parent
3d0adb5f6f
commit
4d5a5d9d97
4 changed files with 162 additions and 16 deletions
|
@ -61,6 +61,7 @@ function main
|
||||||
pptokens = translation_phase_4(input_filename, pptokens)
|
pptokens = translation_phase_4(input_filename, pptokens)
|
||||||
;print_pptokens(pptokens)
|
;print_pptokens(pptokens)
|
||||||
print_object_macros()
|
print_object_macros()
|
||||||
|
print_function_macros()
|
||||||
exit(0)
|
exit(0)
|
||||||
|
|
||||||
:usage_error
|
:usage_error
|
||||||
|
|
|
@ -6,7 +6,11 @@ comment it is
|
||||||
here
|
here
|
||||||
*/
|
*/
|
||||||
#
|
#
|
||||||
#define A 33
|
#define A(_Hello, there, everyone ) 33 + _Hello - everyone * there
|
||||||
|
#define B(x, y, z) 58
|
||||||
|
#define C(hello) hello * hello + hello / hello
|
||||||
|
#define A 22
|
||||||
|
#define C 33
|
||||||
#define _Hello_there5 -76 + sqrt(A)
|
#define _Hello_there5 -76 + sqrt(A)
|
||||||
int main(void) {
|
int main(void) {
|
||||||
printf("\"Hello, world!%c\n\"", '\'');
|
printf("\"Hello, world!%c\n\"", '\'');
|
||||||
|
@ -15,3 +19,4 @@ int main(void) {
|
||||||
5 + (.3e+5+6) & 0xff | 93 -~5;
|
5 + (.3e+5+6) & 0xff | 93 -~5;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
#define _Hello_there 18
|
||||||
|
|
165
05/preprocess.b
165
05/preprocess.b
|
@ -23,6 +23,8 @@ function split_into_preprocessing_tokens
|
||||||
p += n
|
p += n
|
||||||
goto pptokens_read_loop
|
goto pptokens_read_loop
|
||||||
:pptokens_read_loop_end
|
:pptokens_read_loop_end
|
||||||
|
p -= 1
|
||||||
|
if *1p != 10 goto no_newline_at_end_of_file
|
||||||
|
|
||||||
; okay we read the file. first, delete every backslash-newline sequence (phase 2)
|
; okay we read the file. first, delete every backslash-newline sequence (phase 2)
|
||||||
local newlines ; we add more newlines to keep line numbers right
|
local newlines ; we add more newlines to keep line numbers right
|
||||||
|
@ -331,7 +333,11 @@ function split_into_preprocessing_tokens
|
||||||
:str_bad_pptoken
|
:str_bad_pptoken
|
||||||
string Bad preprocessing token.
|
string Bad preprocessing token.
|
||||||
byte 0
|
byte 0
|
||||||
|
:no_newline_at_end_of_file
|
||||||
|
compile_error(filename, 0, .str_no_newline_at_end_of_file)
|
||||||
|
:str_no_newline_at_end_of_file
|
||||||
|
string No newline at end of file.
|
||||||
|
byte 0
|
||||||
; can the given character appear in a C89 ppnumber?
|
; can the given character appear in a C89 ppnumber?
|
||||||
function is_ppnumber_char
|
function is_ppnumber_char
|
||||||
argument c
|
argument c
|
||||||
|
@ -433,7 +439,8 @@ function translation_phase_4
|
||||||
pptoken_copy_and_advance(&in, &out)
|
pptoken_copy_and_advance(&in, &out)
|
||||||
goto phase4_line
|
goto phase4_line
|
||||||
:pp_directive
|
:pp_directive
|
||||||
pptoken_skip(&in)
|
pptoken_skip(&in) ; skip #
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
c = *1in
|
c = *1in
|
||||||
if c == 10 goto phase4_next_line ; "null directive" C89 § 3.8.7
|
if c == 10 goto phase4_next_line ; "null directive" C89 § 3.8.7
|
||||||
b = str_equals(in, .str_error)
|
b = str_equals(in, .str_error)
|
||||||
|
@ -453,9 +460,14 @@ function translation_phase_4
|
||||||
pptoken_skip_spaces(&in)
|
pptoken_skip_spaces(&in)
|
||||||
macro_name = in
|
macro_name = in
|
||||||
pptoken_skip(&in)
|
pptoken_skip(&in)
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
c = *1in
|
c = *1in
|
||||||
if c == '( goto function_macro_definition
|
if c == '( goto function_macro_definition
|
||||||
; it's an object-like macro, e.g. #define X 47
|
; it's an object-like macro, e.g. #define X 47
|
||||||
|
|
||||||
|
b = look_up_object_macro(macro_name)
|
||||||
|
if b != 0 goto macro_redefinition
|
||||||
|
|
||||||
p = object_macros + object_macros_size
|
p = object_macros + object_macros_size
|
||||||
; copy name
|
; copy name
|
||||||
p = strcpy(p, macro_name)
|
p = strcpy(p, macro_name)
|
||||||
|
@ -469,7 +481,73 @@ function translation_phase_4
|
||||||
goto phase4_line
|
goto phase4_line
|
||||||
:function_macro_definition
|
:function_macro_definition
|
||||||
; a function-like macro, e.g. #define JOIN(a,b) a##b
|
; a function-like macro, e.g. #define JOIN(a,b) a##b
|
||||||
byte 0xcc
|
local param_names
|
||||||
|
local param_name
|
||||||
|
local param_idx
|
||||||
|
|
||||||
|
b = look_up_function_macro(macro_name)
|
||||||
|
if b != 0 goto macro_redefinition
|
||||||
|
|
||||||
|
param_names = malloc(4000)
|
||||||
|
pptoken_skip(&in) ; skip opening parenthesis
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
|
param_name = param_names
|
||||||
|
:macro_params_loop
|
||||||
|
c = *1in
|
||||||
|
if c == 10 goto missing_closing_bracket
|
||||||
|
b = isalpha_or_underscore(c)
|
||||||
|
if b == 0 goto bad_macro_params
|
||||||
|
param_name = strcpy(param_name, in)
|
||||||
|
param_name += 1
|
||||||
|
pptoken_skip(&in)
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
|
c = *1in
|
||||||
|
if c == ') goto macro_params_loop_end
|
||||||
|
if c != ', goto bad_macro_params
|
||||||
|
pptoken_skip(&in) ; skip ,
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
|
goto macro_params_loop
|
||||||
|
:macro_params_loop_end
|
||||||
|
|
||||||
|
pptoken_skip(&in) ; skip )
|
||||||
|
pptoken_skip_spaces(&in)
|
||||||
|
|
||||||
|
p = function_macros + function_macros_size
|
||||||
|
p = strcpy(p, macro_name)
|
||||||
|
p += 1
|
||||||
|
|
||||||
|
:fmacro_body_loop
|
||||||
|
if *1in == 10 goto fmacro_body_loop_end
|
||||||
|
param_name = param_names
|
||||||
|
param_idx = 1
|
||||||
|
; check if this token matches any of the parameter names
|
||||||
|
:fmacro_param_check_loop
|
||||||
|
if *1param_name == 0 goto fmacro_param_check_loop_end
|
||||||
|
b = str_equals(in, param_name)
|
||||||
|
if b != 0 goto fmacro_param_match
|
||||||
|
param_name = memchr(param_name, 0)
|
||||||
|
param_name += 1
|
||||||
|
param_idx += 1
|
||||||
|
goto fmacro_param_check_loop
|
||||||
|
:fmacro_param_check_loop_end
|
||||||
|
; it's not a parameter; just copy it out
|
||||||
|
p = strcpy(p, in)
|
||||||
|
p += 1
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto fmacro_body_loop
|
||||||
|
:fmacro_param_match
|
||||||
|
; a match!
|
||||||
|
*1p = param_idx ; store the parameter index (1 = first argument) as a pptoken
|
||||||
|
p += 2
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto fmacro_body_loop
|
||||||
|
:fmacro_body_loop_end
|
||||||
|
*1p = 255
|
||||||
|
p += 1
|
||||||
|
function_macros_size = p - function_macros
|
||||||
|
free(param_names)
|
||||||
|
in += 2 ; skip newline and following null character
|
||||||
|
goto phase4_line
|
||||||
:str_directive_error
|
:str_directive_error
|
||||||
string : #error
|
string : #error
|
||||||
byte 10
|
byte 10
|
||||||
|
@ -481,35 +559,92 @@ function translation_phase_4
|
||||||
:str_unrecognized_directive
|
:str_unrecognized_directive
|
||||||
string Unrecognized preprocessor directive.
|
string Unrecognized preprocessor directive.
|
||||||
byte 0
|
byte 0
|
||||||
|
:macro_redefinition
|
||||||
|
; technically not an error if it was redefined to the same thing, but it's
|
||||||
|
; annoying to check for that
|
||||||
|
compile_error(filename, line_number, .str_macro_redefinition)
|
||||||
|
:str_macro_redefinition
|
||||||
|
string Macro redefinition.
|
||||||
|
byte 0
|
||||||
|
:missing_closing_bracket
|
||||||
|
compile_error(filename, line_number, .str_missing_closing_bracket)
|
||||||
|
:str_missing_closing_bracket
|
||||||
|
string Missing closing ).
|
||||||
|
byte 0
|
||||||
|
:bad_macro_params
|
||||||
|
compile_error(filename, line_number, .str_bad_macro_params)
|
||||||
|
:str_bad_macro_params
|
||||||
|
string Bad macro parameter list.
|
||||||
|
byte 0
|
||||||
|
|
||||||
|
; returns a pointer to the replacement pptokens, or 0 if this macro is not defined
|
||||||
|
function look_up_macro
|
||||||
|
argument macros
|
||||||
|
argument name
|
||||||
|
local p
|
||||||
|
local b
|
||||||
|
p = macros
|
||||||
|
:macro_lookup_loop
|
||||||
|
if *1p == 0 goto return_0
|
||||||
|
b = str_equals(p, name)
|
||||||
|
if b != 0 goto macro_lookup_loop_end
|
||||||
|
; advance to next macro
|
||||||
|
p = memchr(p, 255)
|
||||||
|
p += 1
|
||||||
|
goto macro_lookup_loop
|
||||||
|
:macro_lookup_loop_end
|
||||||
|
p = memchr(p, 0)
|
||||||
|
p += 1
|
||||||
|
return p
|
||||||
|
|
||||||
function look_up_object_macro
|
function look_up_object_macro
|
||||||
argument name
|
argument name
|
||||||
local p
|
return look_up_macro(object_macros, name)
|
||||||
p = object_macros
|
|
||||||
:objmacro_lookup_loop
|
function look_up_function_macro
|
||||||
@TODO
|
argument name
|
||||||
|
return look_up_macro(function_macros, name)
|
||||||
|
|
||||||
function print_object_macros
|
function print_object_macros
|
||||||
|
print_macros(object_macros)
|
||||||
|
return
|
||||||
|
|
||||||
|
function print_function_macros
|
||||||
|
print_macros(function_macros)
|
||||||
|
return
|
||||||
|
|
||||||
|
function print_macros
|
||||||
|
argument macros
|
||||||
local p
|
local p
|
||||||
local c
|
local c
|
||||||
p = object_macros
|
p = macros
|
||||||
:print_objmacros_loop
|
:print_macros_loop
|
||||||
if *1p == 0 goto return_0 ; done!
|
if *1p == 0 goto return_0 ; done!
|
||||||
puts(p)
|
puts(p)
|
||||||
putc(':)
|
putc(':)
|
||||||
putc(32)
|
putc(32)
|
||||||
p = memchr(p, 0)
|
p = memchr(p, 0)
|
||||||
p += 1
|
p += 1
|
||||||
:print_objreplacement_loop
|
:print_replacement_loop
|
||||||
|
c = *1p
|
||||||
|
if c == 255 goto print_replacement_loop_end
|
||||||
|
if c < 32 goto print_macro_param
|
||||||
putc('{)
|
putc('{)
|
||||||
puts(p)
|
puts(p)
|
||||||
putc('})
|
putc('})
|
||||||
p = memchr(p, 0)
|
p = memchr(p, 0)
|
||||||
p += 1
|
p += 1
|
||||||
c = *1p
|
goto print_replacement_loop
|
||||||
if c == 255 goto print_objreplacement_loop_end
|
:print_macro_param
|
||||||
goto print_objreplacement_loop
|
putc('{)
|
||||||
:print_objreplacement_loop_end
|
putc('#)
|
||||||
|
putn(c)
|
||||||
|
putc('})
|
||||||
|
p += 2
|
||||||
|
goto print_replacement_loop
|
||||||
|
:print_replacement_loop_end
|
||||||
p += 1
|
p += 1
|
||||||
fputc(1, 10)
|
fputc(1, 10)
|
||||||
goto print_objmacros_loop
|
goto print_macros_loop
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -205,6 +205,11 @@ function fputn
|
||||||
fputs(fd, s)
|
fputs(fd, s)
|
||||||
return
|
return
|
||||||
|
|
||||||
|
function putn
|
||||||
|
argument n
|
||||||
|
fputn(1, n)
|
||||||
|
return
|
||||||
|
|
||||||
function fputc
|
function fputc
|
||||||
argument fd
|
argument fd
|
||||||
argument c
|
argument c
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue