|
|
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.