summaryrefslogtreecommitdiff
path: root/v4.0/src/DOS/PARSE.ASM
blob: f8de345c5056f535a79cf76379db29b2da5b649c (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
;	SCCSID = @(#)parse.asm	1.2 85/07/23
TITLE PARSE - Parsing system calls for MS-DOS
NAME  PARSE
;
; System calls for parsing command lines
;
;   $PARSE_FILE_DESCRIPTOR
;
;   Modification history:
;
;       Created: ARR 30 March 1983
;               EE PathParse 10 Sept 1983
;

.xlist
;
; get the appropriate segment definitions
;
include dosseg.asm

CODE    SEGMENT BYTE PUBLIC  'CODE'
	ASSUME  SS:DOSGROUP,CS:DOSGROUP

.xcref
INCLUDE DOSSYM.INC
INCLUDE DEVSYM.INC
.cref
.list

BOGUS =FALSE
.lall
	I_Need  chSwitch,BYTE

BREAK <$Parse_File_Descriptor -- Parse an arbitrary string into an FCB>

; Inputs:
;       DS:SI Points to a command line
;       ES:DI Points to an empty FCB
;       Bit 0 of AL = 1 At most one leading separator scanned off
;                   = 0 Parse stops if separator encountered
;       Bit 1 of AL = 1 If drive field blank in command line - leave FCB
;                   = 0  "    "    "     "         "      "  - put 0 in FCB
;       Bit 2 of AL = 1 If filename field blank - leave FCB
;                   = 0  "       "      "       - put blanks in FCB
;       Bit 3 of AL = 1 If extension field blank - leave FCB
;                   = 0  "       "      "        - put blanks in FCB
; Function:
;       Parse command line into FCB
; Returns:
;       AL = 1 if '*' or '?' in filename or extension, 0 otherwise
;       DS:SI points to first character after filename

	procedure   $PARSE_FILE_DESCRIPTOR,NEAR
ASSUME  DS:NOTHING,ES:NOTHING

	invoke  MAKEFCB
	PUSH    SI
	invoke  get_user_stack
	POP     [SI.user_SI]
	return
EndProc $PARSE_FILE_DESCRIPTOR


IF BOGUS
BREAK <$PathParse - Parse a string>

;------------------------------------------------------------------------------
;
; Parse is a string parser.  It copies the next token into a buffer, updates
; the string pointer, and builds a flag word which describes the token.
;
; ENTRY
;       DS:SI - Points to the beginning of the string to be parsed
;       ES:DI - Points to the buffer which will hold the new token
;
; EXIT
;       AX - Flag word
;       DS:SI - String pointer updated to point past the token just found
;       All other registers are unchanged.
;
; All of the isXXXX procedures called by the main routine test a character
; to see if it is of a particular type.  If it is, they store the character
; and return with the ZF set.
;
; CALLS
;       isswit issep ispchr ispsep isinval isdot ischrnull dirdot pasep
;
;
; INTERNAL REGISTER USAGE
;       AH - FF/00  to indicate whether a path token can terminated with a
;            slash or not.
;       AL - Used with lodsb/stosb to transfer and test chars from DS:SI
;       BX - Holds flag word
;       CX - Used with loop/rep and as a work var
;       DX - Used to test the length of names and extensions
;
; EFFECTS
;       The memory pointed to by DI has the next token copied into it.
;
; WARNINGS
;       It is the caller's responsibility to make sure DS:SI does not point
;       to a null string.  If it does, SI is incremented, a null byte is
;       stored at ES:DI, and the routine returns.
;
;------------------------------------------------------------------------------
ParseClassMask          equ     1110000000000000b       ; Token class mask
ParseSwitch             equ     1000000000000000b       ; Switch class
ParseSeparators         equ     0100000000000000b       ; Separator class
ParsePathName           equ     0010000000000000b       ; Path class
ParsePathNameData       equ     0000000000001111b       ; Path token data mask
ParsePathSynErr         equ     0000000000000001b       ; Path has syntax error
ParsePathWild           equ     0000000000000010b       ; Path has wildcards
ParsePathSeparators     equ     0000000000000100b       ; Path has pseparators
ParseInvalidDrive       equ     0000000000001000b       ; Path has invald drive


; Sepchars is a string containing all of the token separator characters
; and is used to test for separators.

Table   segment
Public PRS001S,PRS001E
PRS001S label byte
sepchrs db      9,10,13,' ','+',',',';','='     ; tab cr lf sp + , ; =
seplen  equ     $-sepchrs
PRS001E label byte
table   ends

Procedure $PathParse,NEAR
	assume  ds:nothing,es:nothing
	xor     ah,ah           ; initialize registers and flags
	xor     bx,bx
	cld
	lodsb                   ; used the first byte of the token to
	call    isswit          ; determine its type and call the routine to
	je      switch          ; parse it
	call    issep
	je      separ
	call    ispchr
	je      path
	call    ispsep
	je      path
	call    isdot
	je      path
	call    isinval
	je      inval
	stosb
	jmp     done

inval:  or      bx,ParsePathName        ; an invalid character/path token
	or      bx,ParsePathSynErr      ; was found, set the appropriate
	call    issep                   ; flag bits and parse the rest of
	jne     icont                   ; the token
	dec     di
icont:  dec     si
	jmp     ptosep

switch: mov     bx,ParseSwitch          ; found a switch, set flag and parse
	jmp     ptosep                  ; the rest of it

separ:  mov     bx,ParseSeparators      ; found separator, set flag and parse
seloop: lodsb                           ; everything up to the next non
	call    issep                   ; separator character
	je      seloop
	jmp     bksi

path:   or      bx,ParsePathName        ; found path, set flag
	mov     cx,8                    ; set up to parse a file name
	mov     dx,8
	call    pasep                   ; if the token began with a path
	jne     pcont1                  ; separator or . call rcont which
	not     ah                      ; handles checksfor . and ..
	jmp     rcont
pcont1: cmp     al,'.'
	jne     pcont2
	dec     si
	dec     di
	jmp     rcont
pcont2: cmp     al,'A'                  ; if token may start with a drive
	jge     drive                   ; designator, go to drive. otherwise
	jmp     name1                   ; parse a file name.

drive:  cmp     byte ptr [si],':'       ; if there is a drive designator, parse
	jne     name1                   ; and verify it. otherwise parse a file
	not     ah                      ; name.
	cmp     al,'Z'
	jle     dcont1
	sub     al,' '
dcont1: sub     al,'@'
	invoke  GetthisDrv
	lodsb
	stosb
	jc      dcont2
	jmp     dcont3
dcont2: or      bx,ParseInvalidDrive
dcont3: dec     cx
	lodsb
	call    ispsep
	je      rcont
	dec     si

repeat: mov     al,byte ptr [si-2]      ; repeat and rcont test for //, \\, .,
	call    pasep                   ; and .. and repeatedly calls name
	jne     rcont                   ; and ext until a path token has
	inc     si                      ; been completely parsed.
	jmp     inval
rcont:  call    dirdot
	je      done
	jc      inval
	mov     cx,8
	mov     dx,8
	jmp     name

name1:  dec     cx
name:   lodsb                           ; parse and verify a file name
	call    ispchr
	jne     ncheck
	xor     ah,ah
nloop:  loop    name
	lodsb

ncheck: cmp     ah,0
	jne     ncont
	cmp     cx,dx
	jne     ncont
	jmp     inval
ncont:  call    isdot
	je      ext
	jmp     dcheck

ext:    mov     cx,3                    ; parse and verify a file extension
	mov     dx,3
extl:   lodsb
	call    ispchr
	jne     echeck
eloop:  loop    extl
	lodsb

echeck: cmp     cx,dx
	jne     dcheck
	jmp     inval

dcheck: call    ispsep                  ; do the checks need to make sure
	je      repeat                  ; a file name or extension ended
	call    issep                   ; correctly and checks to see if
	je      bkboth                  ; we're done
	call    ischrnull
	je      done
	jmp     inval

ptosep: lodsb                           ; parse everything to the next separator
	call    issep
	je      bkboth
	call    ischrnull
	je      done
	call    isinval
	jne     ptcont
	or      bx,ParsePathSynErr
ptcont: stosb
	jmp     ptosep

bkboth: dec     di                      ; clean up when the end of the token
bksi:   dec     si                      ; is found, stick a terminating null
done:   xor     al,al                   ; byte at the end of buf, and exit
	stosb
	push    si
	invoke  Get_user_stack
	mov     [si].user_AX,bx
	pop     [si].user_SI
	Transfer sys_ret_ok

Endproc $PathParse

; Is current character the beginning of a switch?

isswit  proc    near
	cmp     al,[chSwitch]
	jne     swret
	stosb
swret:  ret
isswit  endp


; Is the current character a separator?

issep   proc    near
	push    cx
	push    di
	push    es
	mov     cx,cs
	mov     es,cx
	mov     cx,seplen
	mov     di,offset dosgroup:sepchrs
	repne   scasb
	pop     es
	pop     di
	jne     sepret
sepyes: stosb
sepret: pop     cx
	ret
issep   endp


; Is the current character a path character?  If it is a wildcard char too,
;  set that flag.

ispchr  proc    near
	cmp     al,'!'
	je      pcyes
	cmp     al,'#'
	jl      pcret
	cmp     al,'*'
	je      pcwild
	jl      pcyes
	cmp     al,'-'
	je      pcyes
	cmp     al,'0'
	jl      pcret
	cmp     al,'9'
	jle     pcyes
	cmp     al,'?'
	je      pcwild
	jl      pcret
	cmp     al,'Z'
	jle     pcyes
	cmp     al,'^'
	jl      pcret
	cmp     al,'{'
	jle     pcyes
	cmp     al,'}'
	je      pcyes
	cmp     al,'~'
	je      pcyes
	jmp     pcret
pcwild: or      bx,ParsePathWild
pcyes:  stosb
	cmp     al,al
pcret:  ret
ispchr  endp


; Is the current character a path separator?  If so, set that flag after
; storing the byte.

ispsep  proc    near
	call    pasep
	jne     psret
	stosb
	or      bx,ParsePathSeparators
	cmp     al,al
psret:  ret
ispsep  endp


; Set ZF if the character in AL is a path separator.

pasep   proc    near
	cmp     chSwitch,'/'
	je      bkslash
	cmp     al,'/'
	retz
bkslash:cmp     al,'\'
	ret
pasep   endp


; Is the current character invalid?

isinval proc    near
	cmp     al,1
	jl      inret
	cmp     al,8
	jle     inyes
	cmp     al,11
	jl      inret
	cmp     al,13
	jne     incont
	cmp     al,0
	ret
incont: cmp     al,31
	jle     inyes
	cmp     al,'['
	je      inyes
	cmp     al,']'
	je      inyes
	ret
inyes:  cmp     al,al
inret:  ret
isinval endp


; Is the current character a dot?

isdot   proc    near
	cmp     al,'.'
	jne     dotret
	stosb
dotret: ret
isdot   endp


; Is the current character null?  If so, update SI for exiting.

ischrnull  proc    near
	cmp     al,0
	jne     nulret
	dec     si
	cmp     al,al
nulret: ret
ischrnull  endp


; Check for . and ..  Before returning, CF and ZF are set to indicate whether
; the token is invalid (found . or .. followed by an invalid char - CF on),
; we're done (found . or .. followed by null or a separator - ZF on), or the
; token continues (. and .. not found or found and followed by a path
; separator - both flags off).

dirdot  proc    near
	cmp     byte ptr [si], '.'
	jne     diretc
	lodsb
	stosb
	cmp     byte ptr [si],'.'
	jne     dicont
	lodsb
	stosb
dicont: lodsb
	call    ispsep
	je      diretc
	call    issep
	je      dibk
	call    ischrnull
	je      diretd
direti: stc                             ; Invalid return
	ret
dibk:   dec     si
	dec     di
diretd: cmp     al,al                   ; Done return
	ret
diretc: cmp     ah,1                    ; Continue return
	clc
	ret
dirdot  endp
ENDIF

CODE    ENDS
    END