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