edwards@h-sc1.UUCP (william edwards) (08/20/85)
I had a request to post this, so here it is. These are some modifications and additions to the Aztec C croot, which add wildcard expansion and pipes. * I did not write these *. I merely keyed in and debugged somewhat what I found in the March 1985 issue of Dr. Dobb's Journal. Please refer to that for a * commented * version of this code. There are two files here: the first is C source for these routines, and the second is assembler source for a loader. These modules replace the croot which comes with Aztec C. ----croot.c---------------------------------------- /* Copyright (C) 1981,1982 by Manx Software Systems. Copyright (C) 1982 Thomas Fenwick. Copyright (c) 1985 Allen Holub. Manx Software Systems is in no way responsible for this program. These portions may be reproduced for personal, non-profit use, only. All other use is prohibited. You should replace the croot in libc.lib with this module. This posting includes a couple of minor hacks by wse */ #include "fcntl.h" #include "errno.h" #include "io.h" #define MAXARGS 128 #define MAXBUF 128 #define LOADERSIZE 49 #define DEF_FCB 0x5c #define FCBSIZE 36 #define NULL 0 #define QUOTE 0x22 #define CBUF ((char *)0x80) #define CBUFEND (char *)(0x80+128-LOADERSIZE) #define srchfirst(fcb) (bdos (0x11, (fcb)) & 0xff) #define srchnext(fcb) (bdos (0x12, (fcb)) & 0xff) #define bdosopen(fcb) (bdos (0x0f, (fcb)) & 0xff) #define isalnum(c) (c >= 0x20 && c <= 0x7e) int badfd(), noper(); /* * channel table: relates fd's to devices */ struct channel chantab[] = { { 2, 0, 1, 0, noper, 2 } , { 0, 2, 1, 0, noper, 2 } , { 0, 2, 1, 0, noper, 2 } , { 0, 0, 0, 0, badfd, 0 } , { 0, 0, 0, 0, badfd, 0 } , { 0, 0, 0, 0, badfd, 0 } , { 0, 0, 0, 0, badfd, 0 } , { 0, 0, 0, 0, badfd, 0 } , { 0, 0, 0, 0, badfd, 0 } , { 0, 0, 0, 0, badfd, 0 } , { 0, 0, 0, 0, badfd, 0 } , }; static char *Argv[MAXARGS]; static char Argbuf[MAXBUF]; static int Argc; static int Doingpipe = 0; static char *Cmdtail; char *Pipe_in = "$PIPE.IN\0\0\0\0"; char *Pipe_out = "$PIPE.OUT\0\0\0"; Croot() { register char *cp, *fname; register int k; clear (Argbuf, MAXBUF, (char) 32); blockmv(Argbuf, (char *)0x81, 127); clear (CBUF, MAXBUF, (char) 32); Argbuf[*CBUF & 0x7f] = 0; Argv[0] = ""; cp = Argbuf; Argc = 1; while (Argc < MAXARGS) { while (*cp == ' ' || *cp == '\t') ++cp; if (*cp == 0) { break; } else if (*cp == '|') { Doingpipe = 1; Cmdtail = ++cp; fname = Pipe_out; k = 1; goto redir2; } else if (*cp == '>') { /* redirect output */ k = 1; goto redirect; } else if (*cp == '<') { /* redirect input */ k = 0; redirect: while (*++cp == ' ' || *cp == '\t') ; fname = cp; while (*++cp) { if (*cp == ' ' || *cp == '\t') { *cp++ = 0; break; } } redir2: close(k); if (k) k = creat(fname, 0666); else k = open(fname, O_RDONLY); if (k == -1) { strcpy (0x80, "Can't open file for redirection: "); strcat(0x80, fname); strcat(0x80, "\n"); write(2, 0x80, strlen(0x80)); exit(10); } if (Doingpipe) break; } else if (*cp == QUOTE) { Argv[Argc++] == ++cp; while (*cp && (*cp != '"')) { cp++; } *cp++ = 0; } else if (haswild (cp)) { Argc += do_wild (cp, Argv + Argc, MAXARGS - Argc - 1); goto skippast; } else { Argv[Argc++] = cp; skippast: while (*++cp) { if (*cp == ' ' || *cp == '\t') { *cp++ = 0; break; } } } } exit(main(Argc,Argv)); } exit(code) { register char *tailp, *src, *dest; static char buff[MAXARGS]; clear (buff, MAXARGS, NULL); closall_(); unlink (Pipe_in); if ( code ) unlink("A:$$$.SUB"); #ifdef DEBUG perr ("\r\nFirst Cmdtail = "); perr (Cmdtail); perr ("\r\n"); #endif if (Doingpipe) { rename (Pipe_out, Pipe_in); while (*Cmdtail == ' ') Cmdtail++; tailp = Cmdtail; while (*tailp && *tailp != ' ') tailp++; if (*tailp) *tailp++ = '\0'; sprintf (buff, "%s < %s", tailp, Pipe_in); #ifdef DEBUG perr ("\r\nnext Cmdtail = "); perr (Cmdtail); perr ("\r\n"); perr ("\r\nbuff = "); perr (buff); perr ("\r\n"); #endif execl (Cmdtail, buff); perr ("Couldn't open file at end of pipe: "); perr (Cmdtail); perr (".COM"); unlink ("A:$$$.SUB"); unlink ("$$$.SUB"); } boot_(); } execl (name, args) char *name, *args; { register char *cp, *dest, **argp; sprintf (CBUF, "%s.%s", name, "COM"); initfcb ((char *) CBUF, (char *) DEF_FCB); #ifdef DEBUG perr ("\r\nargs: "); perr (args); perr ("\r\n"); #endif if (bdosopen (DEF_FCB) == 0xff) return (0); dest = CBUF + 1; for (argp = &args; *argp && dest < CBUFEND; argp++) { for (cp = *argp; *cp && dest < CBUFEND; *dest++ = *cp++); *dest++ = ' '; } *dest = '\0'; *CBUF = (int) dest - (int) CBUF; #ifdef DEBUG perr ("\r\nCBUF: "); perr (CBUF); perr ("\r\n"); #endif loadldr(); } perr (str) char *str; { while (*str) bdos (2, *str++); } badfd() { errno = EBADF; return -1; } noper() { return 0; } initfcb (filename, fcb) char *filename, *fcb; { register char *fp; register int i; for (i = FCBSIZE, fp = fcb; --i > 0; *fp++ = 0) ; if (*filename && filename[1] == ':') { *fcb = (char) (toupper (*filename) - 'A' + 1); filename += 2; } expand_name (fcb, filename); } expand_name (dest, src) char *dest, *src; { register char *dot, *end, i; dot = ++dest; for (i = 11; --i >= 0;) *dot++ = *(src) ? ' ' : '?'; dot = &dest[8]; end = &dest[10]; while (*src && *src != ' ') { if (*src == '*') { if (dest < dot) { while (dest < dot) *dest++ = '?'; } else { while (dest <= end) *dest++ = '?'; } } else if (*src == '.') dest = dot; else *dest++ = *src; src++; } } int do_wild (fname, argv, maxarg) char *fname, **argv; int maxarg; { register char *dest, *src; register unsigned int tmp; register int i, argc = 0; extern char *alloc(); initfcb ((char *) fname, (char *) DEF_FCB); if ((tmp = srchfirst (DEF_FCB)) != 0xff) { do { if ((dest = fname = alloc (13)) == 0) { perr ("Not enough memory to expand wildcard"); exit (1); } src = ((char *) ((tmp << 5) + 0x80)) + 1; if (*(fname + 1) == ':') { *dest++ = *fname; *dest++ = ':'; } for (i = 1; i <= 11; i++) { if ((*src & 0x7f) != ' ') *dest++ = *src++; else src++; if (i == 8) { if ((*src & 0x7f) == ' ') break; else *dest++ = '.'; } } *dest = '\0'; argv[argc++] = fname; tmp = srchnext (DEF_FCB); } while ((tmp != 0xff) && (argc < maxarg)); } return (argc); } haswild (str) char *str; { register int c; do { c = *str++; if (c == '*' || c == '?') return (1); } while (c && c != ' '); return (0); } ----------ldldr.asm--------------------------------------------- ; LDLDR.ASM -- asm support for Manx pipes closec equ 16 reads equ 20 sdma equ 26 fcb equ 5ch tpa equ 100h tbuff equ 80h bdos equ 05h bdosv equ 06h loader: lxi d,tpa load1: push d push b mvi c,sdma call bdos pop d push d mvi c,reads call bdos pop b pop d ora a jz tpa - 8 mov d,b mov e,c mvi c,closec call bdos mvi c,sdma lxi d,tbuff call bdos jmp tpa load2: lxi h,80h dad d xchg jmp tpa-46 public loadldr_ loadldr_: lxi d,loader lxi h,tpa-49 mvi b,49 L1: ldax d mov m,a inx d inx h dcr b jnz L1 lxi b,fcb lxi d,tpa lhld bdosv sphl jmp tpa-49 end