|
|
1.1 ! root 1: page ,132 ! 2: TITLE stdargv - standard & wildcard _setargv routine ! 3: ;*** ! 4: ;stdargv.asm - standard & wildcard _setargv routine ! 5: ; ! 6: ; Copyright (c) 1985-1987, Microsoft Corporation. All rights reserved. ! 7: ; ! 8: ;Purpose: ! 9: ; processes program command line, with or without wildcard expansion ! 10: ; ! 11: ;******************************************************************************* ! 12: ! 13: ! 14: ifdef WILDCARD ! 15: name _setargv ; wildcard _setargv routine ! 16: else ! 17: name stdargv ; standard _setargv routine ! 18: endif ! 19: ! 20: ifdef WILDCARD ! 21: ?DF = 1 ; tell cmacros.inc we want to define our own segments ! 22: endif ! 23: ! 24: include version.inc ! 25: .xlist ! 26: include cmacros.inc ! 27: include msdos.inc ! 28: .list ! 29: ! 30: ifdef WILDCARD ; ********************************************** ! 31: ! 32: createSeg _TEXT, code, word, public, CODE, <> ! 33: createSeg _DATA, data, word, public, DATA, DGROUP ! 34: ! 35: createSeg HDR, nhdr, byte, public, MSG, DGROUP ! 36: createSeg MSG, nmsg, byte, public, MSG, DGROUP ! 37: createSeg PAD, npad, byte, common, MSG, DGROUP ! 38: createSeg EPAD, nepad, byte, common, MSG, DGROUP ! 39: ! 40: defGrp DGROUP ; define DGROUP ! 41: ! 42: dataOFFSET equ offset DGROUP: ! 43: ! 44: ; Message used by ___setargv (wildcard version of __setargv) ! 45: ! 46: sBegin nmsg ! 47: assumes ds,data ! 48: dw 8 ! 49: db 'R6008',13,10,'- not enough space for arguments',13,10,0 ! 50: sEnd ! 51: ! 52: sBegin npad ! 53: assumes ds,data ! 54: dw -1 ! 55: ; no padding for now; ! 56: ; MAX padding would be ! 57: ; db 25 dup(0) ! 58: sEnd ! 59: ! 60: ! 61: externP _cwild ; Wildcard Expander ! 62: externNP _amsg_exit ; error handler (unable to allocate) ! 63: ! 64: endif ; WILDCARD ; ********************************************** ! 65: ! 66: ! 67: sBegin data ! 68: assumes ds,data ! 69: ! 70: ifdef _QC ; [1] ! 71: extrn __QCrtcsip:DWORD ; [1] ! 72: endif ;_QC ; [1] ! 73: ! 74: C_CR equ 0DH ; ASCII carriage return ! 75: ! 76: C_BLANK equ ' ' ; ASCII space character ! 77: C_TAB equ 09h ; ASCII horizontal tab character ! 78: ! 79: C_QUOTE equ '"' ; ASCII (double) Quote Charater ! 80: C_BACKSLASH equ '\' ; ASCII backward slash character ! 81: ! 82: externDP __argv ; argument string array address ! 83: externW __argc ; count of argument strings ! 84: externW _psp ; address of Program Segment Prefix ! 85: externB _osmajor ; address of DOS version (major part) ! 86: externD _pgmptr ; far ptr to name of program ! 87: ! 88: staticCP retadr,0 ; return address ! 89: ! 90: ! 91: ifdef WILDCARD ; ********************************************** ! 92: ! 93: dta_flag db 0 ; Has DMA been set yet? ! 94: ! 95: file_reserv db 21 dup (0) ! 96: file_attrib db 0 ! 97: file_time dw 0 ! 98: file_date dw 0 ! 99: file_sizel dw 0 ! 100: file_sizeh dw 0 ! 101: file_name db 13 dup (0) ! 102: ! 103: endif ; WILDCARD ; ********************************************** ! 104: ! 105: sEnd ! 106: ! 107: ; **************************************** ! 108: ! 109: jmps MACRO target ! 110: jmp short target ! 111: ENDM ! 112: ! 113: lje MACRO target ! 114: LOCAL temp ! 115: jne temp ! 116: jmp target ! 117: temp: ! 118: ENDM ! 119: ! 120: ifdef IBMC20 ! 121: ! 122: DELIM MACRO target ! 123: cmp al,C_CR ;; Test for end-of-line character ! 124: je target ! 125: ENDM ! 126: ! 127: LDELIM MACRO target ! 128: cmp al,C_CR ;; Test for end-of-line character ! 129: lje target ! 130: ENDM ! 131: ! 132: else ; IBMC20 ! 133: ! 134: DELIM MACRO target ! 135: cmp al,C_CR ;; Test for end-of-line character ! 136: je target ! 137: or al,al ;; Either Carriage Return or Null ! 138: je target ! 139: ENDM ! 140: ! 141: LDELIM MACRO target ! 142: cmp al,C_CR ;; Test for end-of-line character ! 143: lje target ! 144: or al,al ;; Either Carriage Return or Null ! 145: lje target ! 146: ENDM ! 147: ! 148: endif ; IBMC20 ! 149: ! 150: ; **************************************** ! 151: ! 152: sBegin code ! 153: ! 154: assumes ds,data ! 155: assumes ss,data ! 156: assumes cs,code ! 157: ! 158: page ! 159: ;*** ! 160: ;_setargv, __setargv - set up "argc" and "argv" for C programs ! 161: ; ! 162: ;Purpose: ! 163: ; Gets the command line from the PSP and moves the information ! 164: ; to its place on the stack. ! 165: ; ! 166: ; SIDE EFFECTS: ! 167: ; Allocates space on the stack for the argument strings ! 168: ; and a list of pointers to them. ! 169: ; ASSUMPTIONS: ! 170: ; Under DOS 2, there is no argv[0] string, so "C" is used. ! 171: ; Under DOS 3 and later, the argv[0] string is found in the ! 172: ; environment segment, after the double null that terminates ! 173: ; that segment and after a word of value 1. The rest of the ! 174: ; command line is found in the Program Segment Prefix at ! 175: ; offset 81H, and is terminated by a 0DH. This command "tail" ! 176: ; cannot be greater than 126 bytes in length. ! 177: ; ! 178: ; Quote marks and backslashes are treated specially. A quoted ! 179: ; string is passed as a single argument, not including the ! 180: ; opening and closing quote characters. A quote may be imbedded ! 181: ; in a string by placing an odd number of backslashes (`\') ! 182: ; before it. Each pair of backslashes which precedes a quote ! 183: ; results in a single backslash in the resultant string. ! 184: ; An even number of backslashes followed by a quote results in ! 185: ; half that many backslashes, and the quote begins or ends the ! 186: ; quoted part of the string as is appropriate. Backslashes not ! 187: ; followed by a quote are treated normally. ! 188: ; ! 189: ; [""] ==> [] ! 190: ; [\"] ==> ["] ! 191: ; [" \" "] == [ " ] ! 192: ; [" \\"] == [ \] ! 193: ; [" \\ "] == [ \\ ] ! 194: ; [" \\\" "] == [ \" ] ! 195: ; etc. ! 196: ; ["one two three"] ==> [one two three] ! 197: ; [one" two "three] ==> [one two three] ! 198: ; [o"ne two t"hree] ==> [one two three] ! 199: ; ["one \"two\" three"] ==> [one "two" three] ! 200: ; ["x\\\"x"] ==> [x\"x] ! 201: ; ! 202: ;Entry: ! 203: ; ! 204: ;Exit: ! 205: ; "argv" points to a null-terminated list of pointers to ASCIZ ! 206: ; strings, each of which is an argument from the command line. ! 207: ; "argc" is the number of arguments. The strings are copied from ! 208: ; the Program Segment Prefix into space allocated on the stack. ! 209: ; The list of pointers is also located on the stack. ! 210: ; ! 211: ;Uses: ! 212: ; All registers except DS, SS, and BP are modified ! 213: ; Note especially that SI and DI are NOT preserved! ! 214: ; ! 215: ;Exceptions: ! 216: ; ! 217: ;******************************************************************************* ! 218: ! 219: ifdef WILDCARD ; ********************************************** ! 220: ! 221: labelP <PUBLIC,__setargv> ! 222: ! 223: else ; ********************************************** ! 224: ! 225: labelP <PUBLIC,_setargv> ! 226: ! 227: endif ; WILDCARD ; ********************************************** ! 228: ! 229: pop word ptr [retadr] ; get return address (offset) ! 230: if sizeC ! 231: pop word ptr [retadr+2] ; get return address (segment) ! 232: endif ! 233: mov dx,2 ! 234: cmp byte ptr [_osmajor],dl ; 2 bytes if DOS version = 2.X ! 235: je dos_two ! 236: ! 237: mov es,_psp ! 238: mov es,es:[DOS_envp] ; get environment segment ! 239: mov word ptr [_pgmptr+2],es ; set global variable "_pgmptr" ! 240: xor ax,ax ! 241: cwd ; DX=0 ! 242: mov cx,8000H ! 243: xor di,di ; scan from beginning of environment ! 244: find_env_end: ! 245: repne scasb ! 246: scasb ! 247: jne find_env_end ! 248: ; ! 249: inc di ; skip count word (always 0x0001) ! 250: inc di ! 251: mov word ptr [_pgmptr],di ; set global variable "_pgmptr" ! 252: mov cx,-1 ! 253: repne scasb ! 254: not cx ! 255: mov dx,cx ; DX=number of bytes in argv[0] ! 256: dos_two: ! 257: mov di,1 ; always start with one argument ! 258: mov si,81H ! 259: mov ds,_psp ! 260: assumes ds,nothing ! 261: ;* ! 262: ;* Count the command tail arguments ! 263: ;* ! 264: ; ! 265: ; DI will count the number of arguments ! 266: ; DX will count the number of bytes needed for the arguments ! 267: ; (not including the null terminators) ! 268: ; ! 269: arg100: ! 270: arg110: ! 271: lodsb ! 272: cmp al,C_BLANK ! 273: je arg110 ! 274: cmp al,C_TAB ! 275: je arg110 ! 276: ! 277: DELIM arg400 ! 278: ! 279: inc di ; Another argument ! 280: ; ! 281: ; Parse an argument ! 282: ; ! 283: arg200: ! 284: dec si ; back up to reload character ! 285: arg210: ! 286: lodsb ! 287: ! 288: cmp al,C_BLANK ! 289: je arg100 ! 290: cmp al,C_TAB ! 291: je arg100 ; white space terminates argument ! 292: ! 293: DELIM arg400 ! 294: ! 295: cmp al,C_QUOTE ! 296: je arg310 ! 297: ! 298: cmp al,C_BACKSLASH ! 299: je arg220 ! 300: ! 301: inc dx ! 302: jmps arg210 ! 303: ; ! 304: ; Count backslashes ! 305: ; ! 306: arg220: ! 307: xor cx,cx ! 308: arg221: ! 309: inc cx ; CX counts the backslashes ! 310: lodsb ! 311: cmp al,C_BACKSLASH ! 312: je arg221 ! 313: ; ! 314: cmp al,C_QUOTE ! 315: je arg230 ! 316: ! 317: add dx,cx ; not followed by `"' -- treat `\'s normally ! 318: jmp arg200 ! 319: ; ! 320: arg230: ! 321: mov ax,cx ! 322: shr cx,1 ! 323: adc dx,cx ; add 1 for every pair of backslashes ! 324: test al,1 ; plus 1 for the " if odd number of \ ! 325: jnz arg210 ; " was escaped with a \ ! 326: jmps arg310 ; " opens a quoted substring ! 327: ; ! 328: ; Enter a quoted string ! 329: ; ! 330: arg300: ! 331: dec si ; back up to reload character ! 332: arg310: ! 333: lodsb ! 334: ! 335: DELIM arg400 ! 336: ! 337: cmp al,C_QUOTE ! 338: je arg210 ; end of quoted portion of string ! 339: ! 340: cmp al,C_BACKSLASH ! 341: je arg320 ! 342: ! 343: inc dx ! 344: jmp arg310 ! 345: ; ! 346: ; Count backslashes ! 347: ; ! 348: arg320: ! 349: xor cx,cx ! 350: arg321: ! 351: inc cx ; CX counts the backslashes ! 352: lodsb ! 353: cmp al,C_BACKSLASH ! 354: je arg321 ! 355: ; ! 356: cmp al,C_QUOTE ! 357: je arg330 ! 358: ! 359: add dx,cx ; not followed by `"' -- treat `\'s normally ! 360: jmp arg300 ! 361: ; ! 362: arg330: ! 363: mov ax,cx ! 364: shr cx,1 ! 365: adc dx,cx ; add 1 for every pair of backslashes ! 366: test al,1 ; plus 1 for the " if odd number of \ ! 367: jnz arg310 ; " was escaped with a \ ! 368: jmps arg210 ; " closes a quoted substring ! 369: ; ! 370: ; Command line is fully parsed - compute number of bytes needed ! 371: ; ! 372: arg400: ! 373: ; ! 374: ; Number of bytes needed = ! 375: ; Number of bytes used to make strings + ! 376: ; Number of bytes used to terminate strings + ! 377: ; sizeof(DATAPTR) * ( number of arguments + 1 ) ! 378: ; ! 379: push ss ! 380: pop ds ; Restore DS = DGROUP ! 381: assumes ds,data ! 382: ! 383: mov __argc,di ; Store number of arguments ! 384: ! 385: add dx,di ; add in terminator bytes ! 386: ifdef WILDCARD ! 387: add dx,di ; add in Wildcard flag bytes ! 388: endif ! 389: inc di ; add one for NULL pointer ! 390: shl di,1 ! 391: if sizeD ! 392: shl di,1 ! 393: endif ! 394: add dx,di ; add space for pointers to space for chars ! 395: ! 396: and dl,not 1 ; Round up to an even number of bytes ! 397: ; ! 398: ; Allocate space on the stack ! 399: ; ! 400: ; DX is the total number of bytes needed for strings and pointers ! 401: ; DI is the number of bytes needed for the pointers ! 402: ; ! 403: sub sp,dx ! 404: mov ax,sp ! 405: ! 406: mov word ptr (__argv),ax ! 407: if sizeD ! 408: mov word ptr (__argv+2),ds ! 409: endif ! 410: ; ! 411: ; Copy argument strings and addresses onto heap/stack ! 412: ; Address table is on the top, strings below that ! 413: ; ! 414: mov bx,ax ! 415: add di,bx ! 416: ! 417: push ss ; ES=SS ! 418: pop es ; ES:DI is where the string copies will go ! 419: assumes es,data ! 420: ; ! 421: ; DS:SI points to the argv[0] ! 422: ; ! 423: ; ES:BX points to where argv[0],argv[1],argv[2],... go ! 424: ; ES:DI points to where *argv[0],*argv[1],*argv[2],... go ! 425: ; For wildcard version only: ! 426: ; ES:DX points to the wildcard flag character (prepended to argument) ! 427: ; during the creation of each argument ! 428: ; ! 429: mov ss:[bx],di ; argv[i] - offset part ! 430: if sizeD ! 431: mov ss:[bx+2],ss ; argv[i] - segment part ! 432: add bx,4 ! 433: else ! 434: inc bx ! 435: inc bx ! 436: endif ! 437: ! 438: lds si,[_pgmptr] ; copy argv[0], either fake or from env seg ! 439: assumes ds,nothing ! 440: ! 441: ifdef WILDCARD ! 442: movsb ! 443: dec si ; copy first character as quote flag ! 444: endif ! 445: ! 446: copy_argv0: ! 447: lodsb ! 448: stosb ! 449: or al,al ! 450: jnz copy_argv0 ! 451: ; ! 452: ; DS:SI points to the raw command tail string ! 453: ; ! 454: mov si,81H ; address of strings ! 455: mov ds,ss:[_psp] ; DS:SI is where the source strings are ! 456: assumes ds,nothing ! 457: ! 458: jmps arg510 ! 459: ; ! 460: ; Skip blanks ! 461: ; ! 462: arg500: ! 463: xor ax,ax ! 464: stosb ! 465: arg510: ! 466: lodsb ! 467: cmp al,C_BLANK ! 468: je arg510 ! 469: cmp al,C_TAB ! 470: je arg510 ! 471: ! 472: LDELIM arg810 ! 473: ! 474: mov ss:[bx],di ! 475: if sizeD ! 476: mov ss:[bx+2],ss ! 477: add bx,4 ! 478: else ! 479: inc bx ! 480: inc bx ! 481: endif ! 482: ! 483: ifdef WILDCARD ! 484: mov dx,di ! 485: stosb ; initialize wildcard flag ! 486: endif ! 487: ; ! 488: ; ! 489: ; Parse an argument ! 490: ; ! 491: arg600: ! 492: dec si ; back up to reload character ! 493: arg610: ! 494: lodsb ! 495: ! 496: cmp al,C_BLANK ! 497: je arg500 ! 498: cmp al,C_TAB ! 499: je arg500 ; white space terminates argument ! 500: ! 501: DELIM arg800 ! 502: ! 503: cmp al,C_QUOTE ! 504: je arg710x ! 505: ! 506: cmp al,C_BACKSLASH ! 507: je arg620 ! 508: ! 509: stosb ! 510: jmps arg610 ! 511: ; ! 512: ; Count backslashes ! 513: ; ! 514: arg620: ! 515: xor cx,cx ! 516: arg621: ! 517: inc cx ; CX counts the backslashes ! 518: lodsb ! 519: cmp al,C_BACKSLASH ! 520: je arg621 ! 521: ; ! 522: cmp al,C_QUOTE ! 523: je arg630 ! 524: ! 525: mov al,C_BACKSLASH ! 526: rep stosb ; not followed by `"' -- treat `\'s normally ! 527: jmp arg600 ! 528: ; ! 529: arg630: ! 530: mov al,C_BACKSLASH ! 531: shr cx,1 ! 532: rep stosb ! 533: jnc arg710x ; " opens a quoted substring ! 534: mov al,C_QUOTE ! 535: stosb ! 536: jmp arg610 ; " was escaped with a \ ! 537: ; ! 538: ; Enter a quoted string ! 539: ; ! 540: ifdef WILDCARD ! 541: arg710x: ! 542: inc si ; undoes the "DEC SI" between arg700 and arg710 ! 543: endif ! 544: ! 545: arg700x: ! 546: ! 547: ifdef WILDCARD ! 548: xchg dx,di ; set the wildcard flag character to `"' ! 549: mov al,C_QUOTE ! 550: stosb ! 551: dec di ! 552: xchg dx,di ! 553: endif ! 554: ! 555: arg700: ! 556: dec si ; back up to reload character ! 557: ! 558: ifndef WILDCARD ! 559: arg710x: ! 560: endif ! 561: ! 562: arg710: ! 563: lodsb ! 564: ! 565: DELIM arg800 ! 566: ! 567: cmp al,C_QUOTE ! 568: je arg610 ; end of quoted portion of string ! 569: ! 570: cmp al,C_BACKSLASH ! 571: je arg720 ! 572: ! 573: stosb ! 574: jmp arg710 ! 575: ; ! 576: ; Count backslashes ! 577: ; ! 578: arg720: ! 579: xor cx,cx ! 580: arg721: ! 581: inc cx ; CX counts the backslashes ! 582: lodsb ! 583: cmp al,C_BACKSLASH ! 584: je arg721 ! 585: ; ! 586: cmp al,C_QUOTE ! 587: je arg730 ! 588: ! 589: mov al,C_BACKSLASH ! 590: rep stosb ; not followed by `"' -- treat `\'s normally ! 591: jmp arg700x ! 592: ; ! 593: arg730: ! 594: mov al,C_BACKSLASH ! 595: shr cx,1 ! 596: rep stosb ; store 1 for every pair of backslashes ! 597: jnc arg610 ; " closes a quoted substring ! 598: mov al,C_QUOTE ; " was escaped with a \ ! 599: stosb ! 600: jmps arg710x ! 601: ; ! 602: ; Terminate last argument string, terminate list of argument pointers ! 603: ; ! 604: arg800: ! 605: xor ax,ax ! 606: stosb ; null-terminate final argument ! 607: arg810: ! 608: push ss ! 609: pop ds ! 610: assumes ds,data ! 611: ! 612: mov word ptr [bx],0 ; add null pointer to __argv[] ! 613: if sizeD ! 614: mov word ptr [bx+2],0 ! 615: endif ! 616: ! 617: ifndef WILDCARD ! 618: jmp [retadr] ; THE END ! 619: else ! 620: call _cwild ! 621: test ax,ax ! 622: jz no_arg_err ! 623: ! 624: ifdef _QC ; [1] ! 625: mov ds,cs:[$F_PSP] ;[2] get PSP ! 626: mov ax,ds:[PSP_DGROUP_SEG] ;[2] get DGROUP ! 627: mov ds, ax ;[2] ds = DGROUP ! 628: ! 629: mov ax, word ptr [retadr] ; [1] Offset... ! 630: mov word ptr [__QCrtcsip], ax ; [1] ...save ! 631: if sizeC ! 632: mov ax, word ptr [retadr+2] ; [1] Segment... ! 633: mov word ptr [__QCrtcsip+2], ax ; [1] ...save ! 634: else ; [1] ! 635: mov word ptr [__QCrtcsip+2], cs ; [1] (Near call) ! 636: endif ; [1] ! 637: endif ;_QC ; [1] (_QC) ! 638: ! 639: mov ax,8 ! 640: jmp _amsg_exit ; ! 641: ! 642: no_arg_err: ! 643: jmp [retadr] ! 644: ! 645: page ! 646: ;*** ! 647: ;_find(dir) - find first matching file name against pattern "dir" ! 648: ; ! 649: ;Purpose: ! 650: ; _find(dir) - Find first matching file name against pattern "dir" ! 651: ; If dir == NULL, then get next match for current pattern. ! 652: ; ! 653: ;Entry: ! 654: ; dir = DATA PTR of pattern to match ! 655: ; ! 656: ;Exit: ! 657: ; AX = the address of a static area containing the file name if a ! 658: ; match was found. Returns NULL if no match was found. ! 659: ; ! 660: ;Uses: ! 661: ; CX,DX, [dta_flag]. ! 662: ; ! 663: ;Exceptions: ! 664: ; ! 665: ;******************************************************************************* ! 666: ! 667: cProc _find,<PUBLIC> ! 668: parmdp dir ! 669: cBegin ! 670: test [dta_flag],-1 ! 671: jnz not_very_first ! 672: ! 673: mov [dta_flag],-1 ! 674: ; ! 675: ; Set DTA, where the match structure is returned ! 676: ; ! 677: mov dx,dataOFFSET file_reserv ! 678: callos setdma ! 679: ; ! 680: not_very_first: ! 681: mov ah,DOS_findnext ; assume not first ! 682: ! 683: if sizeD ! 684: push ds ! 685: lds dx,dir ! 686: mov cx,ds ! 687: jcxz find_next ! 688: else ! 689: mov dx,dir ! 690: test dx,dx ! 691: jz find_next ! 692: endif ! 693: mov cx,A_D ; match directories as well as files ! 694: mov ah,DOS_findfirst ! 695: find_next: ! 696: callos ! 697: if sizeD ! 698: pop ds ! 699: endif ! 700: mov ax,dataOFFSET file_name ! 701: if sizeD ! 702: mov dx,ds ! 703: endif ! 704: jnc retname ! 705: ! 706: xor ax,ax ; return 0 for no more matches ! 707: if sizeD ! 708: cwd ! 709: endif ! 710: ! 711: retname: ! 712: ! 713: cEnd ! 714: ! 715: endif ; WILDCARD ; *********************************************** ! 716: ! 717: sEnd code ! 718: ! 719: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.