diff --git a/arg-demo.tal b/arg-demo.tal new file mode 100644 index 0000000..61247ee --- /dev/null +++ b/arg-demo.tal @@ -0,0 +1,43 @@ +( program demonstrating how to use arg.tal ) +( ) +( by d_m ) +( ) +( this program just parses the given arguments, ) +( says how many arguments were provided, and ) +( prints each argument with its index. ) + +|0100 + ;callback ;on-stdin arg/init BRK + +( this needs to end in BRK ) +@on-stdin ( -> BRK ) + BRK + +( this needs to return, i.e. end in JMP2r ) +@callback ( -> ) + ;arg/count LDA LIT "0 ADD + ;message/num STA + ;message emit + ;arg/count LDA #00 ( count^ 0^ ) + &loop ( count^ i^ ) + GTHk ?&ok ( count^ i^ ) + POP2 #010f DEO JMP2r ( ; exit ) + &ok ( count^ i^ ) + DUP LIT "0 ADD #18 DEO ( count^ i^ ; index ) + LIT ": #18 DEO ( count^ i^ ; index ) + #2018 DEO ( count^ i^ ; space ) + DUP arg/read emit ( count^ i^ s* ; string ) + #0a18 DEO ( count^ i^ ; newline ) + INC !&loop ( count^ i+1^ ) + +( this is used to print null-terminated strings ) +@emit ( buf* -> ) + LITr 18 ( buf* [dev^] ) + &lp LDAk ?&k POP2 POPr JMP2r ( ) + &k LDAk STHkr DEO INC2 !&lp ( buf+1* [dev^] ) + +( message to print ) +@message "found 20 &num "X 20 "arguments 0a 00 + +( include arg.tal library ) +~arg.tal diff --git a/arg.tal b/arg.tal new file mode 100644 index 0000000..879a3a6 --- /dev/null +++ b/arg.tal @@ -0,0 +1,82 @@ +( arg.tal ) +( ) +( by d_m ) +( ) +( by calling arg/init during the reset vector ) +( the author can skip all the details of reading ) +( and detecting command-line arguments. ) +( ) +( instead they can "wait" until the arguments ) +( are all read before accessing the argument ) +( count and argument string values in a more ) +( ergonomic way. ) +( ) +( when using arg/init authors provide two things: ) +( - callback to run when all args are read ) +( - stdin vector to use once args are read ) +( ) +( the callback can load arg/count to see how many ) +( arguments were given, and run arg/read to get ) +( the address of a particular argument as a ) +( null-terminated string. ) + +@arg ( arg namespace ) + +( initialize the arg library. ) +( call this during the reset vector. ) +&init ( callback* stdin* -> ) + ;arg/stdin STA2 + ;arg/callback STA2 + #00 ;arg/count STA + ;arg/buffer ;arg/pos STA2 + ;arg/on-read #10 DEO2 + #17 DEI #00 EQU ?&no-args JMP2r + &no-args !arg/complete + +( read the nth argument, starting with n=0. ) +( call this during the callback. ) +&read ( n^ -> s* ) + LITr 00 STH SUBr + ;arg/buffer ( buf* [-n^] ) + &loop STHkr ?&ok POPr JMP2r ( pos* [-i^] ) + &ok LDAk ?¬null INCr ( pos* [-i+1^] ) + ¬null INC2 !&loop ( pos+1* [-j] ) + +( internal: console vector to use during argument parsing ) +&on-read ( -> BRK ) + #17 DEI + DUP #02 NEQ ?&b POP arg/store BRK ( 2: arg data ) + &b DUP #03 NEQ ?&c POP arg/next BRK ( 3: next arg ) + &c DUP #04 NEQ ?&d POP arg/finish BRK ( 4: finished with args ) + &d #0000 DIV BRK ( 0/1 are unexpected, error ) + +( internal: read a character ) +&store ( -> ) + #12 DEI !arg/save + +( internal: finish an argument and store null ) +&next ( -> ) + ;arg/count LDAk INC ROT ROT STA + #00 ( fall-through to save ) + +( internal: store character c in the buffer and update position ) +&save ( c^ -> ) + LIT2r :arg/pos LDA2kr STH2r ( c^ addr* [pos*] ) + STA LDA2kr INC2r SWP2r ( [addr1* pos*] ; addr<-c ) + STA2r JMP2r ( ; pos<-addr+1 ) + +( internal: called when last argument is complete ) +&finish ( -> ) + arg/next ( fall-through to complete ) + +( internal: called when arg parsing is done ) +&complete ( -> ) + ;arg/stdin LDA2 #10 DEO2 + ;arg/callback LDA2 JMP2 + +( some handy variables ) +&stdin $2 ( f: -> BRK ) +&callback $2 ( f: -> ) +&count $1 ( number of args given ) +&pos $2 ( position in buffer ) +&buffer $200 ( argument buffer )