4 ; Command line parsing (MDW)
6 ; © 1994-1998 Straylight
9 ;----- Licensing note -------------------------------------------------------
11 ; This file is part of Straylight's Sapphire library.
13 ; Sapphire is free software; you can redistribute it and/or modify
14 ; it under the terms of the GNU General Public License as published by
15 ; the Free Software Foundation; either version 2, or (at your option)
18 ; Sapphire is distributed in the hope that it will be useful,
19 ; but WITHOUT ANY WARRANTY; without even the implied warranty of
20 ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 ; GNU General Public License for more details.
23 ; You should have received a copy of the GNU General Public License
24 ; along with Sapphire. If not, write to the Free Software Foundation,
25 ; 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
27 ;----- Standard header ------------------------------------------------------
32 ;----- Main code ------------------------------------------------------------
34 AREA |Sapphire$$Code|,CODE,READONLY
38 ; On entry: R0 == pointer to a command line string (ctrl terminated)
39 ; R1 == pointer to a buffer (may be equal to R0)
41 ; On exit: CS if another word found, and
42 ; R0 == updated past next word
43 ; R1 preserved, buffer filled with null terminated string
44 ; R2 == pointer to terminating null character
46 ; R0 == pointer to terminating character
47 ; R1 preserved, buffer preserved
50 ; Use: Extracts the next word from a command line string. If the
51 ; string is in a writable buffer, you can set R1 == R0 to
52 ; start with. You can build up a C-like argv array like this:
54 ; ; R0 == pointer to command line in writable buffer
68 ; This routine will handle quoted strings, considering them
69 ; to be single arguments. Either type of quote will do,
70 ; quote doubling is required to insert quotes in quoted
76 STMFD R13!,{R1,R3,R14} ;Save some registers
77 MOV R2,R1 ;Set up buffer pointer
78 MOV R1,#0 ;No quotes found yet
79 MOV R3,#0 ;Various flags:
80 ; b0 == written a character
81 ; b1 == currently in quotes
82 ; b2 == just closed quotes
84 ; --- Skip past leading spaces ---
86 00cl_next LDRB R14,[R0],#1 ;Load a byte from the string
87 CMP R14,#' ' ;Is it a space?
88 CMPNE R14,#9 ;Or a tab will do too
89 BEQ %00cl_next ;Yes -- get another character
91 ; --- Main character reading loop ---
93 10cl_next CMP R14,#' ' ;Is it the string end?
94 SUBLO R0,R0,#1 ;Keep ptr at ctrl char
95 TSTEQ R3,#2 ;Are we currently in quotes?
96 BLS %90cl_next ;No -- deal with it nicely
98 CMP R14,R1 ;Is it the last quote char?
99 BEQ %30cl_next ;Yes -- deal with this
101 BIC R3,R3,#4 ;Last one wasn't a quote
103 CMP R14,#'"' ;Is it a double quote?
104 CMPNE R14,#''' ;Or a single one?
105 TSTEQ R3,#2 ;Make sure not in quoted
106 BEQ %20cl_next ;Yes -- deal with this then
108 STRB R14,[R2],#1 ;Otherwise store the byte
109 ORR R3,R3,#1 ;Remember we've done it
110 LDRB R14,[R0],#1 ;Load a byte from the string
111 B %10cl_next ;And go round again
113 ; --- Handle a new quote character ---
115 20cl_next MOV R1,R14 ;Remember the quote character
116 ORR R3,R3,#2 ;We're now in quotes
117 LDRB R14,[R0],#1 ;Load a byte from the string
118 B %10cl_next ;And go round again
120 ; --- Handle a matched quote character ---
122 ; Now this may be a close quote, or it may be a double quote
123 ; to indicate a literal. We handle this by the following:
125 ; if lastWasCloseQuotes
126 ; write literal quote char
128 ; clear lastWasCloseQuotes
131 ; set lastWasCloseQuotes
134 30cl_next TST R3,#6 ;Was last quote, or inQuotes?
135 BEQ %20cl_next ;No -- then it's an open
136 TST R3,#4 ;Was last one a quote?
137 STRNEB R14,[R2],#1 ;Yes -- then store quote
138 ORRNE R3,R3,#1 ;Remember we store something
139 EOR R3,R3,#6 ;And toggle the bits nicely
140 LDRB R14,[R0],#1 ;Load a byte from the string
141 B %10cl_next ;Return to the loop
143 ; --- We reached the end of the string ---
145 90cl_next TST R3,#1 ;Did we write any text?
146 MOVNE R14,#0 ;A terminating null
147 STRNEB R14,[R2],#0 ;If so, terminate the text
148 LDMFD R13!,{R1,R3,R14} ;Unstack the registers
149 ORRNES PC,R14,#C_flag ;If so, set C on exit
150 BICEQS PC,R14,#C_flag ;Otherwise clear C
154 ; --- cl_buildArgv ---
156 ; On entry: R0 == command line string (writable)
157 ; R1 == address of argv buffer
159 ; On exit: R1 == next unused location in argv buffer
161 ; Use: Turns the given string into an argv array which will make
162 ; argument scanning easier. This is pretty much the code
163 ; given in the description of cl_next.
168 STMFD R13!,{R0,R2,R3,R14} ;Save some registers
169 MOV R3,R1 ;Move the argv address away
170 MOV R1,R0 ;Point to output buffer
172 ; --- Copy the argument pointers over ---
174 00 BL cl_next ;Fetch the next argument
175 MOVCC R1,#0 ;If done, null terminate list
176 STR R1,[R3],#4 ;Store the pointer away
177 MOVCS R1,R0 ;More to come -- reset buffer
178 BCS %b00 ;And loop around
180 ; --- Tidy up and leave ---
182 SUB R1,R3,#4 ;Point at terminating zero
183 LDMFD R13!,{R0,R2,R3,PC}^ ;And return to caller
189 ; On entry: R1 = pointer to
194 ;----- That's all, folks ----------------------------------------------------