From ba2d991765567309241894b64421fa23428f78ad Mon Sep 17 00:00:00 2001 From: Andrew Ekstedt Date: Tue, 23 May 2023 19:45:14 -0700 Subject: [PATCH] lib/flags: wip flag parsing definitely doesn't work yet, but i wanted to make a snapshot of my current progress --- lib/flags.s | 243 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 243 insertions(+) create mode 100644 lib/flags.s diff --git a/lib/flags.s b/lib/flags.s new file mode 100644 index 0000000..4e1c66c --- /dev/null +++ b/lib/flags.s @@ -0,0 +1,243 @@ + +.data + +flags: +.dword 0 # value / default +.byte 1 # type: , bool, string, int +.byte 5 # flag length +#.short 16 # help length +.ascii "-help" +#.ascii "prints help text" + +# last flag +.dword 0 +.dword 0 + +.bss + +entry_sp: .dword 0 +saved_argc: .dword 0 +saved_argv: .dword 0 + +# when a program starts, it should stash the initial value of the sp register somewhere +# e.g. +# +# .data +# entry_sp: +# .dword 0 +# _start: +# la t0, entry_sp +# sd sp, (t0) +# +# then at some opportune moment, it can call init_flags. +# a0 should be used to pass in the initial sp value. +# +# la t0, entry_sp +# ld a0, (t0) +# call init_flags + +# in order to store argc and argv +# a0 - initial stack pointer +init_flags: + la t0, saved_argc + ld t1, (a0) + sd t1, (t0) + + la t0, saved_argv + add t2, a0, 8 + sd t2, (t0) + ret + +# a0 - flag definition struct +parse_flags: + la a1, saved_argc + la a2, saved_argv + ld a1, (a1) + ld a2, (a2) + + tail parse_flags_args + +# a0 - flag definition struct +# a1 - argc +# a2 - argv +parse_flags_args: + # TODO: positional arguments + + # syntax: + # -flag (only boolean flags) + # -flag value (only non-boolean flags) + # -flag=value + + # main loop + # for each argument, if it starts with a '-' then see if it matches a flag + mv s2, a2 +.L_arg_loop: + ld s1, (s2) # load string pointer + beqz s1, .L_next_arg # skip null pointer + # check if first char is a '-' + ld t0, (s1) + beqz t0, .Lno # empty string + addi t0, t0, -'-' + bnez t0, .Lno # not a dash + + # TODO: allow --flag + # TODO: -- should end flag parsing + + mv s0, a0 +.L_flag_loop: + + lbu t3, 8(s0) # type + lbu t2, 9(s0) # flag length + beqz t2, .Lunknown_flag + call flagcmp + # return value: + # 0: no match + # 1: match + # 2: match w/ equal sign + bnez t0, .Lfound + +.L_next_flag: + addi s0, s0, 8 + add s0, s0, t2 + j .L_flag_loop + + +.Lfound: + add t0, s1, t2 # arg+len + lbu t1, (t0) + beqz t1, 1f # is it a \0 or an =? + 0:# move s1 past the = + addi t0, t0, 1 + mv s1, t0 + j 2f + 1:# is this a boolean flag? + li t0, 1 + beq t0, t3, 2f + # if not, set s1 to the next arg and advance s2 + ld s1, 8(s2) + addi s2, s2, 8 + # TODO: if it's null, that's an error + 2: + + # ok now parse the flag +.Lparse_flag: + lbu t3, 8(s0) # load type + li t0, 1 + beq t0, t3, boolflag + li t0, 2 + beq t0, t3, strflag + li t0, 3 + beq t0, t3, intflag + j .Lbad_flag_def + +boolflag: + lbu t0, 0(s1) + # if arg is empty, set value to true + beqz t0, 0f + # check for "true" and "false" + li t1, 'f' + beq t0, t1, .Lboolcmpfalse + li t1, 't' + beq t0, t1, .Lboolcmptrue + # anything else is an error + j .Lboolbad + +.Lboolcmpfalse: + lbu t0, 1(s1) + beqz t0, .Lboolbad + li t1, 'a' + bne t1, t0, .Lboolbad + + lbu t0, 2(s1) + beqz t0, .Lboolbad + li t1, 'l' + bne t1, t0, .Lboolbad + + lbu t0, 3(s1) + beqz t0, .Lboolbad + li t1, 's' + bne t1, t0, .Lboolbad + + lbu t0, 4(s1) + beqz t0, .Lboolbad + li t1, 's' + bne t1, t0, .Lboolbad + + lbu t0, 5(s1) + bnez t0, .Lboolbad + j 0b + + sd x0, 0(s0) + j .L_next_arg + +.Lboolcmptrue: + lbu t0, 1(s1) + beqz t0, .Lboolbad + li t1, 'r' + bne t1, t0, .Lboolbad + + lbu t0, 2(s1) + beqz t0, .Lboolbad + li t1, 'u' + bne t1, t0, .Lboolbad + + lbu t0, 3(s1) + beqz t0, .Lboolbad + li t1, 'e' + bne t1, t0, .Lboolbad + + lbu t0, 4(s1) + bnez t0, .Lboolbad + + 1:li t1, 1 + sd t1, 0(s0) + j .L_next_arg + +strflag: + # easy, just store the string pointer + # TODO: strlen + sd s1, 0(s0) + j .L_next_arg + +intflag: + # gotta convert string to int + # TODO: negative numbers + # TODO: detect overflow + # TODO: hex + mv t0, x0 + li t2, 10 + lbu t1, 0(s1) + beqz t1, .Lbadint + 0:addi t1, t1, -0x30 # '0' + bltz t1, .Lbadint + bge t1, t2, .Lbadint + mul t0, t0, t2 + add t0, t0, t1 + addi s1, s1, 1 + lbu t1, 0(s1) + bnez t1, 0b + 1:sd t0, 0(s0) + j .L_next_arg + + +.L_next_arg: + + + ret + +.Lbadint: +.Lboolbad: +.Lunknown_flag: + li a0, -1 + ret + +# t4 - flag +# t5 - +# t6 length +# t0 - return +flagcmp: + mv t0, zero + ret + +handle_flag: +