Files
Sepp J Morris 31738079c4 Upload
Digital Research
2020-11-06 18:50:37 +01:00

1479 lines
34 KiB
Plaintext
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*--------------------------------------------------------------*\
| ccp.c CONSOLE COMMAND PROCESSOR v1.1 |
| ========================= |
| |
| CP/M 68k: A CP/M derived operating system |
| |
| *==================================================* |
| *==================================================* |
| *THIS IS THE DUAL PROCESSOR,ROMABLE CP/M-68K SYSTEM* |
| *==================================================* |
| *==================================================* |
| |
| Description: |
| ----------- |
| The Console Command Processor is a |
| distinct program which references |
| the BDOS to provide a human-oriented |
| interface for the console user to the |
| information maintained by the BDOS on |
| disk storage. |
| |
| created by : Tom Saulpaugh Date created: 7/13/82 |
| ---------- ------------ |
| last modified: 03/17/83 St. Patrick's Day!!! |
| ------------- -------------------- |
| |
| (c) COPYRIGHT Digital Research 1983 |
| all rights reserved |
| |
\*--------------------------------------------------------------*/
/*--------------------------------------------------------------*\
| CCP Macro Definitions |
\*--------------------------------------------------------------*/
#include "ccpdef.h" /* include CCP defines */
/*--------------------------------------------------------------*\
| CP/M Builtin Command Table |
\*--------------------------------------------------------------*/
struct _cmd_tbl
{
BYTE *ident; /* command identifer field */
UWORD cmd_code; /* command code field */
}
cmd_tbl[8] = /* declare CP/M built-in table */
{
"DIR",DIRCMD,
"DIRS",DIRSCMD,
"TYPE",TYPECMD,
"REN",RENCMD,
"ERA",ERACMD,
"USER",UCMD,
"SUBMIT",SUBCMD,
NULL,-1
};
/*--------------------------------------------------------------*\
| CP/M-68K COMMAND FILE LOADER TABLE |
\*--------------------------------------------------------------*/
extern struct _filetyps
{
BYTE *typ;
UWORD (*loader) ();
BYTE user_c;
BYTE user_0;
}
load_tbl[];
/*--------------------------------------------------------------*\
| Table of User Prompts and Messages |
\*--------------------------------------------------------------*/
BYTE msg[] = "NON-SYSTEM FILE(S) EXIST$";
BYTE msg2[] = "Enter Filename: $";
BYTE msg3[] = "Enter Old Name: $";
BYTE msg4[] = "Enter New Name: $";
BYTE msg5[] = "File already exists$";
BYTE msg6[] = "No file$";
BYTE msg7[] = "No wildcard filenames$";
BYTE msg8[] = "Syntax: REN Newfile=Oldfile$";
BYTE msg9[] = "Confirm(Y/N)? $";
BYTE msg10[] = "Enter User No: $";
BYTE msg11[] = ".SUB file not found$";
BYTE msg12[] = "User # range is [0-15]$";
BYTE msg13[] = "Too many arguments: $";
BYTE lderr1[] = "insufficient memory or bad file header$";
BYTE lderr2[] = "read error on program load$";
BYTE lderr3[] = "bad relocation information bits$";
BYTE lderror[] = "program load error$";
/*--------------------------------------------------------------*\
| Global Arrays & Variables |
\*--------------------------------------------------------------*/
/********************************/
BYTE load_try; /* flag to mark a load try */
BYTE first_sub; /* flag to save current cmd ptr */
BYTE chain_sub; /* submit chaining flag */
extern BYTE submit; /* submit file flag */
BYTE end_of_file; /* submit end of file flag */
BYTE dirflag; /* used by fill_fcb(? or blanks)*/
BYTE subprompt; /* submit file was prompted for */
extern BYTE morecmds; /* command after warmboot flag */
UWORD sub_index; /* index for subdma buffer */
UWORD index; /* index into cmd argument array*/
UWORD sub_user; /* submit file user number */
UWORD user; /* current default user number */
UWORD cur_disk; /* current default disk drive */
BYTE subcom[CMD_LEN+1]; /* submit command buffer */
BYTE subdma[CMD_LEN]; /* buffer to fill from sub file */
extern BYTE usercmd[CMD_LEN+2]; /* user command buffer */
BYTE *user_ptr; /* next user command to execute */
BYTE *glb_index; /* points to current command */
BYTE save_sub[CMD_LEN+1]; /* saves cur cmd line for submit*/
BYTE subfcb[FCB_LEN]; /* global fcb for sub files */
BYTE cmdfcb[FCB_LEN]; /* global fcb for 68k files */
BYTE *tail; /* pointer to command tail */
extern BYTE autost; /* autostart flag */
BYTE autorom; /* needed for ROM system autost */
BYTE dma[DMA_LEN+3]; /* 128 byte dma buffer */
BYTE parm[MAX_ARGS][ARG_LEN]; /* cmd argument array */
BYTE del[] = /* CP/M-68K set of delimeters */
{'>','<','.',',','=','[',']',';','|','&','/','(',')','+','-','\\'};
/********************************/
/*--------------------------------------------------------------*\
| Function Definitions |
\*--------------------------------------------------------------*/
/********************************/
extern UWORD bdos(); /* this returns a word */
extern UWORD load68k(); /* this returns a word(1-3) */
BYTE *scan_cmd(); /* this returns a ptr to a byte */
UWORD strcmp(); /* this returns a word */
UWORD decode(); /* this returns a word */
UWORD delim(); /* this returns a word */
BYTE true_char(); /* this returns a byte */
UWORD fill_fcb(); /* this returns a word */
UWORD too_many(); /* this returns a word */
UWORD find_colon(); /* this returns a word */
UWORD chk_colon(); /* this returns a word */
UWORD user_cmd(); /* this returns a word */
UWORD cmd_file(); /* this returns a word */
UWORD sub_read(); /* this returns a word */
UWORD dollar(); /* this returns a word */
UWORD comments(); /* this returns a word */
UWORD submit_cmd(); /* this returns a word */
/********************************/
/********************************/
VOID cr_lf() /* print a CR and a Linefeed */
/********************************/
{
bdos(CONSOLE_OUTPUT,CR);
bdos(CONSOLE_OUTPUT,LF);
}
/********************************/
VOID cpy(source,dest) /* copy source to destination */
/********************************/
REG BYTE *source;
REG BYTE *dest;
{
while(*dest++ = *source++);
}
/********************************/
UWORD strcmp(s1,s2) /* compare 2 char strings */
/********************************/
REG BYTE *s1,*s2;
{
while(*s1)
{
if(*s1 > *s2)
return(1);
if(*s1 < *s2)
return(-1);
s1++; s2++;
}
return((*s2 == NULL) ? 0 : -1);
}
/********************************/
VOID copy_cmd(com_index) /* Save the command which */
/* started a submit file */
/* Parameter substituion will */
/* need this command tail. */
/* The buffer save_sub is used */
/* to store the command. */
/********************************/
REG BYTE *com_index;
{
REG BYTE *t1,*temp;
temp = save_sub;
if(subprompt)
{
t1 = parm;
while(*t1)
*temp++ = *t1++;
*temp++ = ' ';
subprompt = FALSE;
}
while(*com_index && *com_index != EXLIMPT)
*temp++ = *com_index++;
*temp = NULL;
}
/********************************/
VOID prompt() /* print the CCP prompt */
/********************************/
{
REG UWORD cur_drive,cur_user_no;
BYTE buffer[3];
cur_user_no = bdos(GET_USER_NO,(long)255);
cur_drive = bdos(RET_CUR_DISK,(long)0);
cur_drive += 'A';
cr_lf();
if(cur_user_no)
{
if(cur_user_no >= 10)
{
buffer[0] = '1';
buffer[1] = ((cur_user_no-10) + '0');
buffer[2] = '$';
}
else
{
buffer[0] = (cur_user_no + '0');
buffer[1] = '$';
}
bdos(PRINT_STRING,buffer);
}
bdos(CONSOLE_OUTPUT,(long)cur_drive);
bdos(CONSOLE_OUTPUT,ARROW);
}
/********************************/
VOID echo_cmd(cmd,mode) /* echo any multiple commands */
/* or any illegal commands */
/********************************/
REG BYTE *cmd;
REG UWORD mode;
{
if(mode == GOOD && (!(autost && autorom)))
prompt();
while(*cmd && *cmd != EXLIMPT)
bdos(CONSOLE_OUTPUT,(long)*cmd++);
if(mode == BAD)
bdos(CONSOLE_OUTPUT,(long)'?');
else
cr_lf();
}
/********************************/
UWORD decode(cmd) /* Recognize the command as: */
/* --------- */
/* 1. Builtin */
/* 2. File */
/********************************/
REG BYTE *cmd;
{
REG UWORD i,n;
/****************************************/
/* Check for a CP/M builtin command */
/****************************************/
for(i = 0; i < 7;i++)
if (strcmp(cmd,cmd_tbl[i].ident) == MATCH)
return(cmd_tbl[i].cmd_code);
/********************************************************/
/* Check for a change of disk drive command */
/********************************************************/
i = 0;
while(i < (ARG_LEN-1) && parm[0][i] != ':')
i++;
if(i == 1 && parm[0][2] == NULL && parm[1][0] == NULL)
if((parm[0][0] >= 'A') && (parm[0][0] <= 'P'))
return(CH_DISK);
if(i == 1 && ((parm[0][0] < 'A') || (parm[0][0] > 'P')))
return(-1);
if(i != 1 && parm[0][i] == ':')
return(-1);
/*****************************************************/
/* Check for Wildcard Filenames */
/* Check Filename for a Delimeter */
/*****************************************************/
if(fill_fcb(0,cmdfcb) > 0)
return(-1);
if(i == 1)
i = 2;
else
i = 0;
if(delim(&parm[0][i]))
return(-1);
for(n = 0;n < ARG_LEN-1 && parm[0][n];n++)
if(parm[0][n] < ' ')
return(-1);
return(FILE);
}
/************************/
VOID check_cmd(tcmd) /* Check end of cmd */
/* for an '!' which */
/* starts another cmd */
REG BYTE *tcmd; /************************/
{
while(*tcmd && *tcmd != EXLIMPT)
tcmd++;
/*----------------------------*/
/* check for multiple command */
/* in case of a warmboot */
/*----------------------------*/
if(*tcmd++ == EXLIMPT && *tcmd)
{
morecmds = TRUE;
while(*tcmd == ' ')
tcmd++;
user_ptr = tcmd;
}
else
if(submit) /* check original cmd line */
{
if(!(end_of_file))
morecmds = TRUE;
/*--------------------------*/
else /* restore cmd to where user*/
/* ptr points to. User_ptr */
/* always points to next */
/* console command to exec */
{ /*--------------------------*/
submit = FALSE;
if(*user_ptr)
morecmds = TRUE;
}
}
else
morecmds = FALSE;
}
/************************/
VOID get_cmd(cmd,max_chars) /* Read in a command */
/*Strip off extra blanks*/
/************************/
REG BYTE *cmd;
REG long max_chars;
{
REG BYTE *c;
max_chars += (cmd - 1);
dma[0] = CMD_LEN; /* set maximum chars to read */
bdos(READ_CONS_BUF,dma); /* then read console */
if(dma[1] != 0 && dma[2] != ';')
cr_lf();
dma[((UWORD)dma[1] & 0xFF)+2] = '\n'; /* tack on end of line char */
if(dma[2] == ';') /* ';' denotes a comment */
dma[2] = '\n';
c = &dma[2];
while(*c == ' ' || *c == TAB)
c++;
while(*c != '\n' && cmd < max_chars)
{
*cmd++ = toupper(*c);
if(*c == ' ' || *c == TAB)
while(*++c == ' ' || *c == TAB);
else
c++;
}
*cmd = NULL; /* tack a null character on the end*/
}
/************************/
BYTE *scan_cmd(com_index) /* move ptr to next cmd */
/* in the command line */
/************************/
REG BYTE *com_index;
{
while((*com_index != EXLIMPT) &&
(*com_index))
com_index++;
while(*com_index == EXLIMPT || *com_index == ' ' ||
*com_index == TAB)
com_index++;
return(com_index);
}
/************************/
VOID get_parms(cmd) /* extract cmd arguments*/
/* from command line */
REG BYTE *cmd; /************************/
{
/************************************************/
/* This function parses the command line */
/* read in by get_cmd(). The expected command */
/* from that line is put into parm[0]. All */
/* parmeters associated with the command are put*/
/* in in sequential order in parm[1],parm[2], */
/* and parm[3]. A command ends at a NULL or */
/* an exlimation point. */
/************************************************/
REG BYTE *line; /* pointer to parm array */
REG UWORD i; /* Row Index */
REG UWORD j; /* Column Index */
line = parm;
for(i = 0; i < (MAX_ARGS * ARG_LEN); i++)
*line++ = NULL;
i = 0;
/***************************************************/
/* separate command line at blanks,exlimation pts */
/***************************************************/
while(*cmd != NULL &&
*cmd != EXLIMPT &&
i < MAX_ARGS)
{
j = 0;
while(*cmd != EXLIMPT &&
*cmd != ' ' &&
*cmd != TAB &&
*cmd)
{
if(j < (ARG_LEN-1))
parm[i][j++] = *cmd;
cmd++;
}
parm[i++][j] = NULL;
if(*cmd == ' ' || *cmd == TAB)
cmd++;
if(i == 1)
tail = cmd; /* mark the beginning of the tail */
}
}
/************************/
UWORD delim(ch) /* check ch to see */
/* if it's a delimeter */
/************************/
REG BYTE *ch;
{
REG UWORD i;
if(*ch <= ' ')
return(TRUE);
for(i = 0;i < sizeof (del);i++)
if(*ch == del[i]) return(TRUE);
return(FALSE);
}
/************************/
BYTE true_char(ch) /* return the desired */
/* character for fcb */
/************************/
REG BYTE *ch;
{
if(*ch == '*') return('?'); /* wildcard */
if(!delim(ch)) /* ascii character */
{
index++; /* increment cmd index */
return(*ch);
}
return(' '); /* pad field with blank */
}
/************************/
UWORD fill_fcb(which_parm,fcb) /* fill the fields of */
/* the file control blk */
/************************/
REG UWORD which_parm;
REG BYTE *fcb;
{
REG BYTE *ptr;
REG BYTE fillch;
REG UWORD j,k;
*fcb = 0;
for(k = 12;k <= 35; k++) /* fill fcb with zero */
fcb[k] = ZERO;
for(k = 1;k <= 11;k++)
fcb[k] = BLANK; /* blank filename+type */
/*******************************************/
/* extract drivecode,filename and filetype */
/* from parmeter blk */
/*******************************************/
if(dirflag)
fillch = '?';
else
fillch = ' ';
index = ZERO;
ptr = fcb;
if(parm[which_parm][index] == NULL) /* no parmemters */
{
ptr++;
for(j = 1;j <= 11;j++)
*ptr++ = fillch;
*fcb = (bdos(RET_CUR_DISK,(long)0)+1);
if(dirflag)
return(11);
else
return(0);
}
if(parm[which_parm][index+1] == ':')
{
*ptr = parm[which_parm][index] - 'A' + 1;
index += 2;
if(parm[which_parm][index] == NULL)
{
ptr = &fcb[1];
for(j = 1;j <= 11;j++)
*ptr++ = fillch;
if(dirflag)
return(11);
else
return(0);
}
}
else /* fill drivecode with the default disk */
*fcb = (bdos(RET_CUR_DISK,(long)0) + 1);
ptr = fcb;
ptr++; /* set pointer to fcb filename */
for(j = 1;j <= 8;j++) /* get filename */
*ptr++ = true_char(&parm[which_parm][index]);
while((!(delim(&parm[which_parm][index])))) index++;
if(parm[which_parm][index] == PERIOD)
{
index++;
for(j = 1;j <= 3;j++) /* get extension */
*ptr++ = true_char(&parm[which_parm][index]);
}
k = 0;
for(j = 1;j <= 11;j++)
if(fcb[j] == '?') k++;
return(k); /* return the number of question marks */
}
/************************/
UWORD too_many() /* too many args ? */
{ /************************/
if(parm[2][0])
{
bdos(PRINT_STRING,msg13);
echo_cmd(&parm[2][0],BAD);
return(TRUE);
}
return(FALSE);
}
/************************/
UWORD find_colon() /* search for a colon */
{ /************************/
REG UWORD i;
i = 0;
while(parm[1][i] && parm[1][i] != ':') i++;
return(i);
}
/************************/
UWORD chk_colon(j) /* check the position of*/
UWORD j; /* the colon and for */
{ /* a legal drive letter */
if(parm[1][j] == ':') /************************/
{
if(j != 1 || parm[1][0] < 'A' || parm[1][0] > 'P')
{
echo_cmd(&parm[1][0],BAD);
return(FALSE);
}
}
return(TRUE);
}
/************************/
VOID dir_cmd(attrib) /* print out a */
/* directory listing */
/*----------------------*/
/* attrib->1 (sysfiles) */
/* attrib->0 (dirfiles) */
/************************/
REG UWORD attrib;
{
BYTE needcr_lf;
REG UWORD dir_index,file_cnt;
REG UWORD save,j,k,curdrive,exist;
exist = FALSE; needcr_lf = FALSE;
if(too_many()) return;
j = find_colon();
if(!chk_colon(j)) return;
fill_fcb(1,cmdfcb);
curdrive = (cmdfcb[0] + 'A' - 1);
dir_index = bdos(SEARCH_FIRST,cmdfcb);
if(dir_index == 255)
bdos(PRINT_STRING,msg6);
save = (32 * dir_index) + 1;
file_cnt = 0;
while(dir_index != 255)
{
if(((attrib) && (dma[save+9] & 0x80)) ||
(!(attrib) && (!(dma[save+9] & 0x80))))
{
if(needcr_lf)
{
cr_lf();
needcr_lf = FALSE;
}
if(file_cnt == 0)
bdos(CONSOLE_OUTPUT,(long)curdrive);
}
else
{
exist = TRUE;
dir_index = bdos(SEARCH_NEXT);
save = (32 * dir_index) + 1;
continue;
}
dir_index = (32 * dir_index) + 1;
bdos(CONSOLE_OUTPUT,COLON);
bdos(CONSOLE_OUTPUT,BLANKS);
j = 1;
while(j <= 11)
{
if(j == 9)
bdos(CONSOLE_OUTPUT,BLANKS);
bdos(CONSOLE_OUTPUT,(long)(dma[dir_index++] & CMASK));
j++;
}
bdos(CONSOLE_OUTPUT,BLANKS);
dir_index = bdos(SEARCH_NEXT);
if(dir_index == 255)
break;
file_cnt++;
save = (32 * dir_index) + 1;
if(file_cnt == 5)
{
file_cnt = 0;
if((attrib && (dma[save+9] & 0x80)) ||
(!(attrib) && (!(dma[save+9] & 0x80))))
cr_lf();
else
needcr_lf = TRUE;
}
} /*----------------------------------------*/
if(exist) /* if files exist that were not displayed */
/* print out a message to the console */
{ /*----------------------------------------*/
cr_lf();
if(attrib)
bdos(PRINT_STRING,msg);
else
bdos(PRINT_STRING,&msg[4]);
}
}
/************************/
VOID type_cmd() /* type out a file */
/* to the console */
/************************/
{
REG UWORD i;
if(parm[1][0] == NULL) /*prompt user for filename*/
{
bdos(PRINT_STRING,msg2);
get_cmd(&parm[1][0],(long)(ARG_LEN-1));
}
if(too_many())
return;
i = find_colon();
if(!chk_colon(i)) return;
i = fill_fcb(1,cmdfcb); /*fill a file control block*/
if(i == 0 && parm[1][0] && (bdos(OPEN_FILE,cmdfcb) <= 3))
{
while(bdos(READ_SEQ,cmdfcb) == 0)
{
for(i = 0;i <= 127;i++)
if(dma[i] != EOF)
bdos(CONSOLE_OUTPUT,(long)dma[i]);
else
break;
}
bdos(RESET_DRIVE,(long)cmdfcb[0]);
} else
if(parm[1][0])
{
if(i > 0)
bdos(PRINT_STRING,msg7);
else
bdos(PRINT_STRING,msg6);
}
}
/************************/
VOID ren_cmd() /* rename a file */
/************************/
{
BYTE new_fcb[FCB_LEN];
REG UWORD i,j,k,bad_cmd;
bad_cmd = FALSE; /*-------------------------*/
if(parm[1][0] == NULL) /*prompt user for filenames*/
{ /*-------------------------*/
bdos(PRINT_STRING,msg3);
get_cmd(&parm[3][0],(long)(ARG_LEN-1));
if(parm[3][0] == NULL)
return;
bdos(PRINT_STRING,msg4);
get_cmd(&parm[1][0],(long)(ARG_LEN-1));
parm[2][0] = '=';
} /*--------------------------------*/
else /*check for correct command syntax*/
{ /*--------------------------------*/
i = 0;
while(parm[1][i] != '=' && parm[1][i]) i++;
if(parm[1][i] == '=')
{
if(!(i > 0 && parm[1][i+1] &&
parm[2][0] == NULL))
bad_cmd = TRUE;
}
else
if(!(parm[2][0] == '=' &&
parm[2][1] == NULL &&
parm[3][0]))
bad_cmd = TRUE;
if(!bad_cmd && parm[1][i] == '=')
{
parm[1][i] = NULL;
i++;
j = 0;
while((parm[3][j++] = parm[1][i++]) != NULL);
parm[2][0] = '=';
}
}
for(j = 1;j < 4;j += 2)
{
k = 0;
while(parm[j][k] != ':' && parm[j][k])
k++;
if(k > 1 && parm[j][k] == ':')
bad_cmd = TRUE;
for(i = 0;i < sizeof del;i++)
if(parm[j][0] == del[i])
{
echo_cmd(&parm[j][0],BAD);
return;
}
}
if(!bad_cmd && parm[1][0] && parm[3][0])
{
i = fill_fcb(1,new_fcb);
j = fill_fcb(3,cmdfcb);
if(i == 0 && j == 0)
{
if(new_fcb[0] != cmdfcb[0])
{
if(parm[1][1] == ':' && parm[3][1] != ':')
cmdfcb[0] = new_fcb[0];
else
if(parm[1][1] != ':' && parm[3][1] == ':')
new_fcb[0] = cmdfcb[0];
else
bad_cmd = TRUE;
}
if(new_fcb[0] < 1 || new_fcb[0] > 16)
bad_cmd = TRUE;
if(!(bad_cmd) && bdos(SEARCH_FIRST,new_fcb) != 255)
bdos(PRINT_STRING,msg5);
else{
k = 0;
for(i = 16;i <= 35;i++)
cmdfcb[i] = new_fcb[k++];
if(cmdfcb[0] < 0 || cmdfcb[0] > 15)
bad_cmd = TRUE;
if(!(bad_cmd) &&
bdos(RENAME_FILE,cmdfcb) > 0)
bdos(PRINT_STRING,msg6);
}
}
else
bdos(PRINT_STRING,msg7);
}
if(bad_cmd)
bdos(PRINT_STRING,msg8);
}
/************************/
VOID era_cmd() /* erase a file from */
/* the directory */
/************************/
{
REG UWORD i;
/*----------------------*/
if(parm[1][0] == NULL) /* prompt for a file */
{ /*----------------------*/
bdos(PRINT_STRING,msg2);
get_cmd(&parm[1][0],(long)(ARG_LEN-1));
}
if(parm[1][0] == NULL)
return;
if(too_many())
return;
i = find_colon();
if(!chk_colon(i))
return;
else
if(parm[1][1] == ':' && parm[1][2] == NULL)
{
echo_cmd(&parm[1][0],BAD);
return;
}
i = fill_fcb(1,cmdfcb); /* fill an fcb */
if(i > 0 && !(submit)) /* no confirmation */
{ /* if submit file */
bdos(PRINT_STRING,msg9);
parm[2][0] = bdos(CONIN,(long)0);
parm[2][0] = toupper(parm[2][0]);
cr_lf();
if(parm[2][0] != 'N' && parm[2][0] != 'Y')
return;
}
if(parm[2][0] != 'N')
if(bdos(DELETE_FILE,cmdfcb) > 0)
bdos(PRINT_STRING,msg6);
}
/************************/
UWORD user_cmd() /* change user number */
/************************/
{
REG UWORD i;
if(parm[1][0] == NULL) /* prompt for a number */
{
bdos(PRINT_STRING,msg10);
get_cmd(&parm[1][0],(long)(ARG_LEN-1));
}
if(parm[1][0] == NULL)
return(TRUE);
if(too_many())
return(TRUE);
if(parm[1][0] < '0' || parm[1][0] > '9')
return(FALSE);
i = (parm[1][0] - '0');
if(i > 9)
return(FALSE);
if(parm[1][1])
i = ((i * 10) + (parm[1][1] - '0'));
if(i < 16 && parm[1][2] == NULL)
bdos(GET_USER_NO,(long)i);
else
return(FALSE);
return(TRUE);
}
UWORD cmd_file(mode)
/************************/
/* */
/* SEARCH ORDER */
/* ============ */
/* */
/* 1. 68K type on the */
/* current user # */
/* 2. BLANK type on */
/* current user # */
/* 3. SUB type on the */
/* current user # */
/* 4. 68K type on */
/* user 0 */
/* 5. BLANK type on the */
/* user 0 */
/* 6. SUB type on */
/* user 0 */
/* */
/*----------------------*/
/* */
/* If a filetype is */
/* specified then I */
/* search the current */
/* user # then user 0 */
/* */
/************************/
UWORD mode;
{
BYTE done,open,sub_open;
BYTE found;
REG UWORD i,n;
UWORD (*ldrpgm) ();
REG BYTE *top;
REG struct _filetyps *p;
dirflag = FALSE;
load_try = TRUE;
done = FALSE;
found = FALSE;
sub_open = FALSE;
open = FALSE;
user = bdos(GET_USER_NO,(long)255);
cur_disk = bdos(RET_CUR_DISK,(long)0);
if(mode == SEARCH) i = 0; else i = 1;
i = fill_fcb(i,cmdfcb);
if(i > 0)
{
bdos(PRINT_STRING,msg7);
return(FALSE);
}
p = &load_tbl;
top = p->typ;
if(cmdfcb[9] == ' ')
{
while(*(p->typ)) /* clear flags in table */
{
p->user_c = p->user_0 = FALSE;
p++;
}
bdos(SELECT_DISK,(long)(cmdfcb[0]-1));
cmdfcb[0] = '?'; cmdfcb[12] = NULL;
i = bdos(SEARCH_FIRST,cmdfcb);
while(i != 255 && !(done))
{
i *= 32;
if(dma[i] == 0 || dma[i] == user)
{
for(n = 9;n <= 11;n++) dma[i+n] &= CMASK;
dma[i+12] = NULL;
p = &load_tbl;
while(*(p->typ))
{
cpy(p->typ,&cmdfcb[9]);
if(strcmp(&cmdfcb[1],&dma[i+1]) == MATCH)
{
found = TRUE;
if(dma[i] == user) p->user_c = TRUE;
else p->user_0 = TRUE;
if(mode == SEARCH &&
strcmp(p->typ,top) == MATCH)
done = TRUE;
else
if(strcmp(p->typ,"SUB") == MATCH) done = TRUE;
}
p++;
}
}
i = bdos(SEARCH_NEXT);
}
if(!(found))
{
if(mode == SUB_FILE) bdos(PRINT_STRING,msg11);
dirflag = TRUE; load_try = FALSE;
bdos(SELECT_DISK,(long)cur_disk); return(FALSE);
}
if(mode == SEARCH)
fill_fcb(0,cmdfcb);
else
fill_fcb(1,cmdfcb);
p = &load_tbl;
while(*(p->typ))
{
if(p->user_c || p->user_0)
{
if(mode == SEARCH) break;
if(strcmp(p->typ,"SUB") == MATCH) break;
}
p++;
}
if(*(p->typ))
{
if(!(p->user_c)) bdos(GET_USER_NO,(long)0);
cpy(p->typ,&cmdfcb[9]);
}
}
bdos(SELECT_DISK,(long)cur_disk);
while(1)
{
if(bdos(OPEN_FILE,cmdfcb) <= 3)
{
for(n = 9;n <= 11;n++) cmdfcb[n] &= CMASK;
if(cmdfcb[9] == 'S' && cmdfcb[10] == 'U' && cmdfcb[11] == 'B')
{
sub_open = TRUE;
sub_user = bdos(GET_USER_NO,(long)255);
if(submit) chain_sub = TRUE;
else first_sub = TRUE;
for(i = 0;i < FCB_LEN;i++)
subfcb[i] = cmdfcb[i];
if(mode == SEARCH) subprompt = FALSE;
submit = TRUE;
end_of_file = FALSE;
}
else if(mode != SUB_FILE)
open = TRUE;
break;
}
else if(bdos(GET_USER_NO,(long)255) == 0) break;
else bdos(GET_USER_NO,(long)0);
}
if(open)
{
check_cmd(glb_index);
if(!(found))
{
p = &load_tbl;
while(*(p->typ))
if(strcmp(p->typ,&cmdfcb[9]) == MATCH) break;
else p++;
}
if(*(p->typ))
ldrpgm = p->loader;
else
ldrpgm = load68k; /* default */
/* ATTEMPT THE PROGRAM LOAD */
switch( (*ldrpgm) (glb_index) )
{
case 1: bdos(PRINT_STRING,lderr1); break;
case 2: bdos(PRINT_STRING,lderr2); break;
case 3: bdos(PRINT_STRING,lderr3); break;
default : bdos(PRINT_STRING,lderror);
}
}
if(!(sub_open) && mode == SUB_FILE)
bdos(PRINT_STRING,msg11);
bdos(GET_USER_NO,(long)user);
dirflag = TRUE;
load_try = FALSE;
morecmds = FALSE;
return((sub_open || open));
}
/************************/
UWORD sub_read() /* Read the submit file */
{ /************************/
if(bdos(READ_SEQ,subfcb))
{
end_of_file = TRUE;
return(FALSE);
}
return(TRUE);
}
/************************/
UWORD dollar(k,mode,com_index) /* Translate $n to */
/* nth argument on the */
/* command line */
/************************/
REG UWORD k;
REG UWORD mode;
REG BYTE *com_index;
{
REG UWORD n,j,p_index;
REG BYTE *p1;
j = sub_index;
if(k >= CMD_LEN)
{
k = 0;
if(!sub_read())
return(k);
}
if((subdma[k] >= '0') && (subdma[k] <= '9'))
{
p_index = (subdma[k] - '0');
p1 = com_index;
if(*p1++ == 'S' &&
*p1++ == 'U' &&
*p1++ == 'B' &&
*p1++ == 'M' &&
*p1++ == 'I' &&
*p1++ == 'T' &&
*p1 == ' ')
p_index++;
p1 = com_index;
for(n = 1; n <= p_index; n++)
{
while(*p1 != ' ' && *p1)
p1++;
if(*p1 == ' ')
p1++;
}
while(*p1 != ' ' && *p1 && j < CMD_LEN)
if(mode == FILL)
subcom[j++] = *p1++;
else
bdos(CONSOLE_OUTPUT,(long)*p1++);
k++;
}
else
{
if(mode == FILL)
subcom[j++] = '$';
else
bdos(CONSOLE_OUTPUT,(long)'$');
if(subdma[k] == '$')
k++;
}
sub_index = j;
if(k >= CMD_LEN)
{
k = 0;
sub_read();
}
return(k);
}
/************************/
UWORD comments(k,com_index) /* Strip and echo submit*/
/* file comments */
/************************/
REG UWORD k;
REG BYTE *com_index;
{
REG UWORD done;
done = FALSE;
prompt();
do
{
while(k < CMD_LEN &&
subdma[k] != EOF &&
subdma[k] != Cr)
{
if(subdma[k] == '$')
{
k++;
k = dollar(k,NOFILL,com_index);
}
else
bdos(CONSOLE_OUTPUT,(long)subdma[k++]);
}
if(k == CMD_LEN && subdma[k] != EOF && subdma[k] != Cr)
{
k = 0;
if(!sub_read()) done = TRUE;
}
else
{
if(subdma[k] == Cr)
{
k += 2;
if(k >= CMD_LEN)
{
k = 0;
sub_read();
}
}
else
end_of_file = TRUE;
done = TRUE;
}
}while(!(done));
return(k);
}
/************************/
VOID translate(com_index) /* TRANSLATE the subfile*/
/* and fill sub buffer. */
/************************/
REG BYTE *com_index;
{
REG BYTE *p1;
REG UWORD j,n,k,p_index;
j = 0;
k = sub_index;
while(!(end_of_file) && j < CMD_LEN
&& subdma[k] != Cr && subdma[k] != EXLIMPT)
{
switch(subdma[k])
{
case ';': k = comments(k,com_index);
break;
case TAB:
case ' ': if(j > 0)
subcom[j++] = subdma[k++];
blankout: while(k < CMD_LEN &&
(subdma[k] == ' ' || subdma[k] == TAB))
k++;
if(k >= CMD_LEN)
{
k = 0;
if(!sub_read());
else
goto blankout;
}
break;
case '$': k++;
sub_index = j;
k = dollar(k,FILL,com_index);
j = sub_index;
break;
case Lf: k++;
if(k >= CMD_LEN)
{
k = 0;
sub_read();
}
break;
case EOF:
end_of_file = TRUE;
break;
default: subcom[j++] = subdma[k++];
if(k >= CMD_LEN)
{
k = 0;
sub_read();
}
}
}
/*------------------------------------------------------------------*/
/* TRANSLATION OF A COMMAND IS COMPLETE */
/* -Now move sub_index to next command- */
/*------------------------------------------------------------------*/
if(subdma[k] == Cr || subdma[k] == EXLIMPT)
do
{
while(k < CMD_LEN &&
(subdma[k] == Cr ||
subdma[k] == Lf ||
subdma[k] == EXLIMPT))
k++;
if(k == CMD_LEN)
{
k = 0;
if(!sub_read())
break;
}
else
{
if(subdma[k] == EOF)
end_of_file = TRUE;
break;
}
}while(TRUE);
sub_index = k;
}
/************************/
UWORD submit_cmd(com_index) /* fill up the subcom */
/* buffer */
/************************/
/*--------------------------------------------------------------*\
| |
| Submit_Cmd is a Procedure that returns exactly |
| one command from the submit file. Submit_Cmd is |
| called only when the end of file marker has not |
| been read yet. Upon leaving submit_cmd,the variable |
| sub_index points to the beginning of the next command |
| to translate and execute. The buffer subdma is used |
| to hold the UN-translated submit file contents. |
| The buffer subcom holds a translated command. |
| Comments are echoed to the screen by the procedure |
| "comments". Parameters are substituted in comments |
| as well as command lines. |
| |
\*--------------------------------------------------------------*/
REG BYTE *com_index;
{
REG UWORD i,cur_user;
for(i = 0;i <= CMD_LEN;i++)
subcom[i] = NULL;
cur_user = bdos(GET_USER_NO,(long)255);
bdos(GET_USER_NO,(long)sub_user);
bdos(SET_DMA_ADDR,subdma);
if(first_sub || chain_sub)
{
for(i = 0;i < CMD_LEN;i++)
subdma[i] = NULL;
sub_read();
sub_index = 0;
}
if(!(end_of_file))
translate(com_index);
for(i = 0;i < CMD_LEN;i++)
subcom[i] = toupper(subcom[i]);
bdos(SET_DMA_ADDR,dma);
bdos(GET_USER_NO,(long)cur_user);
}
/************************/
VOID execute_cmd(cmd) /* branch to */
/* appropriate routine */
/************************/
REG BYTE *cmd;
{
REG UWORD i,flag;
switch( decode(cmd) )
{
case DIRCMD: dir_cmd(0);
break;
case DIRSCMD: dir_cmd(1);
break;
case TYPECMD: type_cmd();
break;
case RENCMD: ren_cmd();
break;
case ERACMD: era_cmd();
break;
case UCMD: if(!(user_cmd()))
bdos(PRINT_STRING,msg12);
break;
case CH_DISK: bdos(SELECT_DISK,(long)(parm[0][0]-'A'));
break;
case SUBCMD: flag = SUB_FILE;
if(parm[1][0] == NULL)
{
bdos(PRINT_STRING,msg2);
get_cmd(subdma,(long)(CMD_LEN-1));
i = 0;
while(subdma[i] != ' ' &&
subdma[i] &&
i < ARG_LEN-1 )
parm[1][i] = subdma[i++];
parm[1][i] = NULL;
if(i != 0) subprompt = TRUE;
else break;
}
else
subprompt = FALSE;
goto gosub;
case FILE: flag = SEARCH;
gosub: if(cmd_file(flag))
break;
if(flag == SUB_FILE)
break;
default : echo_cmd(parm,BAD);
}
}
main()
{ /*---------------------*/
REG BYTE *com_index; /* cmd execution ptr */
/*---------------------*/
dirflag = TRUE; /* init fcb fill flag */
bdos(SET_DMA_ADDR,dma); /* set system dma addr */
/*---------------------*/
if(load_try)
{
bdos(SELECT_DISK,(long)cur_disk);
bdos(GET_USER_NO,(long)user);
load_try = FALSE;
}
/*---------------------*/
if(morecmds) /* if a warmboot */
{ /* occured & there were*/
/* more cmds to do */
if(submit) /*---------------------*/
{
com_index = subcom;
submit_cmd(save_sub);
while(!*com_index)
{
if(end_of_file)
{
com_index = user_ptr;
submit = FALSE;
break;
}
else submit_cmd(save_sub);
}
}
else
com_index = user_ptr;
morecmds = FALSE;
if(*com_index)
echo_cmd(com_index,GOOD);
}
else
{ /*----------------------*/
prompt(); /* prompt for command */
com_index = usercmd; /* set execution pointer*/
if(autost && autorom) /* check for COLDBOOT cm*/
{ /* */
echo_cmd(usercmd,GOOD); /* echo the command */
autorom = FALSE; /* turn off .bss flag */
} /* */
else /* otherwise....... */
get_cmd(usercmd,(long)(CMD_LEN));/*read a cmd */
} /************************/
/*--------------------------------------------------------------*\
| |
| MAIN CCP PARSE LOOP |
| =================== |
| |
\*--------------------------------------------------------------*/
while(*com_index)
{ /*--------------------*/
glb_index = com_index; /* save for use in */
/* check_cmd call */
get_parms(com_index); /* parse command line */
if(parm[0][0] && parm[0][0] != ';')/*-----------*/
execute_cmd(parm); /* execute command */
/*--------------------*/
if(!(submit))
com_index = scan_cmd(com_index);/* inc pointer */
else
{
com_index = subcom;
if(first_sub || chain_sub)
{
if(subprompt)
copy_cmd(subdma);
else
copy_cmd(glb_index);
if(first_sub)
user_ptr = scan_cmd(glb_index);
submit_cmd(save_sub);
first_sub = chain_sub = FALSE;
}
else
*com_index = NULL;
while(*com_index == NULL)
{
if(end_of_file)
{
com_index = user_ptr;
submit = FALSE;
break;
}
else
submit_cmd(save_sub);
}
}
if(*com_index)
echo_cmd(com_index,GOOD);
}
}