820
|
1 ********************************************************************
|
|
2 * NGU - The "Next Great Utility"
|
|
3 *
|
|
4 * $Id$
|
|
5 *
|
|
6 * NGU is a template for writing utilities under OS-9/6809. It has
|
|
7 * robust option handling and is littered with comments to help you
|
|
8 * write your own utilities.
|
|
9 *
|
|
10 * NGU uses a two-pass method for parsing the command line. On the
|
|
11 * first pass, dash options are processed and internal flags are set
|
|
12 * accordingly. As the options are processed, they are cleared to
|
|
13 * spaces so that they won't be present on the second pass.
|
|
14 *
|
|
15 * For the second pass, NGU parses options that don't begin with -.
|
|
16 * Presumably these are filenames or other names that are to be
|
|
17 * processed.
|
|
18 *
|
|
19 * Features:
|
|
20 * - Both options and files can be specified anywhere
|
|
21 * on the command line
|
|
22 * (i.e ngu -a test1 -b test2 -c=foo)
|
|
23 *
|
|
24 * - Options can be combined behind one dash:
|
|
25 * (i.e ngu -ab test1 -c=foo test2 test3)
|
|
26 *
|
|
27 * - Several useful assembly routines are provided for
|
|
28 * copying strings and determining string length.
|
|
29 *
|
|
30 * Limitations:
|
|
31 * - Only single character options can be processed.
|
|
32 * Multi-character options (i.e. -delete) are not allowed.
|
|
33 *
|
|
34 * - The current file counter is one byte, allowing a maximum
|
|
35 * of 255 files.
|
|
36 *
|
|
37 * Ed. Comments Who YY/MM/DD
|
|
38 * ------------------------------------------------------------------
|
|
39 * 1 Put your development info here BGP 03/01/11
|
|
40
|
|
41 nam NGU
|
|
42 ttl The "Next Great Utility"
|
|
43
|
|
44 ifp1
|
|
45 use defsfile
|
|
46 use rbfdefs
|
|
47 endc
|
|
48
|
|
49 * Here are some tweakable options
|
|
50 DOHELP set 1 1 = include help info
|
|
51 STCKSIZE set 64 our stack size in bytes
|
|
52 COPTSIZ set 64 max size of C option's parameter
|
|
53
|
|
54 * Module header definitions
|
|
55 tylg set Prgrm+Objct
|
|
56 atrv set ReEnt+rev
|
|
57 rev set $01
|
|
58 edition set 1
|
|
59
|
|
60 mod eom,name,tylg,atrv,start,size
|
|
61
|
|
62
|
|
63 * Your utility's static storage vars go here
|
|
64 org 0
|
|
65 parmptr rmb 2 pointer to our command line params
|
|
66 bufptr rmb 2 pointer to user expandable buffer
|
|
67 bufsiz rmb 2 size of user expandable buffer
|
|
68 * What follows are utility specific options
|
|
69 gota rmb 1
|
|
70 gotb rmb 1
|
|
71 filecnt rmb 1
|
|
72 coptflg rmb 1 1 = this option has been processed once already
|
|
73 clrmark equ . everything before here gets cleared at start
|
|
74 copt rmb COPTSIZ buffer for what follows after -c=
|
|
75 * Next is a user adjustable buffer with # modifier on command line.
|
|
76 * Some utilities won't need this, some will.
|
|
77 * Currently set up to be larger for Level 2 than Level 1
|
|
78 * Note: this buffer must come just before the stack
|
|
79 IFGT Level-1
|
|
80 bigbuff rmb 8*1024 8K default buffer for Level 2
|
|
81 ELSE
|
|
82 bigbuff rmb 512 512 byte default buffer for Level 1
|
|
83 ENDC
|
|
84 * Finally the stack for any PSHS/PULS/BSR/LBSRs that we might do
|
|
85 stack rmb STCKSIZE
|
|
86 size equ .
|
|
87
|
|
88 * The utility name and edition goes here
|
821
|
89 name fcs /NGU/
|
820
|
90 fcb edition
|
|
91
|
|
92 * Place constant strings here
|
|
93 IFNE DOHELP
|
|
94 HlpMsg fcb C$LF
|
|
95 fcc /Use: NGU [<opts>] <path> [<path>] [<opts>]/
|
|
96 fcb C$LF
|
|
97 fcc / -a option 1/
|
|
98 fcb C$LF
|
|
99 fcc / -b option 2/
|
|
100 fcb C$LF
|
|
101 fcb C$CR
|
|
102 HlpMsgL equ *-HlpMsg
|
|
103 ENDC
|
821
|
104 UnkOpt fcc /unknown option: /
|
|
105 UnkOptL equ *-UnkOpt
|
820
|
106
|
|
107 * Here's how registers are set when this process is forked:
|
|
108 *
|
|
109 * +-----------------+ <-- Y (highest address)
|
|
110 * ! Parameter !
|
|
111 * ! Area !
|
|
112 * +-----------------+ <-- X, SP
|
|
113 * ! Data Area !
|
|
114 * +-----------------+
|
|
115 * ! Direct Page !
|
|
116 * +-----------------+ <-- U, DP (lowest address)
|
|
117 *
|
|
118 * D = parameter area size
|
|
119 * PC = module entry point abs. address
|
|
120 * CC = F=0, I=0, others undefined
|
|
121
|
|
122 * The start of the program is here
|
|
123 * Before any command line processing is done, we clear out
|
|
124 * our static memory from U to clrmark, then determine the
|
|
125 * size of our data area (minus stack)
|
|
126 start pshs u,x save registers for later
|
|
127 leax <clrmark,u point to end of area to zero out
|
|
128 IFNE H6309
|
821
|
129 subr u,x subtract U from X
|
|
130 tfr x,w and put X in W
|
|
131 clr ,-s put a zero on the stack
|
|
132 tfm s,u+ and use TFM to clear starting at U
|
|
133 leas 1,s clean up the stack
|
820
|
134 ELSE
|
|
135 pshs x save end pointer on stack
|
|
136 clrnxt clr ,u+ clear out
|
|
137 cmpu ,s done?
|
|
138 bne clrnxt branch if not
|
|
139 leas 2,s else clear stack
|
|
140 ENDC
|
|
141 puls x,u and restore our earlier saved registers
|
|
142 leay bigbuff,u point Y to copy buffer offset in U
|
|
143 stx <parmptr save parameter pointer
|
|
144 sty <bufptr save pointer to buffer
|
|
145 tfr s,d place top of stack in D
|
|
146 IFNE H6309
|
|
147 subr y,d
|
|
148 ELSE
|
|
149 pshs y save Y on stack
|
|
150 subd ,s++ get size of space between copybuf and X
|
|
151 ENDC
|
|
152 subd #STCKSIZE subtract out our stack
|
|
153 std <bufsiz size of our buffer
|
|
154
|
|
155 * At this point we have determined our buffer space and saved pointers
|
821
|
156 * for later use. Now we will parse the command line for options that
|
|
157 * begin with -
|
820
|
158 lbsr SkipSpcs move past any spaces on command line
|
|
159 cmpa #C$CR CR?
|
|
160 lbeq ShowHelp if so, no parameters... show help and exit
|
|
161 GetChar lda ,x+ get next character on cmd line
|
|
162 cmpa #C$CR CR?
|
|
163 lbeq DoNGU if so, do whatever this utility does
|
|
164 cmpa #'- is it an option?
|
|
165 beq GetDash if so, process it
|
|
166 inc <filecnt else must be a non-option argument (file)
|
|
167 lbsr SkipNSpc move past the argument
|
|
168 ChkDash lbsr SkipSpcs and any following spaces
|
|
169 bra GetChar start processing again
|
|
170 GetDash lda #C$SPAC get a space char
|
|
171 sta -1,x and wipe out the dash from the cmd line
|
|
172 GetDash2 ldd ,x+ load option char and char following
|
|
173 anda #$5F make uppercase
|
|
174 IsItA cmpa #'A is it this option?
|
|
175 bne IsItB branch if not
|
|
176 inc <gota
|
|
177 lbra FixCmdLn
|
|
178 IsItB cmpa #'B is it this option?
|
|
179 bne IsItC branch if not
|
|
180 inc <gotb
|
|
181 bra FixCmdLn
|
|
182 IsItC cmpa #'C is it this option?
|
|
183 bne BadOpt branch if not
|
|
184 tst <coptflg was this option already specified?
|
|
185 bne BadOpt show help if so
|
|
186 cmpb #'= 2nd char =?
|
|
187 bne BadOpt show help if not
|
|
188 inc <coptflg else tag this option as parsed
|
|
189 ldb #C$SPAC get space
|
|
190 stb -$01,x write over c
|
|
191 stb ,x+ and = sign, inc X to dest dir
|
|
192 * check for valid char after -c=
|
|
193 lda ,x
|
|
194 cmpa #C$SPAC
|
|
195 lbeq ShowHelp
|
|
196 cmpa #C$COMA
|
|
197 lbeq ShowHelp
|
|
198 cmpa #C$CR
|
|
199 lbeq ShowHelp
|
|
200 leay <copt,u point Y to parameber buffer
|
|
201 tfr y,d transfer Y to D
|
|
202 addd #COPTSIZ
|
|
203 pshs b,a save updated ptr value
|
|
204 ldb #C$SPAC get space
|
|
205 L0339 lda ,x get byte at X
|
|
206 stb ,x+ store space at X and inc
|
|
207 sta ,y+ save loaded byte at Y and inc
|
|
208 cmpy ,s are we at end?
|
|
209 beq L035D branch if so (buffer too small)
|
|
210 cmpa #C$SPAC else is char in A a space?
|
|
211 beq L0350 branch if so
|
|
212 cmpa #C$COMA coma?
|
|
213 beq L0350 branch if so
|
|
214 cmpa #C$CR cr?
|
|
215 bne L0339 get next byte if not
|
|
216 L0350 leax -1,x
|
|
217 sta ,x restore previous A
|
|
218 leas $02,s kill stack
|
|
219 lbra ChkDash
|
|
220 L035D leas $02,s
|
|
221 ldb #$BF else buffer size too small
|
|
222 orcc #Carry
|
|
223 lbra Exit
|
|
224 FixCmdLn lda #C$SPAC get space
|
|
225 sta -$01,x and wipe out option character
|
|
226 cmpb #'0
|
|
227 lblt ChkDash start dash option processing again
|
|
228 lbra GetDash possibly another option following?
|
|
229
|
|
230 * We branch here if we encounter an unknown option character
|
821
|
231 * A = bad option character
|
|
232 BadOpt leax UnkOpt,pcr
|
|
233 ldy #UnkOptL
|
|
234 ldb #C$CR
|
|
235 pshs d save bad option and CR on stack
|
|
236 lda #$02 stderr
|
|
237 os9 I$Write
|
|
238 leax ,s point X at option char on stack
|
|
239 os9 I$WritLn print option and CR
|
|
240 puls d clean up stack
|
|
241 lbra ShowHelp
|
820
|
242
|
|
243
|
|
244 * At this point options are processed.
|
|
245 * We load X with our parameter pointer and go down the command line
|
|
246 * looking at each file to process (options have been wiped out with
|
|
247 * spaces)
|
|
248 DoNGU tst <filecnt we should have at least one file on cmdline
|
|
249 lbeq ShowHelp if not, exit with error
|
|
250 ldx <parmptr get our parameter pointer off stack
|
|
251 lbsr SkipSpcs skip any leading spaces
|
|
252 bra ExitOk
|
|
253
|
|
254 ShowHelp equ *
|
|
255 IFNE DOHELP
|
|
256 leax >HlpMsg,pcr point to help message
|
|
257 ldy #HlpMsgL get length
|
|
258 lda #$02 std error
|
|
259 os9 I$WritLn write it
|
|
260 ENDC
|
|
261 ExitOk clrb clear carry
|
|
262 Exit os9 F$Exit and exit
|
|
263
|
|
264 * This routine counts the number of non-whitespace characters
|
|
265 * starting at X
|
|
266 *
|
|
267 * Entry:
|
|
268 * X = ptr to string (space, comma or CR terminated)
|
|
269 * Exit:
|
|
270 * D = length of string
|
|
271 * X = ptr to byte after string
|
|
272 StrLen pshs u
|
|
273 ldu #$0000
|
|
274 StrLenLp lda ,x+
|
|
275 cmpa #C$SPAC
|
|
276 beq StrLenEx
|
|
277 cmpa #C$COMA
|
|
278 beq StrLenEx
|
|
279 cmpa #C$CR
|
|
280 beq StrLenEx
|
|
281 leau 1,u
|
|
282 bra StrLenLp
|
|
283 StrLenEx tfr u,d
|
|
284 puls u,pc
|
|
285
|
|
286 * This routine copies a string of text from X to Y until
|
|
287 * a whitespace character or CR is encountered
|
|
288 *
|
|
289 * Entry:
|
|
290 * X = ptr to src string
|
|
291 * Y = ptr to dest string
|
|
292 * Exit:
|
|
293 * D = number of bytes copied
|
|
294 * X = ptr to byte after original string
|
|
295 * Y = ptr to byte after copied string
|
|
296 StrCpy pshs u
|
|
297 ldu #$0000
|
|
298 CopyFnLp lda ,x+
|
|
299 cmpa #C$SPAC
|
|
300 beq CopyFnEx
|
|
301 cmpa #C$COMA
|
|
302 beq CopyFnEx
|
|
303 cmpa #C$CR
|
|
304 beq CopyFnEx
|
|
305 sta ,y+
|
|
306 leau 1,u
|
|
307 bra CopyFnLp
|
|
308 CopyFnEx tfr u,d
|
|
309 puls u,pc
|
|
310
|
|
311 * This routine skip over spaces and commas
|
|
312 *
|
|
313 * Entry:
|
|
314 * X = ptr to data to parse
|
|
315 * Exit:
|
|
316 * X = ptr to first non-whitespace char
|
|
317 * A = non-whitespace char
|
|
318 SkipSpcs lda ,x+
|
|
319 cmpa #C$SPAC
|
|
320 beq SkipSpcs
|
|
321 cmpa #C$COMA
|
|
322 beq SkipSpcs
|
|
323 leax -1,x
|
|
324 rts
|
|
325
|
821
|
326 * This routine skips over everything but spaces, commas and CRs
|
820
|
327 *
|
|
328 * Entry:
|
|
329 * X = ptr to data to parse
|
|
330 * Exit:
|
|
331 * X = ptr to first whitespace char
|
|
332 * A = whitespace char
|
|
333 SkipNSpc lda ,x+
|
|
334 cmpa #C$SPAC
|
|
335 beq EatOut
|
|
336 cmpa #C$COMA
|
|
337 beq EatOut
|
|
338 cmpa #C$CR
|
|
339 bne SkipNSpc
|
|
340 EatOut leax -1,x
|
|
341 rts
|
|
342
|
|
343 emod
|
|
344 eom equ *
|
|
345 end
|