riscv-utils/lib/flags.s
Andrew Ekstedt ba2d991765 lib/flags: wip flag parsing
definitely doesn't work yet, but i wanted to make a snapshot of my
current progress
2023-05-23 19:45:14 -07:00

244 lines
4.2 KiB
ArmAsm

.data
flags:
.dword 0 # value / default
.byte 1 # type: <end>, 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: