diff options
Diffstat (limited to 'v4.0/src/DOS/PARSE.ASM')
| -rw-r--r-- | v4.0/src/DOS/PARSE.ASM | 447 |
1 files changed, 447 insertions, 0 deletions
diff --git a/v4.0/src/DOS/PARSE.ASM b/v4.0/src/DOS/PARSE.ASM new file mode 100644 index 0000000..f8de345 --- /dev/null +++ b/v4.0/src/DOS/PARSE.ASM | |||
| @@ -0,0 +1,447 @@ | |||
| 1 | ; SCCSID = @(#)parse.asm 1.2 85/07/23 | ||
| 2 | TITLE PARSE - Parsing system calls for MS-DOS | ||
| 3 | NAME PARSE | ||
| 4 | ; | ||
| 5 | ; System calls for parsing command lines | ||
| 6 | ; | ||
| 7 | ; $PARSE_FILE_DESCRIPTOR | ||
| 8 | ; | ||
| 9 | ; Modification history: | ||
| 10 | ; | ||
| 11 | ; Created: ARR 30 March 1983 | ||
| 12 | ; EE PathParse 10 Sept 1983 | ||
| 13 | ; | ||
| 14 | |||
| 15 | .xlist | ||
| 16 | ; | ||
| 17 | ; get the appropriate segment definitions | ||
| 18 | ; | ||
| 19 | include dosseg.asm | ||
| 20 | |||
| 21 | CODE SEGMENT BYTE PUBLIC 'CODE' | ||
| 22 | ASSUME SS:DOSGROUP,CS:DOSGROUP | ||
| 23 | |||
| 24 | .xcref | ||
| 25 | INCLUDE DOSSYM.INC | ||
| 26 | INCLUDE DEVSYM.INC | ||
| 27 | .cref | ||
| 28 | .list | ||
| 29 | |||
| 30 | BOGUS =FALSE | ||
| 31 | .lall | ||
| 32 | I_Need chSwitch,BYTE | ||
| 33 | |||
| 34 | BREAK <$Parse_File_Descriptor -- Parse an arbitrary string into an FCB> | ||
| 35 | |||
| 36 | ; Inputs: | ||
| 37 | ; DS:SI Points to a command line | ||
| 38 | ; ES:DI Points to an empty FCB | ||
| 39 | ; Bit 0 of AL = 1 At most one leading separator scanned off | ||
| 40 | ; = 0 Parse stops if separator encountered | ||
| 41 | ; Bit 1 of AL = 1 If drive field blank in command line - leave FCB | ||
| 42 | ; = 0 " " " " " " - put 0 in FCB | ||
| 43 | ; Bit 2 of AL = 1 If filename field blank - leave FCB | ||
| 44 | ; = 0 " " " - put blanks in FCB | ||
| 45 | ; Bit 3 of AL = 1 If extension field blank - leave FCB | ||
| 46 | ; = 0 " " " - put blanks in FCB | ||
| 47 | ; Function: | ||
| 48 | ; Parse command line into FCB | ||
| 49 | ; Returns: | ||
| 50 | ; AL = 1 if '*' or '?' in filename or extension, 0 otherwise | ||
| 51 | ; DS:SI points to first character after filename | ||
| 52 | |||
| 53 | procedure $PARSE_FILE_DESCRIPTOR,NEAR | ||
| 54 | ASSUME DS:NOTHING,ES:NOTHING | ||
| 55 | |||
| 56 | invoke MAKEFCB | ||
| 57 | PUSH SI | ||
| 58 | invoke get_user_stack | ||
| 59 | POP [SI.user_SI] | ||
| 60 | return | ||
| 61 | EndProc $PARSE_FILE_DESCRIPTOR | ||
| 62 | |||
| 63 | |||
| 64 | IF BOGUS | ||
| 65 | BREAK <$PathParse - Parse a string> | ||
| 66 | |||
| 67 | ;------------------------------------------------------------------------------ | ||
| 68 | ; | ||
| 69 | ; Parse is a string parser. It copies the next token into a buffer, updates | ||
| 70 | ; the string pointer, and builds a flag word which describes the token. | ||
| 71 | ; | ||
| 72 | ; ENTRY | ||
| 73 | ; DS:SI - Points to the beginning of the string to be parsed | ||
| 74 | ; ES:DI - Points to the buffer which will hold the new token | ||
| 75 | ; | ||
| 76 | ; EXIT | ||
| 77 | ; AX - Flag word | ||
| 78 | ; DS:SI - String pointer updated to point past the token just found | ||
| 79 | ; All other registers are unchanged. | ||
| 80 | ; | ||
| 81 | ; All of the isXXXX procedures called by the main routine test a character | ||
| 82 | ; to see if it is of a particular type. If it is, they store the character | ||
| 83 | ; and return with the ZF set. | ||
| 84 | ; | ||
| 85 | ; CALLS | ||
| 86 | ; isswit issep ispchr ispsep isinval isdot ischrnull dirdot pasep | ||
| 87 | ; | ||
| 88 | ; | ||
| 89 | ; INTERNAL REGISTER USAGE | ||
| 90 | ; AH - FF/00 to indicate whether a path token can terminated with a | ||
| 91 | ; slash or not. | ||
| 92 | ; AL - Used with lodsb/stosb to transfer and test chars from DS:SI | ||
| 93 | ; BX - Holds flag word | ||
| 94 | ; CX - Used with loop/rep and as a work var | ||
| 95 | ; DX - Used to test the length of names and extensions | ||
| 96 | ; | ||
| 97 | ; EFFECTS | ||
| 98 | ; The memory pointed to by DI has the next token copied into it. | ||
| 99 | ; | ||
| 100 | ; WARNINGS | ||
| 101 | ; It is the caller's responsibility to make sure DS:SI does not point | ||
| 102 | ; to a null string. If it does, SI is incremented, a null byte is | ||
| 103 | ; stored at ES:DI, and the routine returns. | ||
| 104 | ; | ||
| 105 | ;------------------------------------------------------------------------------ | ||
| 106 | ParseClassMask equ 1110000000000000b ; Token class mask | ||
| 107 | ParseSwitch equ 1000000000000000b ; Switch class | ||
| 108 | ParseSeparators equ 0100000000000000b ; Separator class | ||
| 109 | ParsePathName equ 0010000000000000b ; Path class | ||
| 110 | ParsePathNameData equ 0000000000001111b ; Path token data mask | ||
| 111 | ParsePathSynErr equ 0000000000000001b ; Path has syntax error | ||
| 112 | ParsePathWild equ 0000000000000010b ; Path has wildcards | ||
| 113 | ParsePathSeparators equ 0000000000000100b ; Path has pseparators | ||
| 114 | ParseInvalidDrive equ 0000000000001000b ; Path has invald drive | ||
| 115 | |||
| 116 | |||
| 117 | ; Sepchars is a string containing all of the token separator characters | ||
| 118 | ; and is used to test for separators. | ||
| 119 | |||
| 120 | Table segment | ||
| 121 | Public PRS001S,PRS001E | ||
| 122 | PRS001S label byte | ||
| 123 | sepchrs db 9,10,13,' ','+',',',';','=' ; tab cr lf sp + , ; = | ||
| 124 | seplen equ $-sepchrs | ||
| 125 | PRS001E label byte | ||
| 126 | table ends | ||
| 127 | |||
| 128 | Procedure $PathParse,NEAR | ||
| 129 | assume ds:nothing,es:nothing | ||
| 130 | xor ah,ah ; initialize registers and flags | ||
| 131 | xor bx,bx | ||
| 132 | cld | ||
| 133 | lodsb ; used the first byte of the token to | ||
| 134 | call isswit ; determine its type and call the routine to | ||
| 135 | je switch ; parse it | ||
| 136 | call issep | ||
| 137 | je separ | ||
| 138 | call ispchr | ||
| 139 | je path | ||
| 140 | call ispsep | ||
| 141 | je path | ||
| 142 | call isdot | ||
| 143 | je path | ||
| 144 | call isinval | ||
| 145 | je inval | ||
| 146 | stosb | ||
| 147 | jmp done | ||
| 148 | |||
| 149 | inval: or bx,ParsePathName ; an invalid character/path token | ||
| 150 | or bx,ParsePathSynErr ; was found, set the appropriate | ||
| 151 | call issep ; flag bits and parse the rest of | ||
| 152 | jne icont ; the token | ||
| 153 | dec di | ||
| 154 | icont: dec si | ||
| 155 | jmp ptosep | ||
| 156 | |||
| 157 | switch: mov bx,ParseSwitch ; found a switch, set flag and parse | ||
| 158 | jmp ptosep ; the rest of it | ||
| 159 | |||
| 160 | separ: mov bx,ParseSeparators ; found separator, set flag and parse | ||
| 161 | seloop: lodsb ; everything up to the next non | ||
| 162 | call issep ; separator character | ||
| 163 | je seloop | ||
| 164 | jmp bksi | ||
| 165 | |||
| 166 | path: or bx,ParsePathName ; found path, set flag | ||
| 167 | mov cx,8 ; set up to parse a file name | ||
| 168 | mov dx,8 | ||
| 169 | call pasep ; if the token began with a path | ||
| 170 | jne pcont1 ; separator or . call rcont which | ||
| 171 | not ah ; handles checksfor . and .. | ||
| 172 | jmp rcont | ||
| 173 | pcont1: cmp al,'.' | ||
| 174 | jne pcont2 | ||
| 175 | dec si | ||
| 176 | dec di | ||
| 177 | jmp rcont | ||
| 178 | pcont2: cmp al,'A' ; if token may start with a drive | ||
| 179 | jge drive ; designator, go to drive. otherwise | ||
| 180 | jmp name1 ; parse a file name. | ||
| 181 | |||
| 182 | drive: cmp byte ptr [si],':' ; if there is a drive designator, parse | ||
| 183 | jne name1 ; and verify it. otherwise parse a file | ||
| 184 | not ah ; name. | ||
| 185 | cmp al,'Z' | ||
| 186 | jle dcont1 | ||
| 187 | sub al,' ' | ||
| 188 | dcont1: sub al,'@' | ||
| 189 | invoke GetthisDrv | ||
| 190 | lodsb | ||
| 191 | stosb | ||
| 192 | jc dcont2 | ||
| 193 | jmp dcont3 | ||
| 194 | dcont2: or bx,ParseInvalidDrive | ||
| 195 | dcont3: dec cx | ||
| 196 | lodsb | ||
| 197 | call ispsep | ||
| 198 | je rcont | ||
| 199 | dec si | ||
| 200 | |||
| 201 | repeat: mov al,byte ptr [si-2] ; repeat and rcont test for //, \\, ., | ||
| 202 | call pasep ; and .. and repeatedly calls name | ||
| 203 | jne rcont ; and ext until a path token has | ||
| 204 | inc si ; been completely parsed. | ||
| 205 | jmp inval | ||
| 206 | rcont: call dirdot | ||
| 207 | je done | ||
| 208 | jc inval | ||
| 209 | mov cx,8 | ||
| 210 | mov dx,8 | ||
| 211 | jmp name | ||
| 212 | |||
| 213 | name1: dec cx | ||
| 214 | name: lodsb ; parse and verify a file name | ||
| 215 | call ispchr | ||
| 216 | jne ncheck | ||
| 217 | xor ah,ah | ||
| 218 | nloop: loop name | ||
| 219 | lodsb | ||
| 220 | |||
| 221 | ncheck: cmp ah,0 | ||
| 222 | jne ncont | ||
| 223 | cmp cx,dx | ||
| 224 | jne ncont | ||
| 225 | jmp inval | ||
| 226 | ncont: call isdot | ||
| 227 | je ext | ||
| 228 | jmp dcheck | ||
| 229 | |||
| 230 | ext: mov cx,3 ; parse and verify a file extension | ||
| 231 | mov dx,3 | ||
| 232 | extl: lodsb | ||
| 233 | call ispchr | ||
| 234 | jne echeck | ||
| 235 | eloop: loop extl | ||
| 236 | lodsb | ||
| 237 | |||
| 238 | echeck: cmp cx,dx | ||
| 239 | jne dcheck | ||
| 240 | jmp inval | ||
| 241 | |||
| 242 | dcheck: call ispsep ; do the checks need to make sure | ||
| 243 | je repeat ; a file name or extension ended | ||
| 244 | call issep ; correctly and checks to see if | ||
| 245 | je bkboth ; we're done | ||
| 246 | call ischrnull | ||
| 247 | je done | ||
| 248 | jmp inval | ||
| 249 | |||
| 250 | ptosep: lodsb ; parse everything to the next separator | ||
| 251 | call issep | ||
| 252 | je bkboth | ||
| 253 | call ischrnull | ||
| 254 | je done | ||
| 255 | call isinval | ||
| 256 | jne ptcont | ||
| 257 | or bx,ParsePathSynErr | ||
| 258 | ptcont: stosb | ||
| 259 | jmp ptosep | ||
| 260 | |||
| 261 | bkboth: dec di ; clean up when the end of the token | ||
| 262 | bksi: dec si ; is found, stick a terminating null | ||
| 263 | done: xor al,al ; byte at the end of buf, and exit | ||
| 264 | stosb | ||
| 265 | push si | ||
| 266 | invoke Get_user_stack | ||
| 267 | mov [si].user_AX,bx | ||
| 268 | pop [si].user_SI | ||
| 269 | Transfer sys_ret_ok | ||
| 270 | |||
| 271 | Endproc $PathParse | ||
| 272 | |||
| 273 | ; Is current character the beginning of a switch? | ||
| 274 | |||
| 275 | isswit proc near | ||
| 276 | cmp al,[chSwitch] | ||
| 277 | jne swret | ||
| 278 | stosb | ||
| 279 | swret: ret | ||
| 280 | isswit endp | ||
| 281 | |||
| 282 | |||
| 283 | ; Is the current character a separator? | ||
| 284 | |||
| 285 | issep proc near | ||
| 286 | push cx | ||
| 287 | push di | ||
| 288 | push es | ||
| 289 | mov cx,cs | ||
| 290 | mov es,cx | ||
| 291 | mov cx,seplen | ||
| 292 | mov di,offset dosgroup:sepchrs | ||
| 293 | repne scasb | ||
| 294 | pop es | ||
| 295 | pop di | ||
| 296 | jne sepret | ||
| 297 | sepyes: stosb | ||
| 298 | sepret: pop cx | ||
| 299 | ret | ||
| 300 | issep endp | ||
| 301 | |||
| 302 | |||
| 303 | ; Is the current character a path character? If it is a wildcard char too, | ||
| 304 | ; set that flag. | ||
| 305 | |||
| 306 | ispchr proc near | ||
| 307 | cmp al,'!' | ||
| 308 | je pcyes | ||
| 309 | cmp al,'#' | ||
| 310 | jl pcret | ||
| 311 | cmp al,'*' | ||
| 312 | je pcwild | ||
| 313 | jl pcyes | ||
| 314 | cmp al,'-' | ||
| 315 | je pcyes | ||
| 316 | cmp al,'0' | ||
| 317 | jl pcret | ||
| 318 | cmp al,'9' | ||
| 319 | jle pcyes | ||
| 320 | cmp al,'?' | ||
| 321 | je pcwild | ||
| 322 | jl pcret | ||
| 323 | cmp al,'Z' | ||
| 324 | jle pcyes | ||
| 325 | cmp al,'^' | ||
| 326 | jl pcret | ||
| 327 | cmp al,'{' | ||
| 328 | jle pcyes | ||
| 329 | cmp al,'}' | ||
| 330 | je pcyes | ||
| 331 | cmp al,'~' | ||
| 332 | je pcyes | ||
| 333 | jmp pcret | ||
| 334 | pcwild: or bx,ParsePathWild | ||
| 335 | pcyes: stosb | ||
| 336 | cmp al,al | ||
| 337 | pcret: ret | ||
| 338 | ispchr endp | ||
| 339 | |||
| 340 | |||
| 341 | ; Is the current character a path separator? If so, set that flag after | ||
| 342 | ; storing the byte. | ||
| 343 | |||
| 344 | ispsep proc near | ||
| 345 | call pasep | ||
| 346 | jne psret | ||
| 347 | stosb | ||
| 348 | or bx,ParsePathSeparators | ||
| 349 | cmp al,al | ||
| 350 | psret: ret | ||
| 351 | ispsep endp | ||
| 352 | |||
| 353 | |||
| 354 | ; Set ZF if the character in AL is a path separator. | ||
| 355 | |||
| 356 | pasep proc near | ||
| 357 | cmp chSwitch,'/' | ||
| 358 | je bkslash | ||
| 359 | cmp al,'/' | ||
| 360 | retz | ||
| 361 | bkslash:cmp al,'\' | ||
| 362 | ret | ||
| 363 | pasep endp | ||
| 364 | |||
| 365 | |||
| 366 | ; Is the current character invalid? | ||
| 367 | |||
| 368 | isinval proc near | ||
| 369 | cmp al,1 | ||
| 370 | jl inret | ||
| 371 | cmp al,8 | ||
| 372 | jle inyes | ||
| 373 | cmp al,11 | ||
| 374 | jl inret | ||
| 375 | cmp al,13 | ||
| 376 | jne incont | ||
| 377 | cmp al,0 | ||
| 378 | ret | ||
| 379 | incont: cmp al,31 | ||
| 380 | jle inyes | ||
| 381 | cmp al,'[' | ||
| 382 | je inyes | ||
| 383 | cmp al,']' | ||
| 384 | je inyes | ||
| 385 | ret | ||
| 386 | inyes: cmp al,al | ||
| 387 | inret: ret | ||
| 388 | isinval endp | ||
| 389 | |||
| 390 | |||
| 391 | ; Is the current character a dot? | ||
| 392 | |||
| 393 | isdot proc near | ||
| 394 | cmp al,'.' | ||
| 395 | jne dotret | ||
| 396 | stosb | ||
| 397 | dotret: ret | ||
| 398 | isdot endp | ||
| 399 | |||
| 400 | |||
| 401 | ; Is the current character null? If so, update SI for exiting. | ||
| 402 | |||
| 403 | ischrnull proc near | ||
| 404 | cmp al,0 | ||
| 405 | jne nulret | ||
| 406 | dec si | ||
| 407 | cmp al,al | ||
| 408 | nulret: ret | ||
| 409 | ischrnull endp | ||
| 410 | |||
| 411 | |||
| 412 | ; Check for . and .. Before returning, CF and ZF are set to indicate whether | ||
| 413 | ; the token is invalid (found . or .. followed by an invalid char - CF on), | ||
| 414 | ; we're done (found . or .. followed by null or a separator - ZF on), or the | ||
| 415 | ; token continues (. and .. not found or found and followed by a path | ||
| 416 | ; separator - both flags off). | ||
| 417 | |||
| 418 | dirdot proc near | ||
| 419 | cmp byte ptr [si], '.' | ||
| 420 | jne diretc | ||
| 421 | lodsb | ||
| 422 | stosb | ||
| 423 | cmp byte ptr [si],'.' | ||
| 424 | jne dicont | ||
| 425 | lodsb | ||
| 426 | stosb | ||
| 427 | dicont: lodsb | ||
| 428 | call ispsep | ||
| 429 | je diretc | ||
| 430 | call issep | ||
| 431 | je dibk | ||
| 432 | call ischrnull | ||
| 433 | je diretd | ||
| 434 | direti: stc ; Invalid return | ||
| 435 | ret | ||
| 436 | dibk: dec si | ||
| 437 | dec di | ||
| 438 | diretd: cmp al,al ; Done return | ||
| 439 | ret | ||
| 440 | diretc: cmp ah,1 ; Continue return | ||
| 441 | clc | ||
| 442 | ret | ||
| 443 | dirdot endp | ||
| 444 | ENDIF | ||
| 445 | |||
| 446 | CODE ENDS | ||
| 447 | END | ||