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
|
|
89 name fcs /NGE/
|
|
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
|
|
104
|
|
105 * Here's how registers are set when this process is forked:
|
|
106 *
|
|
107 * +-----------------+ <-- Y (highest address)
|
|
108 * ! Parameter !
|
|
109 * ! Area !
|
|
110 * +-----------------+ <-- X, SP
|
|
111 * ! Data Area !
|
|
112 * +-----------------+
|
|
113 * ! Direct Page !
|
|
114 * +-----------------+ <-- U, DP (lowest address)
|
|
115 *
|
|
116 * D = parameter area size
|
|
117 * PC = module entry point abs. address
|
|
118 * CC = F=0, I=0, others undefined
|
|
119
|
|
120 * The start of the program is here
|
|
121 * Before any command line processing is done, we clear out
|
|
122 * our static memory from U to clrmark, then determine the
|
|
123 * size of our data area (minus stack)
|
|
124 start pshs u,x save registers for later
|
|
125 leax <clrmark,u point to end of area to zero out
|
|
126 IFNE H6309
|
|
127 subr u,x
|
|
128 tfr x,w
|
|
129 clr ,-s
|
|
130 tfm s,u+
|
|
131 leas 1,s
|
|
132 ELSE
|
|
133 pshs x save end pointer on stack
|
|
134 clrnxt clr ,u+ clear out
|
|
135 cmpu ,s done?
|
|
136 bne clrnxt branch if not
|
|
137 leas 2,s else clear stack
|
|
138 ENDC
|
|
139 puls x,u and restore our earlier saved registers
|
|
140 leay bigbuff,u point Y to copy buffer offset in U
|
|
141 stx <parmptr save parameter pointer
|
|
142 sty <bufptr save pointer to buffer
|
|
143 tfr s,d place top of stack in D
|
|
144 IFNE H6309
|
|
145 subr y,d
|
|
146 ELSE
|
|
147 pshs y save Y on stack
|
|
148 subd ,s++ get size of space between copybuf and X
|
|
149 ENDC
|
|
150 subd #STCKSIZE subtract out our stack
|
|
151 std <bufsiz size of our buffer
|
|
152
|
|
153 * At this point we have determined our buffer space and saved pointers
|
|
154 * for later use. Now we will parse the command line
|
|
155 lbsr SkipSpcs move past any spaces on command line
|
|
156 cmpa #C$CR CR?
|
|
157 lbeq ShowHelp if so, no parameters... show help and exit
|
|
158 GetChar lda ,x+ get next character on cmd line
|
|
159 cmpa #C$CR CR?
|
|
160 lbeq DoNGU if so, do whatever this utility does
|
|
161 cmpa #'- is it an option?
|
|
162 beq GetDash if so, process it
|
|
163 inc <filecnt else must be a non-option argument (file)
|
|
164 lbsr SkipNSpc move past the argument
|
|
165 ChkDash lbsr SkipSpcs and any following spaces
|
|
166 bra GetChar start processing again
|
|
167 GetDash lda #C$SPAC get a space char
|
|
168 sta -1,x and wipe out the dash from the cmd line
|
|
169 GetDash2 ldd ,x+ load option char and char following
|
|
170 anda #$5F make uppercase
|
|
171 IsItA cmpa #'A is it this option?
|
|
172 bne IsItB branch if not
|
|
173 inc <gota
|
|
174 lbra FixCmdLn
|
|
175 IsItB cmpa #'B is it this option?
|
|
176 bne IsItC branch if not
|
|
177 inc <gotb
|
|
178 bra FixCmdLn
|
|
179 IsItC cmpa #'C is it this option?
|
|
180 bne BadOpt branch if not
|
|
181 tst <coptflg was this option already specified?
|
|
182 bne BadOpt show help if so
|
|
183 cmpb #'= 2nd char =?
|
|
184 bne BadOpt show help if not
|
|
185 inc <coptflg else tag this option as parsed
|
|
186 ldb #C$SPAC get space
|
|
187 stb -$01,x write over c
|
|
188 stb ,x+ and = sign, inc X to dest dir
|
|
189 * check for valid char after -c=
|
|
190 lda ,x
|
|
191 cmpa #C$SPAC
|
|
192 lbeq ShowHelp
|
|
193 cmpa #C$COMA
|
|
194 lbeq ShowHelp
|
|
195 cmpa #C$CR
|
|
196 lbeq ShowHelp
|
|
197 leay <copt,u point Y to parameber buffer
|
|
198 tfr y,d transfer Y to D
|
|
199 addd #COPTSIZ
|
|
200 pshs b,a save updated ptr value
|
|
201 ldb #C$SPAC get space
|
|
202 L0339 lda ,x get byte at X
|
|
203 stb ,x+ store space at X and inc
|
|
204 sta ,y+ save loaded byte at Y and inc
|
|
205 cmpy ,s are we at end?
|
|
206 beq L035D branch if so (buffer too small)
|
|
207 cmpa #C$SPAC else is char in A a space?
|
|
208 beq L0350 branch if so
|
|
209 cmpa #C$COMA coma?
|
|
210 beq L0350 branch if so
|
|
211 cmpa #C$CR cr?
|
|
212 bne L0339 get next byte if not
|
|
213 L0350 leax -1,x
|
|
214 sta ,x restore previous A
|
|
215 leas $02,s kill stack
|
|
216 lbra ChkDash
|
|
217 L035D leas $02,s
|
|
218 ldb #$BF else buffer size too small
|
|
219 orcc #Carry
|
|
220 lbra Exit
|
|
221 FixCmdLn lda #C$SPAC get space
|
|
222 sta -$01,x and wipe out option character
|
|
223 cmpb #'0
|
|
224 lblt ChkDash start dash option processing again
|
|
225 lbra GetDash possibly another option following?
|
|
226
|
|
227 * We branch here if we encounter an unknown option character
|
|
228 BadOpt lbra ShowHelp
|
|
229
|
|
230
|
|
231 * At this point options are processed.
|
|
232 * We load X with our parameter pointer and go down the command line
|
|
233 * looking at each file to process (options have been wiped out with
|
|
234 * spaces)
|
|
235 DoNGU tst <filecnt we should have at least one file on cmdline
|
|
236 lbeq ShowHelp if not, exit with error
|
|
237 ldx <parmptr get our parameter pointer off stack
|
|
238 lbsr SkipSpcs skip any leading spaces
|
|
239 bra ExitOk
|
|
240
|
|
241 ShowHelp equ *
|
|
242 IFNE DOHELP
|
|
243 leax >HlpMsg,pcr point to help message
|
|
244 ldy #HlpMsgL get length
|
|
245 lda #$02 std error
|
|
246 os9 I$WritLn write it
|
|
247 ENDC
|
|
248 ExitOk clrb clear carry
|
|
249 Exit os9 F$Exit and exit
|
|
250
|
|
251 * This routine counts the number of non-whitespace characters
|
|
252 * starting at X
|
|
253 *
|
|
254 * Entry:
|
|
255 * X = ptr to string (space, comma or CR terminated)
|
|
256 * Exit:
|
|
257 * D = length of string
|
|
258 * X = ptr to byte after string
|
|
259 StrLen pshs u
|
|
260 ldu #$0000
|
|
261 StrLenLp lda ,x+
|
|
262 cmpa #C$SPAC
|
|
263 beq StrLenEx
|
|
264 cmpa #C$COMA
|
|
265 beq StrLenEx
|
|
266 cmpa #C$CR
|
|
267 beq StrLenEx
|
|
268 leau 1,u
|
|
269 bra StrLenLp
|
|
270 StrLenEx tfr u,d
|
|
271 puls u,pc
|
|
272
|
|
273 * This routine copies a string of text from X to Y until
|
|
274 * a whitespace character or CR is encountered
|
|
275 *
|
|
276 * Entry:
|
|
277 * X = ptr to src string
|
|
278 * Y = ptr to dest string
|
|
279 * Exit:
|
|
280 * D = number of bytes copied
|
|
281 * X = ptr to byte after original string
|
|
282 * Y = ptr to byte after copied string
|
|
283 StrCpy pshs u
|
|
284 ldu #$0000
|
|
285 CopyFnLp lda ,x+
|
|
286 cmpa #C$SPAC
|
|
287 beq CopyFnEx
|
|
288 cmpa #C$COMA
|
|
289 beq CopyFnEx
|
|
290 cmpa #C$CR
|
|
291 beq CopyFnEx
|
|
292 sta ,y+
|
|
293 leau 1,u
|
|
294 bra CopyFnLp
|
|
295 CopyFnEx tfr u,d
|
|
296 puls u,pc
|
|
297
|
|
298 * This routine skip over spaces and commas
|
|
299 *
|
|
300 * Entry:
|
|
301 * X = ptr to data to parse
|
|
302 * Exit:
|
|
303 * X = ptr to first non-whitespace char
|
|
304 * A = non-whitespace char
|
|
305 SkipSpcs lda ,x+
|
|
306 cmpa #C$SPAC
|
|
307 beq SkipSpcs
|
|
308 cmpa #C$COMA
|
|
309 beq SkipSpcs
|
|
310 leax -1,x
|
|
311 rts
|
|
312
|
|
313 * This routine skips over non-spaces and non-commas
|
|
314 *
|
|
315 * Entry:
|
|
316 * X = ptr to data to parse
|
|
317 * Exit:
|
|
318 * X = ptr to first whitespace char
|
|
319 * A = whitespace char
|
|
320 SkipNSpc lda ,x+
|
|
321 cmpa #C$SPAC
|
|
322 beq EatOut
|
|
323 cmpa #C$COMA
|
|
324 beq EatOut
|
|
325 cmpa #C$CR
|
|
326 bne SkipNSpc
|
|
327 EatOut leax -1,x
|
|
328 rts
|
|
329
|
|
330 emod
|
|
331 eom equ *
|
|
332 end
|