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.

109 lines
2.8KB

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