mirror of
https://github.com/SEPPDROID/Digital-Research-Source-Code.git
synced 2025-10-23 00:14:25 +00:00
229 lines
9.2 KiB
C
229 lines
9.2 KiB
C
/*****************************************************************************
|
||
*
|
||
* "__main()" Subroutine to "_main()"
|
||
* ----------------------------------
|
||
* Copyright 1983 by Digital Research Inc. All rights reserved.
|
||
*
|
||
* Routine "__main()" is entered from the "_main()" routine to start a
|
||
* C program. The command string from CP/M is parsed into
|
||
* a UNIX-like "argc/argv" setup, including simple I/O redirection.
|
||
*
|
||
* This module can be compiled without wildcard parsing if the
|
||
* symbol "NOWILD" (note upper case) is defined in the compile line.
|
||
*
|
||
* Edits:
|
||
* 28-Feb-84 whf "_salloc()" goes to NOWILD region
|
||
* 02-Feb-84 whf nowild -> NOWILD, removed write()
|
||
* 01-Jan-84 whf add in handle for OPTION*.h
|
||
* 08-Dec-83 whf handle PC-DOS diffs, add ">>" redirection
|
||
* 11-Oct-83 whf converted to DRC from CPM68K
|
||
*
|
||
* Calling Sequence:
|
||
* return = _main(command,length);
|
||
*
|
||
* Where:
|
||
* command Is the address of the command line from CP/M
|
||
* length Is the number of characters in the line,
|
||
* excluding the termination character (CR/LF).
|
||
*
|
||
*****************************************************************************/
|
||
#include "portab.h" /* Include std definitions */
|
||
#include "osif.h" /* Include CP/M Definitions */
|
||
#include "ctype.h" /* char type definitions */
|
||
|
||
#define STDIN 0 /* file descriptors */
|
||
#define STDOUT 1 /* */
|
||
#define STDERR 2 /* */
|
||
|
||
#define ISWHITE(ch) ((ch)==NULL || isspace(ch)) /* */
|
||
|
||
#ifndef NOWILD
|
||
EXTERN BYTE *_salloc(); /* Stack allocation routine */
|
||
#endif
|
||
EXTERN BYTE *sbrk(); /* Incr break location */
|
||
EXTERN BYTE *strchr(); /* V7 "index" function */
|
||
EXTERN BYTE __pname[]; /* Default Program name */
|
||
MLOCAL WORD argc; /* Arg count */
|
||
MLOCAL BYTE *argv; /* -> array of pointers */
|
||
MLOCAL BYTE *argv2; /* Companion ptr to argv */
|
||
|
||
__main(com, len) /****************************/
|
||
BYTE *com; /* Command address */
|
||
WORD len; /* Command length */
|
||
{ /****************************/
|
||
REG WORD i; /* Define a count var. */
|
||
REG BYTE *s; /* Temp byte pointer */
|
||
REG BYTE *p; /* Another "" */
|
||
REG BYTE c; /* Character temp */
|
||
FD *pfd; /* File Desc temp */
|
||
BYTE tmpbuf[30]; /* Filename temp */
|
||
BYTE *strchr(); /* V7 index() func */
|
||
/****************************/
|
||
argv2 = argv = sbrk(0); /* -> first free location */
|
||
argc = 0; /* No args yet */
|
||
addargv(__pname); /* */
|
||
for (s = com; *s; s += i) /* One arg at a time */
|
||
{ /* */
|
||
while (*s && isspace(*s)) /* Skip leading spaces */
|
||
++s; /* */
|
||
if (!*s) /* End of line? */
|
||
break; /* Yes, don't continue */
|
||
if(*s == '"' || *s == '\'') /* Quoted string */
|
||
{ /* */
|
||
c = *s; /* c = quote character */
|
||
p = strchr(s+1,c); /* Find next */
|
||
if (p == NULLPTR) /* Any? */
|
||
_err(s,": unmatched quote");/* No, bitch. */
|
||
i = (WORD)p-s; /* Compute length */
|
||
s[i++] = '\0'; /* Nullify at end */
|
||
addargv(s+1); /* Add to arg list */
|
||
} /****************************/
|
||
else /* */
|
||
{ /****************************/
|
||
for(i = 0; !ISWHITE(s[i]); ++i)/* How many characters? */
|
||
; /* */
|
||
if (s[i]) /* If last is space, etc... */
|
||
s[i++] = '\0'; /* Make it a null for C */
|
||
switch(*s) /* Now do i/o scan */
|
||
{ /****************************/
|
||
case '<': /* Redirecting input?? */
|
||
close(STDIN); /* Yes, close TTY */
|
||
if (opena(s + 1,READ) != STDIN) /* Open New */
|
||
_err("Cannot open ", s + 1) ;/* Can't ... */
|
||
break; /* Done with this one */
|
||
/****************************/
|
||
case '>': /* Redirecting output?? */
|
||
close(STDOUT); /* Close output */
|
||
if(s[1]=='>') { /* Appending? */
|
||
if(opena(s+2,WRITE)!=STDOUT /* Try to open old */
|
||
|| -1 == lseek(STDOUT,0L,2) ) /* At EOF */
|
||
_err("Cannot append ",s+1); /* Can't */
|
||
} else { /*** */
|
||
if (creata(s+1,0)!=STDOUT) /* Try to open new */
|
||
_err("Cannot create ", s + 1); /* Can't */
|
||
} /* */
|
||
break; /****************************/
|
||
/* */
|
||
default: /* Just a regular arg */
|
||
/****************************/
|
||
#ifndef NOWILD /********************************************************/
|
||
/********************************************************/
|
||
if(strchr(s,'?') || /* Wild */
|
||
strchr(s,'*')) /* Cards? */
|
||
{ /****************************/
|
||
pfd = _getccb(STDERR+1); /* Use unused channel */
|
||
__OSIF(SETDMA,pfd->buffer);/* Use buffer for DMA */
|
||
c=__open(STDERR+1,s,SEARCHF); /* Do the search */
|
||
if(c == 0xff) /* Failed ... */
|
||
_err(s,": No match"); /* Complain */
|
||
while(c != 0xff) /* Do search next's */
|
||
{ /****************************/
|
||
_toasc(pfd,c,tmpbuf); /* Convert file to ascii */
|
||
p = _salloc(strlen(tmpbuf)+1);/* Allocate area */
|
||
strcpy(p,tmpbuf); /* Move in filename */
|
||
addargv(p); /* Add this file to argv */
|
||
c=__open(STDERR+1,s,SEARCHN); /* Search next */
|
||
} /****************************/
|
||
} else /* */
|
||
/********************************************************/
|
||
#endif /********************************************************/
|
||
|
||
addargv(s); /* save in argv */
|
||
} /* */
|
||
} /* */
|
||
} /****************************/
|
||
addargv(NULLPTR); /* Insure terminator */
|
||
argc--; /* Back off by 1 */
|
||
if( brk(argv2)==FAILURE) /* Allocate the pointers */
|
||
_err("Stack Overflow",""); /* Call "Stack Overflow" rtn*/
|
||
exit(main(argc,argv,NULLPTR)); /* Invoke C program (No Env)*/
|
||
}
|
||
|
||
/* */
|
||
MLOCAL _err(s1,s2) /* Error routine */
|
||
char *s1; /* Message text */
|
||
char *s2; /* Filename */
|
||
{ /****************************/
|
||
char buf[128]; /* place to build message */
|
||
/* */
|
||
strcpy(buf,s1); /* Output error message */
|
||
strcat(buf,s2); /* And filename */
|
||
strcat(buf,"\r\n$"); /* + Newline */
|
||
__OSIF(C_WRITESTR,buf); /* output directly to CON: */
|
||
exit(-1); /* And fail hard */
|
||
} /****************************/
|
||
|
||
/*
|
||
* Addargv function -- adds a pointer to the argv array, getting the
|
||
* space from the heap.
|
||
*/
|
||
MLOCAL addargv(ptr) /****************************/
|
||
REG BYTE *ptr; /* -> Argument string to add*/
|
||
{ /* */
|
||
*((BYTE **)argv2) = ptr; /* Load pointer */
|
||
argv2 += sizeof(char *); /* More room from heap */
|
||
argc++; /* Increment arg count */
|
||
} /****************************/
|
||
|
||
/*****************************************************************************/
|
||
/*****************************************************************************/
|
||
#ifndef NOWILD
|
||
/*
|
||
* Toasc routine -- combines the FCB name in the DMA and the user number
|
||
* / drive field to produce an ascii file name for SEARCHes.
|
||
*
|
||
*/
|
||
MLOCAL _toasc(p,c,buf) /*****************************/
|
||
REG FD *p; /* -> Data area */
|
||
REG BYTE c; /* 0 .. 3 search code */
|
||
REG BYTE *buf; /* Output buffer area */
|
||
{ /*****************************/
|
||
REG BYTE *f; /* -> Fcb in DMA buffer */
|
||
WORD i; /* Temp. */
|
||
/* */
|
||
*buf = NULL; /* Nullify at first */
|
||
i = FALSE; /*****************************/
|
||
f = p->buffer; /* Pnt to results of search */
|
||
#if CPM /*================================================================*/
|
||
f += c*32; /* c == directory search code*/
|
||
if( p->user ) /* User # not default? */
|
||
{ /* Yes */
|
||
i = (p->user) -1; /* Cvt to real user # */
|
||
if( i>=10 ) *buf++ = '1'; /* Assume user # <15 */
|
||
*buf++ = '0' + (i % 10); /* now for digits */
|
||
*buf++ = ':'; /* finish off with this */
|
||
i = TRUE; /* remember */
|
||
}; /*****************************/
|
||
#endif /*================================================================*/
|
||
if(p->fcb.drive) /* Drive specified? */
|
||
{ /* Yes */
|
||
if(i) /* User #? */
|
||
buf--; /* Yes, back up over ':' */
|
||
*buf++ = p->fcb.drive - 1 + 'a'; /* Put in drive code */
|
||
*buf++ = ':'; /* And delimiter */
|
||
} /* */
|
||
for(i=1;i<9;i++) /* Move the filename */
|
||
{ /*****************************/
|
||
if(f[i] != ' ') /* Non-blank? */
|
||
*buf++ = tolower((f[i]&0x7f)); /* Yes, move it in */
|
||
} /*****************************/
|
||
*buf++ = '.'; /* Put in delimiter */
|
||
for(i=9; i<12; i++) /* Move in extension */
|
||
{ /* */
|
||
if(f[i] != ' ') /* Non-blank? */
|
||
*buf++ = tolower((f[i]&0x7f)); /* Yes, move it in */
|
||
} /*****************************/
|
||
*buf++ = NULL; /* Null at end */
|
||
} /*****************************/
|
||
|
||
#else
|
||
nowildcards() /* stubroutine for OPTION*.h package */
|
||
{
|
||
}
|
||
#endif
|
||
|
||
/*****************************************************************************/
|
||
/*****************************************************************************/
|
||
************************************************************/
|
||
************************************************************/
|