|
|
1.1 ! root 1: TITLE stdargv.asm - OS/2 standard & wildcard _setargv routine ! 2: ;*** ! 3: ;5stdargv.asm - OS/2 standard & wildcard _setargv routine ! 4: ; ! 5: ; Copyright (c) 1985-1987, Microsoft Corporation. All rights reserved. ! 6: ; ! 7: ;Purpose: ! 8: ; processes program command line, with or without wildcard expansion ! 9: ; ! 10: ;******************************************************************************* ! 11: ! 12: ifdef WILDCARD ! 13: name _setargv ; wildcard _setargv routine ! 14: else ! 15: name stdargv ; standard _setargv routine ! 16: endif ! 17: ! 18: include version.inc ! 19: .xlist ! 20: include cmacros.inc ! 21: include msdos.inc ! 22: .list ! 23: ! 24: sBegin data ! 25: assumes ds,data ! 26: ! 27: C_BLANK equ ' ' ; ASCII space character ! 28: C_TAB equ 09h ; ASCII horizontal tab character ! 29: ! 30: C_QUOTE equ '"' ; ASCII (double) Quote Charater ! 31: C_BACKSLASH equ '\' ; ASCII backward slash character ! 32: ! 33: externDP __argv ; argument string array address ! 34: externW __argc ; count of argument strings ! 35: externW _aenvseg ; environment segment ! 36: externW _acmdln ; offset of command line in env. seg. ! 37: externD _pgmptr ; far pointer to program name ! 38: ! 39: staticW cmdstart,0 ; start of command line string ! 40: staticCP retadr,0 ; return address ! 41: ! 42: ifdef WILDCARD ! 43: ! 44: staticW findhandle,1 ; handle used for wildcard matching ! 45: ! 46: FileFindBuf struc ! 47: create_date dw ? ;* date of file creation ! 48: create_time dw ? ;* time of file creation ! 49: access_date dw ? ;* date of last access ! 50: access_time dw ? ;* time of last access ! 51: write_date dw ? ;* date of last write ! 52: write_time dw ? ;* time of last write ! 53: file_size dd ? ;* file size (end of data) ! 54: falloc_size dd ? ;* file allocated size ! 55: attributes dw ? ;* attributes of the file ! 56: string_len db ? ;* returned length of ascii name str. ! 57: file_name db 13 dup (?) ;* name string ! 58: FileFindBuf ends ! 59: ! 60: findbuf FileFindBuf <> ;* struct FileFindBuf findbuf; ! 61: ! 62: endif ; WILDCARD ! 63: ! 64: sEnd data ! 65: ! 66: ;========================================= ! 67: ! 68: ifdef WILDCARD ! 69: extrn DOSFINDFIRST:far ! 70: extrn DOSFINDNEXT:far ! 71: externP _cwild ; Wildcard Expander ! 72: endif ! 73: ! 74: ;========================================= ! 75: ! 76: jmps MACRO target ! 77: jmp short target ! 78: ENDM ! 79: ! 80: lje MACRO target ! 81: LOCAL temp ! 82: jne temp ! 83: jmp target ! 84: temp: ! 85: ENDM ! 86: ! 87: DELIM MACRO ! 88: or al,al ;; Test for end-of-line character (null) ! 89: ENDM ! 90: ! 91: ;========================================= ! 92: ! 93: ! 94: sBegin code ! 95: ! 96: externNP _stdalloc ; routine to allocate heap memory ! 97: externNP _amsg_exit ; error handler (unable to allocate) ! 98: ! 99: assumes ds,data ! 100: assumes ss,data ! 101: assumes cs,code ! 102: ! 103: page ! 104: ;*** ! 105: ;_setargv, __setargv - set up "argc" and "argv" for C programs ! 106: ; ! 107: ;Purpose: ! 108: ; Read the command line and create the argv array for C ! 109: ; programs. ! 110: ; ! 111: ;Entry: ! 112: ; Arguments are retrieved from the program command line. ! 113: ; ! 114: ;Exit: ! 115: ; "argv" points to a null-terminated list of pointers to ASCIZ ! 116: ; strings, each of which is an argument from the command line. ! 117: ; "argc" is the number of arguments. The strings are copied from ! 118: ; the environment segment into space allocated on the heap/stack. ! 119: ; The list of pointers is also located on the heap or stack. ! 120: ; ! 121: ;Uses: ! 122: ; ! 123: ;Exceptions: ! 124: ; ! 125: ;******************************************************************************* ! 126: ! 127: ! 128: ifdef WILDCARD ; ********************************************** ! 129: ! 130: labelP <PUBLIC,__setargv> ! 131: ! 132: else ; ********************************************** ! 133: ! 134: labelP <PUBLIC,_setargv> ! 135: ! 136: endif ; WILDCARD ; ********************************************** ! 137: ! 138: pop word ptr [retadr] ; get return address (offset) ! 139: ! 140: if sizeC ! 141: pop word ptr [retadr+2] ; get return address (segment) ! 142: endif ! 143: mov ax,_acmdln ! 144: mov ds,_aenvseg ! 145: assumes ds,nothing ! 146: ! 147: mov si,ax ! 148: ; ! 149: ; If there is no argument string, use the ! 150: ; program name for the command line string. ! 151: ; Scan back for the null before "PgmPtr" ! 152: ; ! 153: find_argv0: ! 154: dec si ! 155: jz found_argv0 ! 156: cmp byte ptr ds:[si-1],0 ! 157: jne find_argv0 ! 158: found_argv0: ! 159: mov word ptr [_pgmptr],si ! 160: mov word ptr [_pgmptr+2],ds ! 161: xchg ax,si ; restore SI to [_acmdln] ! 162: test byte ptr ds:[si],-1 ! 163: jnz store_cmdstart ! 164: xchg ax,si ; use PgmPtr instead of ArgPtr ! 165: store_cmdstart: ! 166: mov [cmdstart],si ! 167: ! 168: xor dx,dx ; Start with zero bytes ! 169: mov di,1 ; Start with one arguments ! 170: count_argv0: ! 171: lodsb ! 172: inc dx ; count each byte in argv[0] ! 173: or al,al ; including the terminator ! 174: jnz count_argv0 ! 175: ;* ! 176: ;* Count the command line arguments ! 177: ;* ! 178: ;* ... previous environment strings ... ! 179: ;* null byte (end of last environment string) ! 180: ;* null byte (end of environment) ! 181: ;* program name string ! 182: ;* null byte ! 183: ;* DS:SI ==> raw command line string ! 184: ;* null byte ! 185: ;* null byte ! 186: ;* ! 187: ;* DI will count the number of arguments ! 188: ;* ! 189: ;* DX will count the number of bytes needed to ! 190: ;* store the arguments themselves, incl. final nulls ! 191: ;* ! 192: ;* ! 193: ;* Count the command tail arguments ! 194: ;* ! 195: ; ! 196: ; DI will count the number of arguments ! 197: ; DX will count the number of bytes needed for the arguments ! 198: ; (not including the null terminators) ! 199: ; ! 200: arg100: ! 201: arg110: ! 202: lodsb ! 203: cmp al,C_BLANK ! 204: je arg110 ! 205: cmp al,C_TAB ! 206: je arg110 ! 207: ! 208: DELIM ! 209: je arg400 ! 210: ! 211: inc di ; Another argument ! 212: ; ! 213: ; Parse an argument ! 214: ; ! 215: arg200: ! 216: dec si ; back up to reload character ! 217: arg210: ! 218: lodsb ! 219: ! 220: cmp al,C_BLANK ! 221: je arg100 ! 222: cmp al,C_TAB ! 223: je arg100 ; white space terminates argument ! 224: ! 225: DELIM ! 226: je arg400 ! 227: ! 228: cmp al,C_QUOTE ! 229: je arg310 ! 230: ! 231: cmp al,C_BACKSLASH ! 232: je arg220 ! 233: ! 234: inc dx ! 235: jmps arg210 ! 236: ; ! 237: ; Count backslashes ! 238: ; ! 239: arg220: ! 240: xor cx,cx ! 241: arg221: ! 242: inc cx ; CX counts the backslashes ! 243: lodsb ! 244: cmp al,C_BACKSLASH ! 245: je arg221 ! 246: ; ! 247: cmp al,C_QUOTE ! 248: je arg230 ! 249: ! 250: add dx,cx ; not followed by `"' -- treat `\'s normally ! 251: jmp arg200 ! 252: ; ! 253: arg230: ! 254: mov ax,cx ! 255: shr cx,1 ! 256: adc dx,cx ; add 1 for every pair of backslashes ! 257: test al,1 ; plus 1 for the " if odd number of \ ! 258: jnz arg210 ; " was escaped with a \ ! 259: jmps arg310 ; " opens a quoted substring ! 260: ; ! 261: ; Enter a quoted string ! 262: ; ! 263: arg300: ! 264: dec si ; back up to reload character ! 265: arg310: ! 266: lodsb ! 267: ! 268: DELIM ! 269: je arg400 ! 270: ! 271: cmp al,C_QUOTE ! 272: je arg210 ; end of quoted portion of string ! 273: ! 274: cmp al,C_BACKSLASH ! 275: je arg320 ! 276: ! 277: inc dx ! 278: jmp arg310 ! 279: ; ! 280: ; Count backslashes ! 281: ; ! 282: arg320: ! 283: xor cx,cx ! 284: arg321: ! 285: inc cx ; CX counts the backslashes ! 286: lodsb ! 287: cmp al,C_BACKSLASH ! 288: je arg321 ! 289: ; ! 290: cmp al,C_QUOTE ! 291: je arg330 ! 292: ! 293: add dx,cx ; not followed by `"' -- treat `\'s normally ! 294: jmp arg300 ! 295: ; ! 296: arg330: ! 297: mov ax,cx ! 298: shr cx,1 ! 299: adc dx,cx ; add 1 for every pair of backslashes ! 300: test al,1 ; plus 1 for the " if odd number of \ ! 301: jnz arg310 ; " was escaped with a \ ! 302: jmps arg210 ; " closes a quoted substring ! 303: ; ! 304: ; Command line is fully parsed - compute number of bytes needed ! 305: ; ! 306: arg400: ! 307: ; ! 308: ; Number of bytes needed = ! 309: ; Number of bytes used to make strings + ! 310: ; Number of bytes used to terminate strings + ! 311: ; sizeof(DATAPTR) * ( number of arguments + 1 ) ! 312: ; ! 313: push ss ! 314: pop ds ; Restore DS = DGROUP ! 315: assumes ds,data ! 316: ! 317: mov __argc,di ; Store number of arguments ! 318: ! 319: add dx,di ; add in terminator bytes ! 320: ifdef WILDCARD ! 321: add dx,di ; add in Wildcard flag bytes ! 322: endif ! 323: inc di ; add one for NULL pointer ! 324: shl di,1 ! 325: if sizeD ! 326: shl di,1 ! 327: endif ! 328: mov ax,di ! 329: add ax,dx ; add space for pointers to space for chars ! 330: ! 331: and al,not 1 ; Round up to an even number of bytes ! 332: ; ! 333: ; Allocate space on the heap (or the stack) ! 334: ; ! 335: ; AX is the total number of bytes needed for strings and pointers ! 336: ; DI is the number of bytes needed for the pointers ! 337: ; ! 338: call _stdalloc ! 339: jnc args_ok ! 340: arg_error: ! 341: mov ax,8 ;Out of heap/stack space. ! 342: jmp _amsg_exit ! 343: ! 344: args_ok: ! 345: mov word ptr (__argv),ax ! 346: if sizeD ! 347: mov word ptr (__argv+2),ds ! 348: endif ! 349: ; ! 350: ; Copy argument strings and addresses onto heap/stack ! 351: ; Address table is on the top, strings below that ! 352: ; ! 353: mov bx,ax ! 354: add di,ax ! 355: ! 356: push ss ; ES=SS ! 357: pop es ; ES:DI is where the string copies will go ! 358: assumes es,data ! 359: ; ! 360: ; DS:SI points to the argv[0] ! 361: ; ! 362: ; ES:BX points to where argv[0],argv[1],argv[2],... go ! 363: ; ES:DI points to where *argv[0],*argv[1],*argv[2],... go ! 364: ; For wildcard version only: ! 365: ; ES:DX points to the wildcard flag character (prepended to argument) ! 366: ; during the creation of each argument ! 367: ; ! 368: ! 369: mov ss:[bx],di ; argv[i] - offset part ! 370: if sizeD ! 371: mov ss:[bx+2],ss ; argv[i] - segment part ! 372: add bx,4 ! 373: else ! 374: inc bx ! 375: inc bx ! 376: endif ! 377: ! 378: mov si,cmdstart ; Get pointer to argv[0] ! 379: mov ds,_aenvseg ! 380: assumes ds,nothing ! 381: ! 382: ifdef WILDCARD ! 383: movsb ! 384: dec si ; copy first character as quote flag ! 385: endif ! 386: ! 387: copy_argv0: ! 388: lodsb ! 389: stosb ! 390: or al,al ! 391: jnz copy_argv0 ! 392: ; ! 393: ; DS:SI points to the raw command tail string ! 394: ; ! 395: ! 396: jmps arg510 ! 397: ; ! 398: ; Skip blanks ! 399: ; ! 400: arg500: ! 401: xor ax,ax ! 402: stosb ! 403: arg510: ! 404: lodsb ! 405: cmp al,C_BLANK ! 406: je arg510 ! 407: cmp al,C_TAB ! 408: je arg510 ! 409: ! 410: DELIM ! 411: lje arg810 ! 412: ! 413: mov ss:[bx],di ! 414: if sizeD ! 415: mov ss:[bx+2],ss ! 416: add bx,4 ! 417: else ! 418: inc bx ! 419: inc bx ! 420: endif ! 421: ! 422: ifdef WILDCARD ! 423: mov dx,di ! 424: stosb ; initialize wildcard flag ! 425: endif ! 426: ; ! 427: ; ! 428: ; Parse an argument ! 429: ; ! 430: arg600: ! 431: dec si ; back up to reload character ! 432: arg610: ! 433: lodsb ! 434: ! 435: cmp al,C_BLANK ! 436: je arg500 ! 437: cmp al,C_TAB ! 438: je arg500 ; white space terminates argument ! 439: ! 440: DELIM ! 441: je arg800 ! 442: ! 443: cmp al,C_QUOTE ! 444: je arg710x ! 445: ! 446: cmp al,C_BACKSLASH ! 447: je arg620 ! 448: ! 449: stosb ! 450: jmps arg610 ! 451: ; ! 452: ; Count backslashes ! 453: ; ! 454: arg620: ! 455: xor cx,cx ! 456: arg621: ! 457: inc cx ; CX counts the backslashes ! 458: lodsb ! 459: cmp al,C_BACKSLASH ! 460: je arg621 ! 461: ; ! 462: cmp al,C_QUOTE ! 463: je arg630 ! 464: ! 465: mov al,C_BACKSLASH ! 466: rep stosb ; not followed by `"' -- treat `\'s normally ! 467: jmp arg600 ! 468: ; ! 469: arg630: ! 470: mov al,C_BACKSLASH ! 471: shr cx,1 ! 472: rep stosb ! 473: jnc arg710x ; " opens a quoted substring ! 474: mov al,C_QUOTE ! 475: stosb ! 476: jmp arg610 ; " was escaped with a \ ! 477: ; ! 478: ; Enter a quoted string ! 479: ; ! 480: ifdef WILDCARD ! 481: arg710x: ! 482: inc si ; undoes the "DEC SI" between arg700 and arg710 ! 483: endif ! 484: ! 485: arg700x: ! 486: ! 487: ifdef WILDCARD ! 488: xchg dx,di ; set the wildcard flag character to `"' ! 489: mov al,C_QUOTE ! 490: stosb ! 491: dec di ! 492: xchg dx,di ! 493: endif ! 494: ! 495: arg700: ! 496: dec si ; back up to reload character ! 497: ! 498: ifndef WILDCARD ! 499: arg710x: ! 500: endif ! 501: ! 502: arg710: ! 503: lodsb ! 504: ! 505: DELIM ! 506: je arg800 ! 507: ! 508: cmp al,C_QUOTE ! 509: je arg610 ; end of quoted portion of string ! 510: ! 511: cmp al,C_BACKSLASH ! 512: je arg720 ! 513: ! 514: stosb ! 515: jmp arg710 ! 516: ; ! 517: ; Count backslashes ! 518: ; ! 519: arg720: ! 520: xor cx,cx ! 521: arg721: ! 522: inc cx ; CX counts the backslashes ! 523: lodsb ! 524: cmp al,C_BACKSLASH ! 525: je arg721 ! 526: ; ! 527: cmp al,C_QUOTE ! 528: je arg730 ! 529: ! 530: mov al,C_BACKSLASH ! 531: rep stosb ; not followed by `"' -- treat `\'s normally ! 532: jmp arg700x ! 533: ; ! 534: arg730: ! 535: mov al,C_BACKSLASH ! 536: shr cx,1 ! 537: rep stosb ; store 1 for every pair of backslashes ! 538: jnc arg610 ; " closes a quoted substring ! 539: mov al,C_QUOTE ; " was escaped with a \ ! 540: stosb ! 541: jmps arg710x ! 542: ; ! 543: ; Terminate last argument string, terminate list of argument pointers ! 544: ; ! 545: arg800: ! 546: xor ax,ax ! 547: stosb ; null-terminate final argument ! 548: arg810: ! 549: push ss ! 550: pop ds ! 551: assumes ds,data ! 552: ! 553: mov word ptr [bx],0 ; add null pointer to __argv[] ! 554: if sizeD ! 555: mov word ptr [bx+2],0 ! 556: endif ! 557: ! 558: ifndef WILDCARD ! 559: jmp [retadr] ; THE END ! 560: else ! 561: call _cwild ! 562: test ax,ax ! 563: jnz to_arg_error ! 564: jmp [retadr] ; THE END ! 565: ! 566: to_arg_error: ! 567: jmp arg_error ! 568: ! 569: page ! 570: ;*** ! 571: ;_find(pattern) - find matching filename ! 572: ; ! 573: ;Purpose: ! 574: ; if argument is non-null, do a DosFindFirst on that pattern ! 575: ; otherwise do a DosFindNext call. Return matching filename ! 576: ; or NULL if no more matches. ! 577: ; ! 578: ; char *_find(pattern) ! 579: ; char *pattern; ! 580: ; { ! 581: ; static struct FileFindBuf findbuf; ! 582: ; static unsigned findhandle=1; ! 583: ; unsigned findcount=1; ! 584: ; int rc; ! 585: ; ! 586: ; if(pattern) ! 587: ; rc = DOSFINDFIRST((char far *) pattern, ! 588: ; (unsigned far *) &findhandle, A_D, ! 589: ; (struct FileFindBuf far *) &findbuf, sizeof(findbuf), ! 590: ; (unsigned far *) &findcount, 0L); ! 591: ; else ! 592: ; rc = DOSFINDNEXT(findhandle, ! 593: ; (struct FileFindBuf far *) &findbuf, sizeof(findbuf), ! 594: ; (unsigned far *) &findcount); ! 595: ; ! 596: ; return(rc ? NULL : findbuf.file_name); ! 597: ; } ! 598: ; ! 599: ;Entry: ! 600: ; pattern = pointer to pattern or NULL ! 601: ; (NULL means find next matching filename) ! 602: ; ! 603: ;Exit: ! 604: ; AX (or DX:AX) = pointer to matching file name ! 605: ; or NULL if no more matches. ! 606: ; ! 607: ;Uses: ! 608: ; ! 609: ;Exceptions: ! 610: ; ! 611: ;******************************************************************************* ! 612: ! 613: cProc _find,<PUBLIC>,<> ! 614: parmDP pattern ! 615: ; localW findcount ! 616: findcount equ (word ptr [bp-2]) ! 617: cBegin ! 618: mov ax,1 ! 619: push ax ; mov [findcount],1 ! 620: mov bx,dataOFFSET findbuf ! 621: mov dx,size findbuf ! 622: lea ax,findcount ! 623: ; ! 624: ; DS:BX = &findbuf ! 625: ; DX = sizeof(findbuf) ! 626: ; SS:AX = &findcount ! 627: ; CX = FP_OFF(pattern) ! 628: ; ! 629: if sizeD ! 630: les cx,pattern ! 631: cmp word ptr [pattern+2],0 ! 632: jz find_next ! 633: else ! 634: mov cx,pattern ! 635: jcxz find_next ! 636: endif ! 637: ; ! 638: ; Make first call to DOSFINDFIRST ! 639: ; ! 640: if sizeD ! 641: push es ! 642: else ! 643: push ds ! 644: endif ! 645: push cx ; (char far *) pattern ! 646: mov cx,dataOFFSET findhandle ! 647: mov [findhandle],1 ; always use handle 1 ! 648: push ds ! 649: push cx ; (unsigned far *) & findhandle ! 650: mov cx,A_D ! 651: push cx ; match attribute: normal files + directories ! 652: push ds ! 653: push bx ; (struct FileFindBuf far *) &findbuf ! 654: push dx ; sizeof(findbuf) ! 655: push ss ! 656: push ax ; (unsigned far *) &findcount ! 657: xor ax,ax ! 658: push ax ! 659: push ax ; 0L (reserved) ! 660: call DOSFINDFIRST ! 661: jmp short check_rc ! 662: ; ! 663: ; get next match ! 664: ; ! 665: find_next: ! 666: push [findhandle] ; findhandle ! 667: push ds ! 668: push bx ; (struct FileFindBuf far *) &findbuf ! 669: push dx ; sizeof(findbuf) ! 670: push ss ! 671: push ax ! 672: call DOSFINDNEXT ! 673: ; ! 674: check_rc: ! 675: add bx,offset file_name ; BX = findbuf.file_name ! 676: if sizeD ! 677: mov dx,ds ! 678: endif ! 679: test ax,ax ; check for error in system call ! 680: xchg ax,bx ; return findbuf.file_name if successful ! 681: jz rc_zero ! 682: ; ! 683: xor ax,ax ; return NULL for error ! 684: if sizeD ! 685: cwd ! 686: endif ! 687: rc_zero: ! 688: ! 689: cEnd ! 690: ! 691: endif ; WILDCARD ! 692: ! 693: sEnd code ! 694: ! 695: end
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.