start translation phase 4
This commit is contained in:
parent
ac6cb985db
commit
3d0adb5f6f
5 changed files with 245 additions and 4 deletions
|
@ -106,3 +106,27 @@
|
|||
:str_hash_hash
|
||||
string ##
|
||||
byte 0
|
||||
:str_error
|
||||
string error
|
||||
byte 0
|
||||
:str_define
|
||||
string define
|
||||
byte 0
|
||||
:str_include
|
||||
string include
|
||||
byte 0
|
||||
:str_ifdef
|
||||
string ifdef
|
||||
byte 0
|
||||
:str_ifndef
|
||||
string ifndef
|
||||
byte 0
|
||||
:str_if
|
||||
string if
|
||||
byte 0
|
||||
:str_elif
|
||||
string elif
|
||||
byte 0
|
||||
:str_else
|
||||
string else
|
||||
byte 0
|
||||
|
|
18
05/main.b
18
05/main.b
|
@ -8,6 +8,13 @@ byte 0
|
|||
byte 0
|
||||
goto main
|
||||
|
||||
|
||||
global object_macros_size
|
||||
global function_macros_size
|
||||
; these are allocated in main()
|
||||
global object_macros
|
||||
global function_macros
|
||||
|
||||
function compile_error
|
||||
argument file
|
||||
argument line
|
||||
|
@ -15,12 +22,12 @@ function compile_error
|
|||
fputs(2, file)
|
||||
fputc(2, ':)
|
||||
fputn(2, line)
|
||||
fputs(2, .str_error)
|
||||
fputs(2, .str_error_prefix)
|
||||
fputs(2, message)
|
||||
fputc(2, 10)
|
||||
exit(1)
|
||||
|
||||
:str_error
|
||||
:str_error_prefix
|
||||
string : Error:
|
||||
byte 32
|
||||
byte 0
|
||||
|
@ -38,6 +45,9 @@ function main
|
|||
local output_filename
|
||||
local pptokens
|
||||
|
||||
object_macros = malloc(4000000)
|
||||
function_macros = malloc(4000000)
|
||||
|
||||
input_filename = .str_default_input_filename
|
||||
output_filename = .str_default_output_filename
|
||||
if argc == 1 goto have_filenames
|
||||
|
@ -47,6 +57,10 @@ function main
|
|||
:have_filenames
|
||||
pptokens = split_into_preprocessing_tokens(input_filename)
|
||||
print_pptokens(pptokens)
|
||||
print_separator()
|
||||
pptokens = translation_phase_4(input_filename, pptokens)
|
||||
;print_pptokens(pptokens)
|
||||
print_object_macros()
|
||||
exit(0)
|
||||
|
||||
:usage_error
|
||||
|
|
|
@ -1,10 +1,13 @@
|
|||
#include <stdio.h>
|
||||
-#include <stdio.h>
|
||||
|
||||
int test(int, double, ...);\
|
||||
/* here is a nice
|
||||
comment it is
|
||||
here
|
||||
*/
|
||||
#
|
||||
#define A 33
|
||||
#define _Hello_there5 -76 + sqrt(A)
|
||||
int main(void) {
|
||||
printf("\"Hello, world!%c\n\"", '\'');
|
||||
_X55 = Y4_C_;
|
||||
|
|
153
05/preprocess.b
153
05/preprocess.b
|
@ -360,3 +360,156 @@ function print_pptokens
|
|||
:print_pptokens_loop_end
|
||||
putc(10)
|
||||
return
|
||||
|
||||
function pptoken_copy_and_advance
|
||||
argument p_in
|
||||
argument p_out
|
||||
local in
|
||||
local out
|
||||
in = *8p_in
|
||||
out = *8p_out
|
||||
out = strcpy(out, in)
|
||||
in = memchr(in, 0)
|
||||
*8p_in = in + 1
|
||||
*8p_out = out + 1
|
||||
return
|
||||
|
||||
function pptoken_skip
|
||||
argument p_in
|
||||
local in
|
||||
in = *8p_in
|
||||
in = memchr(in, 0)
|
||||
*8p_in = in + 1
|
||||
return
|
||||
|
||||
; skip any space tokens here
|
||||
function pptoken_skip_spaces
|
||||
argument p_in
|
||||
local in
|
||||
in = *8p_in
|
||||
:pptoken_skip_spaces_loop
|
||||
if *1in != 32 goto pptoken_skip_spaces_loop_end
|
||||
pptoken_skip(&in)
|
||||
goto pptoken_skip_spaces_loop
|
||||
:pptoken_skip_spaces_loop_end
|
||||
*8p_in = in
|
||||
return
|
||||
|
||||
; phase 4:
|
||||
; Preprocessing directives are executed and macro invocations are expanded.
|
||||
; A #include preprocessing directive causes the named header or source file to be processed from phase 1 through phase 4, recursively.
|
||||
function translation_phase_4
|
||||
argument filename
|
||||
argument input
|
||||
local output
|
||||
local in
|
||||
local out
|
||||
local p
|
||||
local c
|
||||
local b
|
||||
local line_number
|
||||
|
||||
output = malloc(16000000)
|
||||
out = output
|
||||
in = input
|
||||
line_number = 0
|
||||
|
||||
:phase4_line
|
||||
line_number += 1
|
||||
c = *1in
|
||||
if c == 0 goto phase4_end
|
||||
if c == '# goto pp_directive ; NOTE: ## cannot appear at the start of a line
|
||||
|
||||
:process_pptoken
|
||||
c = *1in
|
||||
if c == 10 goto phase4_next_line
|
||||
b = isdigit(c)
|
||||
if b != 0 goto phase4_next_pptoken
|
||||
|
||||
:phase4_next_pptoken
|
||||
pptoken_copy_and_advance(&in, &out)
|
||||
goto process_pptoken
|
||||
:phase4_next_line
|
||||
pptoken_copy_and_advance(&in, &out)
|
||||
goto phase4_line
|
||||
:pp_directive
|
||||
pptoken_skip(&in)
|
||||
c = *1in
|
||||
if c == 10 goto phase4_next_line ; "null directive" C89 § 3.8.7
|
||||
b = str_equals(in, .str_error)
|
||||
if b != 0 goto pp_directive_error
|
||||
b = str_equals(in, .str_define)
|
||||
if b != 0 goto pp_directive_define
|
||||
goto unrecognized_directive
|
||||
:pp_directive_error
|
||||
fputs(2, filename)
|
||||
fputc(2, ':)
|
||||
fputn(2, line_number)
|
||||
fputs(2, .str_directive_error)
|
||||
exit(1)
|
||||
:pp_directive_define
|
||||
local macro_name
|
||||
pptoken_skip(&in)
|
||||
pptoken_skip_spaces(&in)
|
||||
macro_name = in
|
||||
pptoken_skip(&in)
|
||||
c = *1in
|
||||
if c == '( goto function_macro_definition
|
||||
; it's an object-like macro, e.g. #define X 47
|
||||
p = object_macros + object_macros_size
|
||||
; copy name
|
||||
p = strcpy(p, macro_name)
|
||||
p += 1
|
||||
; copy contents
|
||||
memccpy_advance(&p, &in, 10) ; copy until newline
|
||||
*1p = 255 ; replace newline with special "macro end" character
|
||||
p += 1
|
||||
object_macros_size = p - object_macros
|
||||
in += 2 ; skip newline and following null character
|
||||
goto phase4_line
|
||||
:function_macro_definition
|
||||
; a function-like macro, e.g. #define JOIN(a,b) a##b
|
||||
byte 0xcc
|
||||
:str_directive_error
|
||||
string : #error
|
||||
byte 10
|
||||
byte 0
|
||||
:phase4_end
|
||||
return output
|
||||
:unrecognized_directive
|
||||
compile_error(filename, line_number, .str_unrecognized_directive)
|
||||
:str_unrecognized_directive
|
||||
string Unrecognized preprocessor directive.
|
||||
byte 0
|
||||
|
||||
function look_up_object_macro
|
||||
argument name
|
||||
local p
|
||||
p = object_macros
|
||||
:objmacro_lookup_loop
|
||||
@TODO
|
||||
|
||||
function print_object_macros
|
||||
local p
|
||||
local c
|
||||
p = object_macros
|
||||
:print_objmacros_loop
|
||||
if *1p == 0 goto return_0 ; done!
|
||||
puts(p)
|
||||
putc(':)
|
||||
putc(32)
|
||||
p = memchr(p, 0)
|
||||
p += 1
|
||||
:print_objreplacement_loop
|
||||
putc('{)
|
||||
puts(p)
|
||||
putc('})
|
||||
p = memchr(p, 0)
|
||||
p += 1
|
||||
c = *1p
|
||||
if c == 255 goto print_objreplacement_loop_end
|
||||
goto print_objreplacement_loop
|
||||
:print_objreplacement_loop_end
|
||||
p += 1
|
||||
fputc(1, 10)
|
||||
goto print_objmacros_loop
|
||||
|
|
47
05/util.b
47
05/util.b
|
@ -90,6 +90,28 @@ function memchr
|
|||
:memchr_loop_end
|
||||
return p
|
||||
|
||||
; copy from *p_src to *p_dest until terminator is reached, setting both to point to their respective terminators
|
||||
function memccpy_advance
|
||||
argument p_dest
|
||||
argument p_src
|
||||
argument terminator
|
||||
local src
|
||||
local dest
|
||||
local c
|
||||
src = *8p_src
|
||||
dest = *8p_dest
|
||||
:memccpy_advance_loop
|
||||
c = *1src
|
||||
*1dest = c
|
||||
if c == terminator goto memccpy_advance_loop_end
|
||||
src += 1
|
||||
dest += 1
|
||||
goto memccpy_advance_loop
|
||||
:memccpy_advance_loop_end
|
||||
*8p_src = src
|
||||
*8p_dest = dest
|
||||
return
|
||||
|
||||
function strlen
|
||||
argument s
|
||||
local p
|
||||
|
@ -101,6 +123,7 @@ function strlen
|
|||
:strlen_loop_end
|
||||
return p - s
|
||||
|
||||
; like C strcpy, but returns a pointer to the terminating null character in dest
|
||||
function strcpy
|
||||
argument dest
|
||||
argument src
|
||||
|
@ -119,6 +142,20 @@ function strcpy
|
|||
:strcpy_loop_end
|
||||
return p
|
||||
|
||||
function str_equals
|
||||
argument a
|
||||
argument b
|
||||
local c
|
||||
local d
|
||||
:str_equals_loop
|
||||
c = *1a
|
||||
d = *1b
|
||||
if c != d goto return_0
|
||||
if c == 0 goto return_1
|
||||
a += 1
|
||||
b += 1
|
||||
goto str_equals_loop
|
||||
|
||||
function str_startswith
|
||||
argument s
|
||||
argument prefix
|
||||
|
@ -150,6 +187,16 @@ function puts
|
|||
fputs(1, s)
|
||||
return
|
||||
|
||||
function print_separator
|
||||
fputs(1, .str_separator)
|
||||
return
|
||||
|
||||
:str_separator
|
||||
byte 10
|
||||
string ------------------------------------------------
|
||||
byte 10
|
||||
byte 0
|
||||
|
||||
function fputn
|
||||
argument fd
|
||||
argument n
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue