[net.sources] AZTEC C CROOT

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