$rom_sources/base.ual

( string functions )
( STR_ADDR -> SHORT)
@{ *addr }length
   :INDEX 0 :
   @LEN_LOOP
       *INDEX DUP LFA ++ OVR STA POP
   (addr) DUP :INDEX ADD LFA 0 #LEN_LOOP JNE
   INDEX ++
JCC

( STR_ADDR STR_ADDR -> SHORT )
@{ *addr1 *addr2 }compare
   :IN_2 0 :
   @CMP_LOOP
       (addr1 addr2) OVR IN_2 ADD LFA
       OVR IN_2 ADD LFA
       DUP 0 #EXIT JEQ
       :IN_2 ++ : POP
       #CMP_LOOP JEQ
   @EXIT_FALSE
       POP POP (addresses)
       0 JCC
   @EXIT
       OVR 0 #EXIT_TRUE JEQ
       #EXIT_FALSE JMP
   @EXIT_TRUE
       POP POP POP POP (loaded data and addresses)
       1 JCC
JCC

( STR_ADDR STR_ADDR SHORT SHORT -> SHORT )
@{ *addr1 *addr2 len len }compare_substr :SUB_STOP : :SUB_START :
   :IN_1 0 :
   :IN_2 SUB_START :
   @CMP_LOOP
       (addr1 addr2) OVR IN_2 ADD LFA
       OVR IN_1 ADD LFA
       (reached the end of *a* string) DUP 0 #EXIT JEQ
       #CHECK_END_OF_SUBSTR JEQ
   @EXIT_FALSE
       POP POP (addresses)
       0 JCC
   @EXIT
       OVR 0 #EXIT_TRUE JEQ
       #EXIT_FALSE JMP
   @EXIT_TRUE
       POP POP POP POP (loaded data and addresses)
       1 JCC
   @CHECK_END_OF_SUBSTR
       (reached the end of *the* substrings) IN_2 SUB_STOP #EXIT_TRUE JEQ
       :IN_2 ++ : POP
       :IN_1 ++ : POP
       #CMP_LOOP JMP
JCC

( We need to add the ability to do width control here)
( STR_ADDR DATA_ADDR ->)
@{ *str *data }f*>>
   :FSTRING_INDEX 0 :
   :FS_DATA_INDEX 0 :
   :F_STRING 0 :
   :FS_DATA 0 :
   :FS_FORMAT_TYPE 0cC :

   DUP *FS_DATA STA
   OVR *F_STRING STA
   @PARSE_STRING
       ?@IF_CURRENT_% F_STRING FSTRING_INDEX ADD LFA 0c% = ?
           :FSTRING_INDEX ++ : POP
           F_STRING FSTRING_INDEX ADD LFA *FS_FORMAT_TYPE STA
           ( Check width value here with a nested if )
           FS_DATA FS_DATA_INDEX ADD LFA 1 1 FS_FORMAT_TYPE OUT
           :FS_DATA_INDEX ++ : POP
       |@ELSE_NOT_% 1 ?
           F_STRING FSTRING_INDEX ADD LFA 1 1 0cC OUT
       ??
       :FSTRING_INDEX ++ : POP
   F_STRING FSTRING_INDEX ADD LFA 0 #PARSE_STRING JNE
JCC

( TODO:MISSING IMPLEMENTATION )
( STR_ADDR STR_ADDR -> SHORT )
@{ *addr1 *addr2 }in
JCC

@{ *addr1 *addr2 }split
JCC

(@{ *str_addr char }previous_index_of )
(    :I 0 :)
(    @LOOP)
(    STR[:I -- :] DUP CHAR #FOUND JEQ)
(    (dupped) 0 #LOOP JNE)
(    @NOT_FOUND -1 JCC)
(    @FOUND POP I JCC)
(JCC)

(@{ *str_addr char }next_index_of :CHAR : :STR :)
(    :I 0 :)
(    @LOOP)
(    STR[:I ++ :] DUP CHAR #FOUND JEQ)
(    (dupped) 0 #LOOP JNE)
(    @NOT_FOUND -1 JCC)
(    @FOUND POP I JCC)
(JCC)

@{}string_to_short
   ;NUMERAL_START 48
   :WORKING_NUMBER 0 :
   @CONTINUE_PARSE
       DUP ;NUMERAL_START SUB
       DUP 0 >= OVR 10 < #NOT_NUMERAL JNE
       :WORKING_NUMBER 10 MUL ADD : POP
       ++
   #CONTINUE_PARSE JMP
   @NOT_NUMERAL
   WORKING_NUMBER
JCC