1 | ;
|
---|
2 | ; OPTIONS.ASM -- Parse options
|
---|
3 | ;
|
---|
4 | ; Copyright (c) 1991-2000 by Eberhard Mattes
|
---|
5 | ;
|
---|
6 | ; This file is part of emx.
|
---|
7 | ;
|
---|
8 | ; emx is free software; you can redistribute it and/or modify it
|
---|
9 | ; under the terms of the GNU General Public License as published by
|
---|
10 | ; the Free Software Foundation; either version 2, or (at your option)
|
---|
11 | ; any later version.
|
---|
12 | ;
|
---|
13 | ; emx is distributed in the hope that it will be useful,
|
---|
14 | ; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
---|
15 | ; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
---|
16 | ; GNU General Public License for more details.
|
---|
17 | ;
|
---|
18 | ; You should have received a copy of the GNU General Public License
|
---|
19 | ; along with emx; see the file COPYING. If not, write to
|
---|
20 | ; the Free Software Foundation, 59 Temple Place - Suite 330,
|
---|
21 | ; Boston, MA 02111-1307, USA.
|
---|
22 | ;
|
---|
23 | ; See emx.asm for a special exception.
|
---|
24 | ;
|
---|
25 |
|
---|
26 | INCLUDE EMX.INC
|
---|
27 | INCLUDE A20.INC
|
---|
28 | INCLUDE PMIO.INC
|
---|
29 | INCLUDE DEBUG.INC
|
---|
30 | INCLUDE MEMORY.INC
|
---|
31 | INCLUDE SIGNAL.INC ; Required by PROCESS.INC
|
---|
32 | INCLUDE PROCESS.INC
|
---|
33 | INCLUDE LOADER.INC
|
---|
34 | INCLUDE EXCEPT.INC
|
---|
35 | INCLUDE RPRINT.INC
|
---|
36 | INCLUDE VERSION.INC
|
---|
37 | INCLUDE XMS.INC
|
---|
38 | INCLUDE MISC.INC
|
---|
39 |
|
---|
40 | PUBLIC TEST_FLAGS, OVERRIDE_FLAG, FP_IGNORE, MACHINE
|
---|
41 | PUBLIC PM_OPTIONS
|
---|
42 | PUBLIC RM_OPTIONS, RM_SKIP_BLANKS, USAGE
|
---|
43 |
|
---|
44 | SV_DATA SEGMENT
|
---|
45 |
|
---|
46 | ;
|
---|
47 | ; Options
|
---|
48 | ;
|
---|
49 | DALIGN 4
|
---|
50 | TEST_FLAGS DWORD 0 ; Test flags
|
---|
51 | OVERRIDE_FLAG BYTE FALSE ; Override some checks
|
---|
52 | FP_IGNORE BYTE FALSE ; Don't check for coprocessor
|
---|
53 |
|
---|
54 | ;
|
---|
55 | ; Hardware
|
---|
56 | ;
|
---|
57 | MACHINE BYTE MACH_PC ; Default: AT compatible
|
---|
58 |
|
---|
59 | OPTT_CALL_NOARG = 0 ; Call function: address
|
---|
60 | OPTT_CALL_ARG = 1 ; Call function: address
|
---|
61 | OPTT_GFLAG = 2 ; Global flag: address
|
---|
62 | OPTT_LFLAG = 3 ; Local flag: mask
|
---|
63 |
|
---|
64 | DOPTION STRUCT
|
---|
65 | OPT_NAME BYTE ?
|
---|
66 | OPT_TYPE BYTE ?
|
---|
67 | OPT_PM BYTE ?
|
---|
68 | OPT_DATA WORD ?
|
---|
69 | DOPTION ENDS
|
---|
70 |
|
---|
71 | OPTIONS_TABLE LABEL DOPTION
|
---|
72 | DOPTION <"!", OPTT_CALL_ARG, 0, OPTF_TEST>
|
---|
73 | DOPTION <"a", OPTT_CALL_ARG, 1, OPTF_ACCESS>
|
---|
74 | DOPTION <"c", OPTT_LFLAG, 1, PF_NO_CORE>
|
---|
75 | DOPTION <"d", OPTT_GFLAG, 0, DISABLE_EXT_MEM>
|
---|
76 | DOPTION <"e", OPTT_LFLAG, 1, PF_REDIR_STDERR>
|
---|
77 | DOPTION <"h", OPTT_CALL_ARG, 0, OPTF_HANDLES>
|
---|
78 | DOPTION <"m", OPTT_CALL_ARG, 0, OPTF_MACHINE>
|
---|
79 | DOPTION <"o", OPTT_GFLAG, 0, STDOUT_DUMP>
|
---|
80 | DOPTION <"p", OPTT_GFLAG, 0, DISABLE_LOW_MEM>
|
---|
81 | DOPTION <"q", OPTT_LFLAG, 1, PF_QUOTE>
|
---|
82 | DOPTION <"r", OPTT_CALL_ARG, 1, OPTF_DRIVE>
|
---|
83 | DOPTION <"s", OPTT_CALL_ARG, 1, OPTF_STACK>
|
---|
84 | DOPTION <"t", OPTT_CALL_ARG, 1, OPTF_TRUNC>
|
---|
85 | DOPTION <"C", OPTT_CALL_ARG, 1, OPTF_COMMIT>
|
---|
86 | DOPTION <"D", OPTT_GFLAG, 0, DEBUG_FLAG>
|
---|
87 | DOPTION <"E", OPTT_GFLAG, 0, FP_IGNORE>
|
---|
88 | DOPTION <"F", OPTT_GFLAG, 0, USE_FAST_A20>
|
---|
89 | DOPTION <"L", OPTT_LFLAG, 1, PF_PRELOAD>
|
---|
90 | DOPTION <"O", OPTT_GFLAG, 0, OVERRIDE_FLAG>
|
---|
91 | DOPTION <"P", OPTT_GFLAG, 0, USE_A20_PATCH>
|
---|
92 | DOPTION <"R", OPTT_CALL_ARG, 0, OPTF_RSX>
|
---|
93 | DOPTION <"S", OPTT_CALL_ARG, 0, OPTF_DEBUG>
|
---|
94 | DOPTION <"V", OPTT_CALL_NOARG, 0, OPTF_VERSION>
|
---|
95 | DOPTION <"X", OPTT_GFLAG, 0, DISABLE_XMS_MEM>
|
---|
96 | DOPTION <"Z", OPTT_LFLAG, 1, PF_DONT_ZERO>
|
---|
97 | DOPTION <0, 0, 0>
|
---|
98 |
|
---|
99 | ;
|
---|
100 | ; Program titel
|
---|
101 | ;
|
---|
102 | $TITLE BYTE "emx ", VERSION, " (rev ", REV_INDEX_TXT, ")"
|
---|
103 | BYTE " -- Copyright (c) 1991-2000 by Eberhard Mattes"
|
---|
104 | BYTE CR, LF, 0
|
---|
105 |
|
---|
106 | $USAGE BYTE "Usage: emx [-cdeoqOV] [-s<stack_size>] "
|
---|
107 | BYTE "<program> [<arguments>]", CR, LF, 0
|
---|
108 |
|
---|
109 | SV_DATA ENDS
|
---|
110 |
|
---|
111 | SV_CODE SEGMENT
|
---|
112 |
|
---|
113 | ASSUME CS:SV_CODE, DS:NOTHING
|
---|
114 |
|
---|
115 | ;
|
---|
116 | ; Skip over blanks
|
---|
117 | ;
|
---|
118 | ; In: ES:SI Pointer to string
|
---|
119 | ;
|
---|
120 | ; Out: ES:SI Pointer to first non-blank character
|
---|
121 | ; AL First non-blank character
|
---|
122 | ;
|
---|
123 | PM_SKIP_BLANKS PROC NEAR
|
---|
124 | PSB_1: MOV AL, ES:[SI]
|
---|
125 | INC SI
|
---|
126 | CMP AL, " "
|
---|
127 | JE SHORT PSB_1
|
---|
128 | CMP AL, TAB
|
---|
129 | JE SHORT PSB_1
|
---|
130 | DEC SI
|
---|
131 | RET
|
---|
132 | PM_SKIP_BLANKS ENDP
|
---|
133 |
|
---|
134 |
|
---|
135 | ;
|
---|
136 | ; Parse options.
|
---|
137 | ;
|
---|
138 | ; In: ES:SI Pointer to null-terminated string
|
---|
139 | ; DI Pointer to process table entry
|
---|
140 | ;
|
---|
141 | ; Out: CY Error
|
---|
142 | ;
|
---|
143 | ASSUME DS:SV_DATA
|
---|
144 | ASSUME DI:PTR PROCESS
|
---|
145 | PM_OPTIONS PROC NEAR
|
---|
146 | PUSH BX
|
---|
147 | ;
|
---|
148 | ; We're looking at the beginning of an argument (or at the whitespace
|
---|
149 | ; preceding the argument) or at the end of the string. If the argument
|
---|
150 | ; does not start with a dash, return.
|
---|
151 | ;
|
---|
152 | PMO_MAIN: CALL PM_SKIP_BLANKS ; Skip blanks
|
---|
153 | OR AL, AL ; End of line?
|
---|
154 | JZ PMO_END ; Yes -> done
|
---|
155 | CMP AL, "-" ; Option?
|
---|
156 | JNE PMO_ERROR ; No -> error
|
---|
157 | INC SI ; Skip dash
|
---|
158 | ;
|
---|
159 | ; We're looking at the name of an option. It's either preceded by
|
---|
160 | ; a dash or by another option which does not take an argument.
|
---|
161 | ;
|
---|
162 | PMO_OPTION: MOV AL, ES:[SI] ; Get name
|
---|
163 | OR AL, AL ; End of line?
|
---|
164 | JZ PMO_ERROR
|
---|
165 | INC SI ; Skip name
|
---|
166 | LEA BX, OPTIONS_TABLE ; Search table
|
---|
167 | ASSUME BX:PTR DOPTION
|
---|
168 | PMO_FIND: CMP [BX].OPT_NAME, 0 ; End of table?
|
---|
169 | JE PMO_ERROR ; Yes -> error
|
---|
170 | CMP [BX].OPT_NAME, AL ; Matching entry?
|
---|
171 | JE SHORT PMO_FOUND ; Yes -> found
|
---|
172 | ADD BX, SIZE DOPTION ; Move to next table entry
|
---|
173 | JMP PMO_FIND ; Loop through the table
|
---|
174 |
|
---|
175 | ;
|
---|
176 | ; We've found a table entry for the current option.
|
---|
177 | ;
|
---|
178 | PMO_FOUND: CMP [BX].OPT_PM, 0 ; Is it a PM option?
|
---|
179 | JE SHORT PMO_SKIP ; No -> ignore & skip it
|
---|
180 | CMP [BX].OPT_TYPE, OPTT_CALL_ARG ; Call handler?
|
---|
181 | JE SHORT PMO_CALL_ARG ; Yes ->
|
---|
182 | CMP [BX].OPT_TYPE, OPTT_CALL_NOARG ; Call handler?
|
---|
183 | JE SHORT PMO_CALL_NOARG ; Yes ->
|
---|
184 | CMP [BX].OPT_TYPE, OPTT_LFLAG ; Local flag?
|
---|
185 | JE SHORT PMO_LFLAG ; Yes -> set it
|
---|
186 | JMP SHORT PMO_ERROR
|
---|
187 |
|
---|
188 | ;
|
---|
189 | ; Set a local flag. OPT_DATA is the bit mask for P_FLAGS
|
---|
190 | ;
|
---|
191 | PMO_LFLAG: MOVZX EAX, [BX].OPT_DATA ; Get bit mask
|
---|
192 | OR [DI].P_FLAGS, EAX ; and set the flag
|
---|
193 | ;
|
---|
194 | ; Look for next option. The option we've just handled does not take
|
---|
195 | ; an argument, therefore we can cluster options without requiring a
|
---|
196 | ; blank and a dash.
|
---|
197 | ;
|
---|
198 | PMO_NEXT: CMP BYTE PTR ES:[SI], 0 ; End of line?
|
---|
199 | JE SHORT PMO_END ; Yes -> done
|
---|
200 | CMP BYTE PTR ES:[SI], " " ; Blank?
|
---|
201 | JE PMO_MAIN ; Yes -> new argument
|
---|
202 | CMP BYTE PTR ES:[SI], TAB ; Tab?
|
---|
203 | JE PMO_MAIN ; Yes -> new argument
|
---|
204 | JMP PMO_OPTION ; Clustered options
|
---|
205 |
|
---|
206 | ;
|
---|
207 | ; Call handler for an option with argument.
|
---|
208 | ;
|
---|
209 | PMO_CALL_ARG: CALL [BX].OPT_DATA ; Call the handler function
|
---|
210 | JC SHORT PMO_ERROR ; Error -> return
|
---|
211 | CMP BYTE PTR ES:[SI], 0 ; End of line?
|
---|
212 | JE SHORT PMO_END ; Yes -> done
|
---|
213 | CMP BYTE PTR ES:[SI], " " ; Blank?
|
---|
214 | JE SHORT PMO_MAIN ; Yes -> new argument
|
---|
215 | CMP BYTE PTR ES:[SI], TAB ; Tab?
|
---|
216 | JE SHORT PMO_MAIN ; Yes -> new argument
|
---|
217 | JMP SHORT PMO_ERROR ; Error
|
---|
218 |
|
---|
219 | ;
|
---|
220 | ; Call handler for an option without argument.
|
---|
221 | ;
|
---|
222 | PMO_CALL_NOARG: CALL [BX].OPT_DATA ; Call the handler function
|
---|
223 | JC SHORT PMO_ERROR ; Error -> return
|
---|
224 | JMP SHORT PMO_NEXT ; Next option
|
---|
225 |
|
---|
226 | ;
|
---|
227 | ; Skip an option.
|
---|
228 | ;
|
---|
229 | PMO_SKIP: CMP [BX].OPT_TYPE, OPTT_CALL_ARG ; With argument?
|
---|
230 | JNE PMO_NEXT ; No -> simply ignore it
|
---|
231 | ;
|
---|
232 | ; Skip the argument.
|
---|
233 | ;
|
---|
234 | PMO_SKIP_ARG: MOV AL, ES:[SI] ; Fetch next character
|
---|
235 | OR AL, AL ; End of line?
|
---|
236 | JZ SHORT PMO_END ; Yes -> done
|
---|
237 | CMP AL, " " ; Blank?
|
---|
238 | JE PMO_MAIN ; Yes -> new argument
|
---|
239 | CMP AL, TAB ; Tab?
|
---|
240 | JE PMO_MAIN ; Yes -> new argument
|
---|
241 | INC SI ; Skip the character
|
---|
242 | JMP SHORT PMO_SKIP_ARG ; Repeat
|
---|
243 |
|
---|
244 | ;
|
---|
245 | ; Done.
|
---|
246 | ;
|
---|
247 | PMO_END: CLC
|
---|
248 | PMO_RET: POP BX
|
---|
249 | RET
|
---|
250 |
|
---|
251 | ;
|
---|
252 | ; Error.
|
---|
253 | ;
|
---|
254 | PMO_ERROR: STC
|
---|
255 | JMP PMO_RET
|
---|
256 |
|
---|
257 | ASSUME BX:NOTHING
|
---|
258 | PM_OPTIONS ENDP
|
---|
259 |
|
---|
260 | ;
|
---|
261 | ; -C option
|
---|
262 | ;
|
---|
263 | OPTF_COMMIT PROC NEAR
|
---|
264 | MOV EAX, 0 ; Default: 0
|
---|
265 | MOV AL, ES:[SI]
|
---|
266 | CALL PM_OPT_ISEND
|
---|
267 | JE SHORT OC_1
|
---|
268 | CALL PM_OPT_NUMBER
|
---|
269 | JC SHORT OC_ERROR
|
---|
270 | CMP EAX, 512*1024 ; 512 MB maximum
|
---|
271 | JA SHORT OC_ERROR
|
---|
272 | SHL EAX, 10 ; Multiply by 1K
|
---|
273 | ADD EAX, 0FFFH ; Round to multiple
|
---|
274 | AND EAX, NOT 0FFFH ; of page size (4096)
|
---|
275 | OC_1: MOV [DI].P_COMMIT_SIZE, EAX ; Set size
|
---|
276 | OR [DI].P_FLAGS, PF_COMMIT ; Set flag
|
---|
277 | CLC
|
---|
278 | RET
|
---|
279 | OC_ERROR: STC
|
---|
280 | RET
|
---|
281 | OPTF_COMMIT ENDP
|
---|
282 |
|
---|
283 |
|
---|
284 |
|
---|
285 | ;
|
---|
286 | ; -a option
|
---|
287 | ;
|
---|
288 | OPTF_ACCESS PROC NEAR
|
---|
289 | MOV AH, 0
|
---|
290 | OA_1: MOV AL, ES:[SI]
|
---|
291 | MOV DL, HW_ACCESS_CODE
|
---|
292 | CMP AL, "c"
|
---|
293 | JE SHORT OA_2
|
---|
294 | MOV DL, HW_ACCESS_MEM
|
---|
295 | CMP AL, "m"
|
---|
296 | JE SHORT OA_2
|
---|
297 | MOV DL, HW_ACCESS_MEM OR HW_ACCESS_WRITE
|
---|
298 | CMP AL, "w"
|
---|
299 | JE SHORT OA_2
|
---|
300 | MOV DL, HW_ACCESS_IO
|
---|
301 | CMP AL, "i"
|
---|
302 | JE SHORT OA_2
|
---|
303 | CMP AH, 0
|
---|
304 | JE SHORT OA_ERROR
|
---|
305 | OR [DI].P_HW_ACCESS, AH
|
---|
306 | CLC
|
---|
307 | RET
|
---|
308 |
|
---|
309 | OA_2: OR AH, DL
|
---|
310 | INC SI
|
---|
311 | JMP SHORT OA_1
|
---|
312 |
|
---|
313 | OA_ERROR: STC
|
---|
314 | RET
|
---|
315 | OPTF_ACCESS ENDP
|
---|
316 |
|
---|
317 | ;
|
---|
318 | ; -r option
|
---|
319 | ;
|
---|
320 | OPTF_DRIVE PROC NEAR
|
---|
321 | MOV AL, ES:[SI]
|
---|
322 | SUB AL, "A"
|
---|
323 | CMP AL, 26
|
---|
324 | JB SHORT OD_1
|
---|
325 | MOV AL, ES:[SI]
|
---|
326 | SUB AL, "a"
|
---|
327 | CMP AL, 26
|
---|
328 | JAE SHORT OD_ERROR
|
---|
329 | OD_1: ADD AL, "A"
|
---|
330 | MOV [DI].P_DRIVE, AL
|
---|
331 | INC SI
|
---|
332 | CLC
|
---|
333 | RET
|
---|
334 |
|
---|
335 | OD_ERROR: STC
|
---|
336 | RET
|
---|
337 | OPTF_DRIVE ENDP
|
---|
338 |
|
---|
339 | ;
|
---|
340 | ; -s option
|
---|
341 | ;
|
---|
342 | OPTF_STACK PROC NEAR
|
---|
343 | CALL PM_OPT_NUMBER
|
---|
344 | JC SHORT OS_ERROR
|
---|
345 | CMP EAX, 8 ; 8 KB minimum
|
---|
346 | JB SHORT OS_ERROR
|
---|
347 | CMP EAX, 512*1024 ; 512 MB maximum
|
---|
348 | JA SHORT OS_ERROR
|
---|
349 | SHL EAX, 10 ; Multiply by 1K
|
---|
350 | ADD EAX, 0FFFH ; Round to multiple
|
---|
351 | AND EAX, NOT 0FFFH ; of page size (4096)
|
---|
352 | MOV [DI].P_STACK_SIZE, EAX ; Set stack size
|
---|
353 | CLC
|
---|
354 | RET
|
---|
355 | OS_ERROR: STC
|
---|
356 | RET
|
---|
357 | OPTF_STACK ENDP
|
---|
358 |
|
---|
359 | ;
|
---|
360 | ; -t option
|
---|
361 | ;
|
---|
362 | OPTF_TRUNC PROC NEAR
|
---|
363 | XOR EAX, EAX
|
---|
364 | MOV AL, ES:[SI]
|
---|
365 | CALL PM_OPT_ISEND
|
---|
366 | JZ SHORT OT_ALL
|
---|
367 | CMP AL, "-"
|
---|
368 | JE OT_MINUS
|
---|
369 | MOV CH, 1
|
---|
370 | OT_LOOP: SUB AL, "A"
|
---|
371 | CMP AL, 26
|
---|
372 | JB SHORT OT_LETTER
|
---|
373 | MOV AL, ES:[SI]
|
---|
374 | SUB AL, "a"
|
---|
375 | CMP AL, 26
|
---|
376 | JB SHORT OT_LETTER
|
---|
377 | CMP BYTE PTR ES:[SI], "/"
|
---|
378 | JNE SHORT OT_ERROR
|
---|
379 | MOV AL, -1
|
---|
380 | OT_LETTER: INC AL
|
---|
381 | AND AL, 1FH
|
---|
382 | TEST CH, CH
|
---|
383 | JZ OT_CLEAR
|
---|
384 | BTS [DI].P_TRUNC, EAX
|
---|
385 | OT_NEXT: INC SI
|
---|
386 | MOV AL, ES:[SI]
|
---|
387 | CALL PM_OPT_ISEND
|
---|
388 | JNZ OT_LOOP
|
---|
389 | CLC
|
---|
390 | RET
|
---|
391 |
|
---|
392 | OT_CLEAR: BTR [DI].P_TRUNC, EAX
|
---|
393 | JMP OT_NEXT
|
---|
394 |
|
---|
395 | OT_MINUS: INC SI
|
---|
396 | MOV AL, ES:[SI]
|
---|
397 | CALL PM_OPT_ISEND
|
---|
398 | JZ SHORT OT_ZERO
|
---|
399 | MOV CH, 0
|
---|
400 | JMP OT_LOOP
|
---|
401 |
|
---|
402 | OT_ZERO: MOV [DI].P_TRUNC, 0
|
---|
403 | CLC
|
---|
404 | RET
|
---|
405 |
|
---|
406 | OT_ALL: MOV [DI].P_TRUNC, NOT 0
|
---|
407 | CLC
|
---|
408 | RET
|
---|
409 |
|
---|
410 | OT_ERROR: STC
|
---|
411 | RET
|
---|
412 | OPTF_TRUNC ENDP
|
---|
413 |
|
---|
414 | ASSUME DI:NOTHING
|
---|
415 |
|
---|
416 | ;
|
---|
417 | ; Set the ZR flag if AL ends the argument of an option
|
---|
418 | ;
|
---|
419 | PM_OPT_ISEND PROC NEAR
|
---|
420 | TEST AL, AL
|
---|
421 | JZ SHORT POE_RET
|
---|
422 | CMP AL, " "
|
---|
423 | JE SHORT POE_RET
|
---|
424 | CMP AL, TAB
|
---|
425 | POE_RET: RET
|
---|
426 | PM_OPT_ISEND ENDP
|
---|
427 |
|
---|
428 | ;
|
---|
429 | ; Parse a number for options (blank or zero terminated)
|
---|
430 | ;
|
---|
431 | ; In: ES:SI Pointer to string
|
---|
432 | ;
|
---|
433 | ; Out: EAX Number
|
---|
434 | ; CY Error
|
---|
435 | ; ES:SI Points to blank or zero
|
---|
436 | ;
|
---|
437 | PM_OPT_NUMBER PROC NEAR
|
---|
438 | PUSH CX
|
---|
439 | PUSH EDX
|
---|
440 | XOR CX, CX
|
---|
441 | XOR EAX, EAX
|
---|
442 | PON_1: MOVZX EDX, BYTE PTR ES:[SI]
|
---|
443 | OR DL, DL
|
---|
444 | JE SHORT PON_END
|
---|
445 | CMP DL, " "
|
---|
446 | JE SHORT PON_END
|
---|
447 | CMP DL, TAB
|
---|
448 | JE SHORT PON_END
|
---|
449 | SUB DL, "0"
|
---|
450 | CMP DL, 9
|
---|
451 | JA SHORT PON_ERROR
|
---|
452 | IMUL EAX, 10
|
---|
453 | JC SHORT PON_ERROR
|
---|
454 | ADD EAX, EDX
|
---|
455 | JC SHORT PON_ERROR
|
---|
456 | INC SI
|
---|
457 | INC CX
|
---|
458 | JMP PON_1
|
---|
459 | PON_END: OR CX, CX
|
---|
460 | JNZ SHORT PON_RET
|
---|
461 | PON_ERROR: STC
|
---|
462 | PON_RET: POP EDX
|
---|
463 | POP CX
|
---|
464 | RET
|
---|
465 | PM_OPT_NUMBER ENDP
|
---|
466 |
|
---|
467 | SV_CODE ENDS
|
---|
468 |
|
---|
469 |
|
---|
470 | INIT_CODE SEGMENT
|
---|
471 |
|
---|
472 | ASSUME CS:INIT_CODE, DS:NOTHING
|
---|
473 |
|
---|
474 | ;
|
---|
475 | ; Skip over blanks
|
---|
476 | ;
|
---|
477 | ; In: ES:SI Pointer to string
|
---|
478 | ;
|
---|
479 | ; Out: ES:SI Pointer to first non-blank character
|
---|
480 | ; AL First non-blank character
|
---|
481 | ;
|
---|
482 | RM_SKIP_BLANKS PROC NEAR
|
---|
483 | RSB_1: MOV AL, ES:[SI]
|
---|
484 | INC SI
|
---|
485 | CMP AL, " "
|
---|
486 | JE SHORT RSB_1
|
---|
487 | CMP AL, TAB
|
---|
488 | JE SHORT RSB_1
|
---|
489 | DEC SI
|
---|
490 | RET
|
---|
491 | RM_SKIP_BLANKS ENDP
|
---|
492 |
|
---|
493 |
|
---|
494 | ;
|
---|
495 | ; Parse startup options. Jump to USAGE if there is an error.
|
---|
496 | ;
|
---|
497 | ; In: ES:SI Pointer to null-terminated string
|
---|
498 | ;
|
---|
499 | ; Out: ES:SI Pointer to first non-option argument
|
---|
500 | ;
|
---|
501 | ASSUME DS:SV_DATA
|
---|
502 | RM_OPTIONS PROC NEAR
|
---|
503 | ;
|
---|
504 | ; We're looking at the beginning of an argument (or at the whitespace
|
---|
505 | ; preceding the argument) or at the end of the string. If the argument
|
---|
506 | ; does not start with a dash, return.
|
---|
507 | ;
|
---|
508 | RMO_MAIN: CALL RM_SKIP_BLANKS ; Skip blanks
|
---|
509 | CMP AL, "-" ; Option?
|
---|
510 | JNE RMO_END ; No -> done
|
---|
511 | INC SI ; Skip dash
|
---|
512 | ;
|
---|
513 | ; We're looking at the name of an option. It's either preceded by
|
---|
514 | ; a dash or by another option which does not take an argument.
|
---|
515 | ;
|
---|
516 | RMO_OPTION: MOV AL, ES:[SI] ; Get and skip name (skipping 0
|
---|
517 | INC SI ; is benign: we jump to USAGE)
|
---|
518 | LEA BX, OPTIONS_TABLE ; Search table
|
---|
519 | ASSUME BX:PTR DOPTION
|
---|
520 | RMO_FIND: CMP [BX].OPT_NAME, 0 ; End of table?
|
---|
521 | JE SHORT RMO_ERROR ; Yes -> error
|
---|
522 | CMP [BX].OPT_NAME, AL ; Matching entry?
|
---|
523 | JE SHORT RMO_FOUND ; Yes -> found
|
---|
524 | ADD BX, SIZE DOPTION ; Move to next table entry
|
---|
525 | JMP RMO_FIND ; Loop through the table
|
---|
526 |
|
---|
527 | ;
|
---|
528 | ; We've found a table entry for the current option.
|
---|
529 | ;
|
---|
530 | RMO_FOUND: CMP [BX].OPT_PM, 0 ; Is it a PM option?
|
---|
531 | JNE SHORT RMO_SKIP ; Yes -> ignore & skip it
|
---|
532 | CMP [BX].OPT_TYPE, OPTT_CALL_ARG ; Call handler?
|
---|
533 | JE SHORT RMO_CALL_ARG ; Yes ->
|
---|
534 | CMP [BX].OPT_TYPE, OPTT_CALL_NOARG ; Call handler?
|
---|
535 | JE SHORT RMO_CALL_NOARG ; Yes ->
|
---|
536 | CMP [BX].OPT_TYPE, OPTT_GFLAG ; Global flag?
|
---|
537 | JE SHORT RMO_GFLAG ; Yes -> set it
|
---|
538 | RMO_ERROR: JMP USAGE ; Error, abort!
|
---|
539 |
|
---|
540 | ;
|
---|
541 | ; Set a global flag. OPT_DATA is the offset in the SV_DATA segment.
|
---|
542 | ;
|
---|
543 | RMO_GFLAG: MOV DI, [BX].OPT_DATA ; Get pointer
|
---|
544 | MOV BYTE PTR [DI], NOT FALSE ; and set the flag to true
|
---|
545 | ;
|
---|
546 | ; Look for next option. The option we've just handled does not take
|
---|
547 | ; an argument, therefore we can cluster options without requiring a
|
---|
548 | ; blank and a dash.
|
---|
549 | ;
|
---|
550 | RMO_NEXT: CMP BYTE PTR ES:[SI], 0 ; End of line?
|
---|
551 | JE SHORT RMO_END ; Yes -> done
|
---|
552 | CMP BYTE PTR ES:[SI], " " ; Blank?
|
---|
553 | JE RMO_MAIN ; Yes -> new argument
|
---|
554 | CMP BYTE PTR ES:[SI], TAB ; Tab?
|
---|
555 | JE RMO_MAIN ; Yes -> new argument
|
---|
556 | JMP RMO_OPTION ; Clustered options
|
---|
557 |
|
---|
558 | ;
|
---|
559 | ; Call handler for an option with argument.
|
---|
560 | ;
|
---|
561 | RMO_CALL_ARG: CALL [BX].OPT_DATA ; Call the handler function
|
---|
562 | CMP BYTE PTR ES:[SI], 0 ; End of line?
|
---|
563 | JE SHORT RMO_END ; Yes -> done
|
---|
564 | CMP BYTE PTR ES:[SI], " " ; Blank?
|
---|
565 | JE SHORT RMO_MAIN ; Yes -> new argument
|
---|
566 | CMP BYTE PTR ES:[SI], TAB ; Tab?
|
---|
567 | JE SHORT RMO_MAIN ; Yes -> new argument
|
---|
568 | JMP RMO_ERROR ; Error
|
---|
569 |
|
---|
570 | ;
|
---|
571 | ; Call handler for an option without argument.
|
---|
572 | ;
|
---|
573 | RMO_CALL_NOARG: CALL [BX].OPT_DATA ; Call the handler function
|
---|
574 | JMP SHORT RMO_NEXT ; Next option
|
---|
575 |
|
---|
576 | ;
|
---|
577 | ; Skip an option.
|
---|
578 | ;
|
---|
579 | RMO_SKIP: CMP [BX].OPT_TYPE, OPTT_CALL_ARG ; With argument?
|
---|
580 | JNE RMO_NEXT ; No -> simply ignore it
|
---|
581 | ;
|
---|
582 | ; Skip the argument.
|
---|
583 | ;
|
---|
584 | RMO_SKIP_ARG: CALL RM_SKIP_ARG ; Fetch next non-white char
|
---|
585 | OR AL, AL
|
---|
586 | JNZ SHORT RMO_MAIN
|
---|
587 | ;
|
---|
588 | ; Done.
|
---|
589 | ;
|
---|
590 | RMO_END: RET
|
---|
591 | ASSUME BX:NOTHING
|
---|
592 | RM_OPTIONS ENDP
|
---|
593 |
|
---|
594 | ;
|
---|
595 | ; Skip the argument of an option
|
---|
596 | ;
|
---|
597 | ; In: ES:SI Pointer to string
|
---|
598 | ;
|
---|
599 | ; Out: SI Pointer to next non-white character
|
---|
600 | ; AL Next non-white character
|
---|
601 | ;
|
---|
602 | RM_SKIP_ARG PROC NEAR
|
---|
603 | SKIP_LOOP: MOV AL, ES:[SI] ; Fetch next character
|
---|
604 | OR AL, AL ; End of line?
|
---|
605 | JZ SHORT FIN ; Yes -> done
|
---|
606 | CMP AL, " " ; Blank?
|
---|
607 | JE SHORT FIN ; Yes -> done
|
---|
608 | CMP AL, TAB ; Tab?
|
---|
609 | JE SHORT FIN ; Yes -> done
|
---|
610 | INC SI ; Skip the character
|
---|
611 | JMP SHORT SKIP_LOOP ; Repeat
|
---|
612 | FIN: RET
|
---|
613 | RM_SKIP_ARG ENDP
|
---|
614 |
|
---|
615 | ;
|
---|
616 | ; Parse a number for options (blank or zero terminated)
|
---|
617 | ;
|
---|
618 | ; In: ES:SI Pointer to string
|
---|
619 | ;
|
---|
620 | ; Out: EAX Number
|
---|
621 | ; ES:SI Points to blank or zero
|
---|
622 | ;
|
---|
623 | RM_OPT_NUMBER PROC NEAR
|
---|
624 | PUSH CX
|
---|
625 | PUSH EDX
|
---|
626 | XOR CX, CX
|
---|
627 | XOR EAX, EAX
|
---|
628 | RON_1: MOVZX EDX, BYTE PTR ES:[SI]
|
---|
629 | OR DL, DL
|
---|
630 | JE SHORT RON_END
|
---|
631 | CMP DL, " "
|
---|
632 | JE SHORT RON_END
|
---|
633 | SUB DL, "0"
|
---|
634 | CMP DL, 9
|
---|
635 | JA USAGE
|
---|
636 | IMUL EAX, 10
|
---|
637 | JC USAGE
|
---|
638 | ADD EAX, EDX
|
---|
639 | JC USAGE
|
---|
640 | INC SI
|
---|
641 | INC CX
|
---|
642 | JMP RON_1
|
---|
643 | RON_END: OR CX, CX
|
---|
644 | JZ USAGE
|
---|
645 | POP EDX
|
---|
646 | POP CX
|
---|
647 | RET
|
---|
648 | RM_OPT_NUMBER ENDP
|
---|
649 |
|
---|
650 | ;
|
---|
651 | ; -! option
|
---|
652 | ;
|
---|
653 | OPTF_TEST PROC NEAR
|
---|
654 | CALL RM_OPT_NUMBER
|
---|
655 | MOV TEST_FLAGS, EAX
|
---|
656 | RET
|
---|
657 | OPTF_TEST ENDP
|
---|
658 |
|
---|
659 | ;
|
---|
660 | ; -h option
|
---|
661 | ;
|
---|
662 | OPTF_HANDLES PROC NEAR
|
---|
663 | CALL RM_OPT_NUMBER
|
---|
664 | CMP EAX, 10
|
---|
665 | JB USAGE
|
---|
666 | CMP EAX, 65536
|
---|
667 | JA USAGE
|
---|
668 | MOV BX, AX
|
---|
669 | MOV AH, DOS_MAJOR
|
---|
670 | MOV AL, DOS_MINOR
|
---|
671 | CMP AX, 031EH ; 3.30 or later?
|
---|
672 | JB SHORT OH_RET ; No -> ignore
|
---|
673 | MOV AH, 67H ; Set handle count
|
---|
674 | INT 21H
|
---|
675 | OH_RET: RET
|
---|
676 | OPTF_HANDLES ENDP
|
---|
677 |
|
---|
678 | ;
|
---|
679 | ; -m option
|
---|
680 | ;
|
---|
681 | OPTF_MACHINE PROC NEAR
|
---|
682 | CALL RM_OPT_NUMBER
|
---|
683 | CMP EAX, MACH_MAX ; Valid machine code?
|
---|
684 | JA USAGE ; No -> error
|
---|
685 | MOV MACHINE, AL ; Set machine code
|
---|
686 | RET
|
---|
687 | OPTF_MACHINE ENDP
|
---|
688 |
|
---|
689 |
|
---|
690 | ;
|
---|
691 | ; -R option (rsx options, ignored by emx)
|
---|
692 | ;
|
---|
693 | OPTF_RSX PROC NEAR
|
---|
694 | CALL RM_SKIP_ARG ; Skip the argument if any
|
---|
695 | RET
|
---|
696 | OPTF_RSX ENDP
|
---|
697 |
|
---|
698 |
|
---|
699 | ;
|
---|
700 | ; -S option (only available if debugger is loaded)
|
---|
701 | ;
|
---|
702 | OPTF_DEBUG PROC NEAR
|
---|
703 | CMP DEBUG_AVAIL, FALSE ; Debugger loaded?
|
---|
704 | JE USAGE ; No -> error
|
---|
705 | MOV AL, ES:[SI]
|
---|
706 | INC SI
|
---|
707 | MOV DX, 03F8H ; COM1
|
---|
708 | CMP AL, "1"
|
---|
709 | JE SHORT OD_1
|
---|
710 | MOV DX, 02F8H ; COM2
|
---|
711 | CMP AL, "2"
|
---|
712 | JE SHORT OD_1
|
---|
713 | DEC SI ; Back up
|
---|
714 | MOV DEBUG_SER_FLAG, FALSE
|
---|
715 | JMP SHORT OD_2
|
---|
716 |
|
---|
717 | OD_1: MOV DEBUG_SER_PORT, DX ; Set port address
|
---|
718 | MOV DEBUG_SER_FLAG, NOT FALSE
|
---|
719 | OD_2: MOV STEP_FLAG, NOT FALSE
|
---|
720 | RET
|
---|
721 | OPTF_DEBUG ENDP
|
---|
722 |
|
---|
723 |
|
---|
724 | ;
|
---|
725 | ; -V option
|
---|
726 | ;
|
---|
727 | OPTF_VERSION PROC NEAR
|
---|
728 | LEA DX, $TITLE
|
---|
729 | CALL RTEXT
|
---|
730 | RET
|
---|
731 | OPTF_VERSION ENDP
|
---|
732 |
|
---|
733 |
|
---|
734 | ;
|
---|
735 | ;
|
---|
736 | ;
|
---|
737 | USAGE PROC NEAR
|
---|
738 | XOR EDX, EDX
|
---|
739 | LEA DX, $USAGE
|
---|
740 | CALL RTEXT
|
---|
741 | MOV AL, 1
|
---|
742 | JMP EXIT
|
---|
743 | USAGE ENDP
|
---|
744 |
|
---|
745 | INIT_CODE ENDS
|
---|
746 |
|
---|
747 | END
|
---|