fmacros starting to work!
This commit is contained in:
parent
f08cdc8e22
commit
19ea12a1d4
4 changed files with 137 additions and 14 deletions
|
@ -31,6 +31,9 @@
|
||||||
#define KEYWORD_STATIC 131
|
#define KEYWORD_STATIC 131
|
||||||
#define KEYWORD_WHILE 132
|
#define KEYWORD_WHILE 132
|
||||||
|
|
||||||
|
:str_missing_closing_bracket
|
||||||
|
string Missing closing ).
|
||||||
|
byte 0
|
||||||
:str_comment_start
|
:str_comment_start
|
||||||
string /*
|
string /*
|
||||||
byte 0
|
byte 0
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
#define TEST(x) hello
|
#define TEST(x,y,z) x hello y there z
|
||||||
#define TEST heloo 2
|
TEST((55,(33,3)),22,(3,49))
|
||||||
TEST(55)
|
|
||||||
main(void) {
|
main(void) {
|
||||||
}
|
}
|
||||||
|
|
126
05/preprocess.b
126
05/preprocess.b
|
@ -441,7 +441,7 @@ function translation_phase_4
|
||||||
pptoken_copy_and_advance(&in, &out)
|
pptoken_copy_and_advance(&in, &out)
|
||||||
goto phase4_line
|
goto phase4_line
|
||||||
:phase4_try_replacements
|
:phase4_try_replacements
|
||||||
macro_replacement(&in, &out)
|
macro_replacement(filename, line_number, &in, &out)
|
||||||
goto phase4_line
|
goto phase4_line
|
||||||
:pp_directive
|
:pp_directive
|
||||||
pptoken_skip(&in) ; skip #
|
pptoken_skip(&in) ; skip #
|
||||||
|
@ -498,7 +498,7 @@ function translation_phase_4
|
||||||
param_name = param_names
|
param_name = param_names
|
||||||
:macro_params_loop
|
:macro_params_loop
|
||||||
c = *1in
|
c = *1in
|
||||||
if c == 10 goto missing_closing_bracket
|
if c == 10 goto phase4_missing_closing_bracket
|
||||||
b = isalpha_or_underscore(c)
|
b = isalpha_or_underscore(c)
|
||||||
if b == 0 goto bad_macro_params
|
if b == 0 goto bad_macro_params
|
||||||
param_name = strcpy(param_name, in)
|
param_name = strcpy(param_name, in)
|
||||||
|
@ -563,17 +563,15 @@ function translation_phase_4
|
||||||
string Unrecognized preprocessor directive.
|
string Unrecognized preprocessor directive.
|
||||||
byte 0
|
byte 0
|
||||||
:macro_redefinition
|
:macro_redefinition
|
||||||
|
; @NONSTANDARD:
|
||||||
; technically not an error if it was redefined to the same thing, but it's
|
; technically not an error if it was redefined to the same thing, but it's
|
||||||
; annoying to check for that
|
; annoying to check for that
|
||||||
compile_error(filename, line_number, .str_macro_redefinition)
|
compile_error(filename, line_number, .str_macro_redefinition)
|
||||||
:str_macro_redefinition
|
:str_macro_redefinition
|
||||||
string Macro redefinition.
|
string Macro redefinition.
|
||||||
byte 0
|
byte 0
|
||||||
:missing_closing_bracket
|
:phase4_missing_closing_bracket
|
||||||
compile_error(filename, line_number, .str_missing_closing_bracket)
|
compile_error(filename, line_number, .str_missing_closing_bracket)
|
||||||
:str_missing_closing_bracket
|
|
||||||
string Missing closing ).
|
|
||||||
byte 0
|
|
||||||
:bad_macro_params
|
:bad_macro_params
|
||||||
compile_error(filename, line_number, .str_bad_macro_params)
|
compile_error(filename, line_number, .str_bad_macro_params)
|
||||||
:str_bad_macro_params
|
:str_bad_macro_params
|
||||||
|
@ -608,7 +606,12 @@ function look_up_function_macro
|
||||||
argument name
|
argument name
|
||||||
return look_up_macro(function_macros, name)
|
return look_up_macro(function_macros, name)
|
||||||
|
|
||||||
|
; replace pptoken(s) at *p_in into *p_out, advancing both
|
||||||
|
; NOTE: if *p_in starts with a function-like macro replacement, it is replaced fully,
|
||||||
|
; otherwise this function only reads 1 token from *p_in
|
||||||
function macro_replacement
|
function macro_replacement
|
||||||
|
argument filename
|
||||||
|
argument line_number
|
||||||
argument p_in
|
argument p_in
|
||||||
argument p_out
|
argument p_out
|
||||||
; "banned" macros prevent #define x x from being a problem
|
; "banned" macros prevent #define x x from being a problem
|
||||||
|
@ -623,6 +626,7 @@ function macro_replacement
|
||||||
local banned_fmacros
|
local banned_fmacros
|
||||||
local banned_objmacros
|
local banned_objmacros
|
||||||
local b
|
local b
|
||||||
|
local c
|
||||||
local p
|
local p
|
||||||
local q
|
local q
|
||||||
local replacement
|
local replacement
|
||||||
|
@ -660,10 +664,10 @@ function macro_replacement
|
||||||
replacement = look_up_object_macro(in)
|
replacement = look_up_object_macro(in)
|
||||||
if replacement == 0 goto no_replacement
|
if replacement == 0 goto no_replacement
|
||||||
p = replacement
|
p = replacement
|
||||||
pptoken_skip(&in)
|
pptoken_skip(&in) ; skip macro
|
||||||
:objreplace_loop
|
:objreplace_loop
|
||||||
if *1p == 255 goto done_replacement
|
if *1p == 255 goto done_replacement
|
||||||
macro_replacement(&p, &out)
|
macro_replacement(filename, line_number, &p, &out)
|
||||||
goto objreplace_loop
|
goto objreplace_loop
|
||||||
|
|
||||||
:fmacro_replacement
|
:fmacro_replacement
|
||||||
|
@ -684,15 +688,71 @@ function macro_replacement
|
||||||
|
|
||||||
replacement = look_up_function_macro(in)
|
replacement = look_up_function_macro(in)
|
||||||
if replacement == 0 goto no_replacement
|
if replacement == 0 goto no_replacement
|
||||||
|
pptoken_skip(&in) ; skip macro name
|
||||||
|
pptoken_skip(&in) ; skip opening bracket
|
||||||
|
if *1in == ') goto empty_fmacro_invocation
|
||||||
|
|
||||||
|
local arguments
|
||||||
|
arguments = malloc(4000)
|
||||||
|
|
||||||
|
; store the arguments (separated by 255-characters)
|
||||||
|
p = arguments
|
||||||
|
:fmacro_arg_loop
|
||||||
|
b = fmacro_arg_end(filename, line_number, in)
|
||||||
|
b -= in
|
||||||
|
memcpy(p, in, b) ; copy the argument to its proper place
|
||||||
|
p += b
|
||||||
|
in += b ; skip argument
|
||||||
|
c = *1in
|
||||||
|
in += 2 ; skip , or )
|
||||||
|
*1p = 255
|
||||||
|
p += 1
|
||||||
|
if c == ', goto fmacro_arg_loop
|
||||||
|
*1p = 255 ; use an additional 255-character to mark the end (note: macro arguments may not be empty)
|
||||||
|
|
||||||
|
; print arguments:
|
||||||
|
; p += 1
|
||||||
|
; p -= arguments
|
||||||
|
; syscall(1, 1, arguments, p)
|
||||||
|
|
||||||
p = replacement
|
p = replacement
|
||||||
:freplace_loop
|
:freplace_loop
|
||||||
if *1p == 255 goto done_replacement
|
if *1p == 255 goto freplace_loop_end
|
||||||
byte 0xcc
|
if *1p < 32 goto fmacro_argument
|
||||||
|
macro_replacement(filename, line_number, &p, &out)
|
||||||
|
goto freplace_loop
|
||||||
:freplace_loop_end
|
:freplace_loop_end
|
||||||
|
free(arguments)
|
||||||
|
goto done_replacement
|
||||||
|
|
||||||
|
:fmacro_argument
|
||||||
|
; @TODO: stringify (#), paste (##) operators
|
||||||
|
|
||||||
|
; write argument to *out
|
||||||
|
local arg_idx
|
||||||
|
arg_idx = *1p
|
||||||
|
q = arguments
|
||||||
|
:fmacro_argfind_loop
|
||||||
|
if *1q == 255 goto fmacro_too_few_arguments
|
||||||
|
if arg_idx == 1 goto fmacro_arg_found
|
||||||
|
q = memchr(q, 255)
|
||||||
|
q += 1
|
||||||
|
arg_idx -= 1
|
||||||
|
goto fmacro_argfind_loop
|
||||||
|
:fmacro_arg_found
|
||||||
|
; q = argument
|
||||||
|
:fmacro_argreplace_loop
|
||||||
|
if *1q == 255 goto fmacro_argreplaced
|
||||||
|
macro_replacement(filename, line_number, &q, &out)
|
||||||
|
goto fmacro_argreplace_loop
|
||||||
|
:fmacro_argreplaced
|
||||||
|
p += 2 ; skip arg idx & null separator
|
||||||
|
goto freplace_loop
|
||||||
|
|
||||||
:no_replacement
|
:no_replacement
|
||||||
pptoken_copy_and_advance(&in, &out)
|
pptoken_copy_and_advance(&in, &out)
|
||||||
; (fallthrough)
|
; (fallthrough)
|
||||||
:done_replacement
|
:done_replacement
|
||||||
*8p_in = in
|
*8p_in = in
|
||||||
*8p_out = out
|
*8p_out = out
|
||||||
; unban any macros we just banned
|
; unban any macros we just banned
|
||||||
|
@ -700,6 +760,50 @@ function macro_replacement
|
||||||
*1old_banned_fmacros_end = 255
|
*1old_banned_fmacros_end = 255
|
||||||
return
|
return
|
||||||
|
|
||||||
|
:empty_fmacro_invocation
|
||||||
|
compile_error(filename, line_number, .str_empty_fmacro_invocation)
|
||||||
|
:str_empty_fmacro_invocation
|
||||||
|
string No arguments provided to function-like macro.
|
||||||
|
byte 0
|
||||||
|
:fmacro_too_few_arguments
|
||||||
|
compile_error(filename, line_number, .str_fmacro_too_few_arguments)
|
||||||
|
:str_fmacro_too_few_arguments
|
||||||
|
string Too few arguments to function-like macro.
|
||||||
|
byte 0
|
||||||
|
|
||||||
|
function fmacro_arg_end
|
||||||
|
argument filename
|
||||||
|
argument line_number
|
||||||
|
argument in
|
||||||
|
local bracket_depth
|
||||||
|
bracket_depth = 1
|
||||||
|
:fmacro_arg_end_loop
|
||||||
|
if *1in == 0 goto fmacro_missing_closing_bracket
|
||||||
|
if *1in == '( goto fmacro_arg_opening_bracket
|
||||||
|
if *1in == ') goto fmacro_arg_closing_bracket
|
||||||
|
if *1in == ', goto fmacro_arg_potential_end
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto fmacro_arg_end_loop
|
||||||
|
:fmacro_arg_potential_end
|
||||||
|
if bracket_depth == 1 goto fmacro_arg_end_loop_end
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto fmacro_arg_end_loop
|
||||||
|
:fmacro_arg_opening_bracket
|
||||||
|
bracket_depth += 1
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto fmacro_arg_end_loop
|
||||||
|
:fmacro_arg_closing_bracket
|
||||||
|
bracket_depth -= 1
|
||||||
|
if bracket_depth == 0 goto fmacro_arg_end_loop_end
|
||||||
|
pptoken_skip(&in)
|
||||||
|
goto fmacro_arg_end_loop
|
||||||
|
:fmacro_arg_end_loop_end
|
||||||
|
|
||||||
|
return in
|
||||||
|
|
||||||
|
:fmacro_missing_closing_bracket
|
||||||
|
compile_error(filename, line_number, .str_missing_closing_bracket)
|
||||||
|
|
||||||
function print_object_macros
|
function print_object_macros
|
||||||
print_macros(object_macros)
|
print_macros(object_macros)
|
||||||
return
|
return
|
||||||
|
|
17
05/util.b
17
05/util.b
|
@ -112,6 +112,23 @@ function memccpy_advance
|
||||||
*8p_dest = dest
|
*8p_dest = dest
|
||||||
return
|
return
|
||||||
|
|
||||||
|
; just like C
|
||||||
|
function memcpy
|
||||||
|
argument dest
|
||||||
|
argument src
|
||||||
|
argument n
|
||||||
|
local p
|
||||||
|
local q
|
||||||
|
p = dest
|
||||||
|
q = src
|
||||||
|
:memcpy_loop
|
||||||
|
if n == 0 goto return_0
|
||||||
|
*1p = *1q
|
||||||
|
p += 1
|
||||||
|
q += 1
|
||||||
|
n -= 1
|
||||||
|
goto memcpy_loop
|
||||||
|
|
||||||
function strlen
|
function strlen
|
||||||
argument s
|
argument s
|
||||||
local p
|
local p
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue