chiark / gitweb /
JPEG support and other fixes from Nick Clark
[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