Initial revision
[ssr] / StraySrc / Libraries / Sapphire / s / cmdLine
1 ;
2 ; cmdLine.s
3 ;
4 ; Command line parsing (MDW)
5 ;
6 ; © 1994-1998 Straylight
7 ;
8
9 ;----- Licensing note -------------------------------------------------------
10 ;
11 ; This file is part of Straylight's Sapphire library.
12 ;
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)
16 ; any later version.
17 ;
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.
22 ;
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.
26
27 ;----- Standard header ------------------------------------------------------
28
29 GET libs:header
30 GET libs:swis
31
32 ;----- Main code ------------------------------------------------------------
33
34 AREA |Sapphire$$Code|,CODE,READONLY
35
36 ; --- cl_next ---
37 ;
38 ; On entry: R0 == pointer to a command line string (ctrl terminated)
39 ; R1 == pointer to a buffer (may be equal to R0)
40 ;
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
45 ; else CC and
46 ; R0 == pointer to terminating character
47 ; R1 preserved, buffer preserved
48 ; R2 corrupted
49 ;
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:
53 ;
54 ; ; R0 == pointer to command line in writable buffer
55 ;
56 ; MOV R1,R0
57 ; ADR R3,argv
58 ; MOV R4,#0
59 ; loop BL cl_next
60 ; MOVCC R1,#0
61 ; STR R1,[R3],#4
62 ; ADDCS R4,#0
63 ; BCS loop
64 ;
65 ; ; R0-R3 corrupted
66 ; ; R4 == argc
67 ;
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
71 ; strings.
72
73 EXPORT cl_next
74 cl_next ROUT
75
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
83
84 ; --- Skip past leading spaces ---
85
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
90
91 ; --- Main character reading loop ---
92
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
97
98 CMP R14,R1 ;Is it the last quote char?
99 BEQ %30cl_next ;Yes -- deal with this
100
101 BIC R3,R3,#4 ;Last one wasn't a quote
102
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
107
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
112
113 ; --- Handle a new quote character ---
114
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
119
120 ; --- Handle a matched quote character ---
121 ;
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:
124 ;
125 ; if lastWasCloseQuotes
126 ; write literal quote char
127 ; set inQuotes
128 ; clear lastWasCloseQuotes
129 ; else if inQuotes
130 ; clear inQuotes
131 ; set lastWasCloseQuotes
132 ; end
133
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
142
143 ; --- We reached the end of the string ---
144
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
151
152 LTORG
153
154 ; --- cl_buildArgv ---
155 ;
156 ; On entry: R0 == command line string (writable)
157 ; R1 == address of argv buffer
158 ;
159 ; On exit: R1 == next unused location in argv buffer
160 ;
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.
164
165 EXPORT cl_buildArgv
166 cl_buildArgv ROUT
167
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
171
172 ; --- Copy the argument pointers over ---
173
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
179
180 ; --- Tidy up and leave ---
181
182 SUB R1,R3,#4 ;Point at terminating zero
183 LDMFD R13!,{R0,R2,R3,PC}^ ;And return to caller
184
185 LTORG
186
187 ; --- cl_getopt ---
188 ;
189 ; On entry: R1 = pointer to
190 ;
191 ; On exit:
192
193
194 ;----- That's all, folks ----------------------------------------------------
195
196 END