Mirror of CollapseOS
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
2.8KB

  1. ; *** Requirements ***
  2. ; lib/parse
  3. ;
  4. ; *** Consts ***
  5. ; maximum number of bytes to receive as args in all commands. Determines the
  6. ; size of the args variable.
  7. .equ PARSE_ARG_MAXCOUNT 3
  8. ; *** Code ***
  9. ; Parse arguments at (HL) with specifiers at (DE) into (IX).
  10. ;
  11. ; Args specifiers are a series of flag for each arg:
  12. ; Bit 0 - arg present: if unset, we stop parsing there
  13. ; Bit 1 - is word: this arg is a word rather than a byte. Because our
  14. ; destination are bytes anyway, this doesn't change much except
  15. ; for whether we expect a space between the hex pairs. If set,
  16. ; you still need to have a specifier for the second part of
  17. ; the multibyte.
  18. ; Bit 2 - optional: If set and not present during parsing, we don't error out
  19. ; and write zero
  20. ;
  21. ; Bit 3 - String argument: If set, this argument is a string. A pointer to the
  22. ; read string, null terminated (max 0x20 chars) will
  23. ; be placed in the next two bytes. This has to be the
  24. ; last argument of the list and it stops parsing.
  25. ; Sets A to nonzero if there was an error during parsing, zero otherwise.
  26. parseArgs:
  27. push bc
  28. push de
  29. push hl
  30. push ix
  31. ; init the arg value to a default 0
  32. xor a
  33. ld (ix), a
  34. ld (ix+1), a
  35. ld (ix+2), a
  36. ld b, PARSE_ARG_MAXCOUNT
  37. .loop:
  38. ld a, (hl)
  39. ; is this the end of the line?
  40. or a ; cp 0
  41. jr z, .endofargs
  42. ; Get the specs
  43. ld a, (de)
  44. bit 0, a ; do we have an arg?
  45. jr z, .error ; not set? then we have too many args
  46. ld c, a ; save the specs for multibyte check later
  47. bit 3, a ; is our arg a string?
  48. jr z, .notAString
  49. ; our arg is a string. Let's place HL in our next two bytes and call
  50. ; it a day. Little endian, remember
  51. ld (ix), l
  52. ld (ix+1), h
  53. jr .success ; directly to success: skip endofargs checks
  54. .notAString:
  55. call parseHexPair
  56. jr c, .error
  57. ; we have a good arg and we need to write A in (IX).
  58. ld (ix), a
  59. ; Good! increase counters
  60. inc de
  61. inc ix
  62. inc hl ; get to following char (generally a space)
  63. ; Our arg is parsed, our pointers are increased. Normally, HL should
  64. ; point to a space *unless* our argspec indicates a multibyte arg.
  65. bit 1, c
  66. jr nz, .nospacecheck ; bit set? no space check
  67. ; do we have a proper space char (or null char)?
  68. ld a, (hl)
  69. or a
  70. jr z, .endofargs
  71. cp ' '
  72. jr nz, .error
  73. inc hl
  74. .nospacecheck:
  75. djnz .loop
  76. ; If we get here, it means that our next char *has* to be a null char
  77. ld a, (hl)
  78. or a ; cp 0
  79. jr z, .success ; zero? great!
  80. jr .error
  81. .endofargs:
  82. ; We encountered our null char. Let's verify that we either have no
  83. ; more args or that they are optional
  84. ld a, (de)
  85. or a
  86. jr z, .success ; no arg? success
  87. bit 2, a
  88. jr z, .error ; if unset, arg is not optional. error
  89. ; success
  90. .success:
  91. xor a
  92. jr .end
  93. .error:
  94. inc a
  95. .end:
  96. pop ix
  97. pop hl
  98. pop de
  99. pop bc
  100. ret