home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
200-299
/
ff284.lzh
/
Dme
/
src
/
command.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-11-27
|
20KB
|
748 lines
/*
* COMMAND.C
*
* (C)Copyright 1987 by Matthew Dillon, All Rights Reserved
*
* )c single character (typing)
* 'c single character (typing)
* `string' string of characters w/ embedded `' allowed!
* (string) same thing w/ embedded () allowed!
* \c override
*
* name arg arg command name. The arguments are interpreted as strings
* for the command.
*
* $scanf macro insert scanf'd variable
* $filename macro insert current file name
*
* Any string arguments not part of a command are considered to be typed
* text.
*/
#include "defs.h"
#include <stdio.h>
#if AREXX
extern int foundcmd; /* control for implicit ARexx macro invocation */
extern int cmderr; /* global command error flag for do_rexx()'s use */
#endif
#define CF_COK 1 /* Can be executed while in command line mode */
#define CF_PAR 2 /* ESCIMM special flag.. save rest of command line */
/* so it can be executed after user entry */
#define CF_ICO 4 /* OK to execute if iconified, else uniconify first*/
#define BTOCP(val, type) ((type)((long)val << 2))
extern char *breakout();
typedef void (*FPTR) ARGS((long));
typedef struct {
char *name; /* command name */
ubyte args;
ubyte flags;
void (*func) ARGS((long)); /* function */
} COMM;
/*
extern void do_map(), do_unmap(), do_up(), do_down(),
do_left(), do_right(), do_return(), do_bs(),
do_del(), do_esc(), do_downadd(), do_lastcolumn(),
do_firstcolumn(),do_edit(), do_tab(), do_backtab(),
do_save(), do_saveas(), do_deline(), do_insline(),
do_top(), do_bottom(), do_source(), do_firstnb(),
do_quit(), do_find(), do_page(), do_savetabs(),
do_split(), do_goto(), do_screentop(), do_screenbottom(),
do_repeat(), do_tabstop(), do_insertmode(),
do_block(), do_bdelete(), do_bcopy(), do_bmove(),
do_bsave(), do_wleft(), do_wright(), do_remeol(),
do_savemap(), do_if(), do_tlate(),
do_bsource(), do_findr(), do_findstr(), do_newwindow(),
do_windowparm(),do_resize(), do_margin(), do_wordwrap(),
do_reformat(), do_execute(), do_chfilename(),do_scrollup(),
do_scrolldown(),do_recall(), do_scanf(), do_iconify(),
do_tomouse(), do_refs(), do_arpload(), do_arpsave(),
do_arpinsfile(),do_setfont(), do_ignorecase(),do_ctags(),
do_addpath(), do_rempath(), do_set(), do_setenv(),
do_unset(), do_unsetenv(), do_ipc(), do_cd();
extern void do_menu(), do_menuclear(), do_menuadd(), do_menudel(),
do_menudelhdr(), do_menuon(), do_menuoff();
extern void do_null(), do_rx();
extern void do_popmark(), do_swapmark(), do_purgemark(),
do_ping(), do_pong(), do_undo();
extern int do_pushmark(), do_rexx(), do_join(),
do_toggle(), do_command(), do_col();
#if AREXX
extern void do_rx(), do_rx1(), do_rx2();
#endif
*/
/*============================================================================*/
/*
* WLEFT/WRIGHT will check command line mode themselves, and thus can
* be marked flags=1 even though they can change the line number.
*
* No more than 255 commands may exist unless you change the type of hindex[]
*
* Command names MUST be sorted by their first character
*/
unsigned char hindex[26]; /* alpha hash into table */
/* args flags */
COMM Comm[] = {
#ifndef NO_DO2
"addpath", 1, CF_COK, (FPTR)do_addpath,
#endif
"arpinsfile", 0, 0, (FPTR)do_arpinsfile,
"arpload", 0, 0, (FPTR)do_arpload,
"arpsave", 0, 0, (FPTR)do_arpsave,
"back", 0, CF_COK, (FPTR)do_bs,
"backtab", 0, CF_COK, (FPTR)do_backtab,
"bcopy", 0, 0, (FPTR)do_bcopy,
"bdelete", 0, 0, (FPTR)do_bdelete,
"block", 0, 0, (FPTR)do_block, /* checks com name for mode */
"bmove", 0, 0, (FPTR)do_bmove,
"bottom", 0, 0, (FPTR)do_bottom,
"bs", 0, CF_COK, (FPTR)do_bs,
"bsave", 1, CF_COK, (FPTR)do_bsave,
"bsource", 0, 0, (FPTR)do_bsource,
"cd", 1, CF_COK, (FPTR)do_cd,
"chfilename", 1, 0, (FPTR)do_chfilename,
"col", 1, CF_COK, (FPTR)do_col,
#ifndef NO_DO_CTAGS
"ctags", 0, CF_ICO, (FPTR)do_ctags,
#endif
"del", 0, CF_COK, (FPTR)do_del,
"deline", 0, 0, (FPTR)do_deline,
"down", 0, 0, (FPTR)do_down,
"downadd", 0, 0, (FPTR)do_downadd,
"esc", 0, CF_COK, (FPTR)do_esc,
"escimm", 1, CF_PAR, (FPTR)do_esc,
"execute", 1, CF_ICO, (FPTR)do_execute,
"find", 1, 0, (FPTR)do_find, /* checks com name for mode */
"findr", 2, 0, (FPTR)do_findr, /* checks com name for mode */
"findstr", 1, CF_COK, (FPTR)do_findstr, /* checks com name for mode */
"first", 0, CF_COK, (FPTR)do_firstcolumn,
"firstnb", 0, CF_COK, (FPTR)do_firstnb,
"goto", 1, 0, (FPTR)do_goto,
"height", 1, CF_COK, (FPTR)do_windowparm,
"iconify", 0, CF_ICO, (FPTR)do_iconify,
"if", 2, CF_COK, (FPTR)do_if,
"ifelse", 3, CF_COK, (FPTR)do_if,
"ignorecase", 1, CF_COK, (FPTR)do_ignorecase,
"insertmode", 1, CF_COK, (FPTR)do_insertmode,
"insfile", 1, 0, (FPTR)do_edit,
"insline", 0, 0, (FPTR)do_insline,
#ifndef NODRES
"ipc", 3, CF_COK, (FPTR)do_ipc,
#endif
"join", 0, 0, (FPTR)do_join,
"last", 0, CF_COK, (FPTR)do_lastcolumn,
"left", 0, CF_COK, (FPTR)do_left,
"leftedge", 1, CF_COK, (FPTR)do_windowparm,
"map", 2, CF_COK, (FPTR)do_map,
"margin", 1, CF_COK, (FPTR)do_margin,
"menuon", 0, 0, (FPTR)do_menuon,
"menuoff", 0, 0, (FPTR)do_menuoff,
"menuadd", 3, 0, (FPTR)do_menuadd,
"menudel", 2, 0, (FPTR)do_menudel,
"menudelhdr", 1, 0, (FPTR)do_menudelhdr,
"menuclear", 0, 0, (FPTR)do_menuclear,
"newfile", 1, 0, (FPTR)do_edit, /* checks com name for mode */
"newwindow", 0, CF_ICO, (FPTR)do_newwindow,
"next", 0, 0, (FPTR)do_find,
"nextr", 0, 0, (FPTR)do_findr,
"null", 0, CF_COK, (FPTR)do_null,
"pagedown", 0, 0, (FPTR)do_page,
"pageset", 1, 0, (FPTR)do_page,
"pageup", 0, 0, (FPTR)do_page,
"ping", 1, CF_ICO, (FPTR)do_ping,
"pong", 1, 0, (FPTR)do_pong,
"prev", 0, 0, (FPTR)do_find,
"prevr", 0, 0, (FPTR)do_findr,
"popmark", 0, 0, (FPTR)do_popmark,
"purgemark", 0, 0, (FPTR)do_purgemark,
"pushmark", 0, 0, (FPTR)do_pushmark,
"quit", 0, CF_ICO, (FPTR)do_quit,
"recall", 0, CF_COK, (FPTR)do_recall,
#ifndef NO_DO_REF
"ref", 0, 0, (FPTR)do_refs,
#endif
"reformat", 0, 0, (FPTR)do_reformat,
"remeol", 0, CF_COK, (FPTR)do_remeol,
#ifndef NO_DO2
"rempath", 1, CF_COK, (FPTR)do_rempath,
#endif
"repeat", 2, CF_ICO|CF_COK, (FPTR)do_repeat,
"repstr", 1, CF_COK, (FPTR)do_findstr,
"resettoggle", 1, CF_COK, (FPTR)do_toggle,
"resize", 2, 0, (FPTR)do_resize,
"return", 0, CF_COK, (FPTR)do_return, /* special meaning in command line mode */
"right", 0, CF_COK, (FPTR)do_right,
#if AREXX
"rx", 1, 0, (FPTR)do_rx, /* explicit ARexx macro invocation */
"rx1", 2, 0, (FPTR)do_rx1, /* explicit, with 1 arg to ARexx macro */
"rx2", 3, 0, (FPTR)do_rx2, /* explicit, with 2 args to ARexx macro */
#endif
"saveas", 1, CF_ICO|CF_COK, (FPTR)do_saveas,
"savemap", 1, CF_ICO|CF_COK, (FPTR)do_savemap, /* checks com name for mode */
"saveold", 0, CF_ICO|CF_COK, (FPTR)do_save,
"savesmap", 1, CF_ICO|CF_COK, (FPTR)do_savemap,
"savetabs", 1, CF_ICO|CF_COK, (FPTR)do_savetabs,
"scanf", 1, CF_COK, (FPTR)do_scanf,
"screenbottom", 0, 0, (FPTR)do_screenbottom,
"screentop", 0, 0, (FPTR)do_screentop,
"scrollup", 0, 0, (FPTR)do_scrollup,
"scrolldown", 0, 0, (FPTR)do_scrolldown,
"set", 2, CF_ICO|CF_COK, (FPTR)do_set,
"setenv", 2, CF_ICO|CF_COK, (FPTR)do_setenv,
"setfont", 2, 0, (FPTR)do_setfont,
"settoggle", 1, CF_COK, (FPTR)do_toggle,
"source", 1, CF_COK, (FPTR)do_source,
"split", 0, 0, (FPTR)do_split,
"swapmark", 0, 0, (FPTR)do_swapmark,
"tab", 0, CF_COK, (FPTR)do_tab,
"tabstop", 1, CF_COK, (FPTR)do_tabstop,
"tlate", 1, CF_COK, (FPTR)do_tlate,
"tmpheight", 1, CF_COK, (FPTR)do_windowparm,
"tmpwidth", 1, CF_COK, (FPTR)do_windowparm,
"toggle", 1, CF_COK, (FPTR)do_toggle,
"tomouse", 0, 0, (FPTR)do_tomouse,
"top", 0, 0, (FPTR)do_top,
"topedge", 1, CF_COK, (FPTR)do_windowparm,
"unblock", 0, 0, (FPTR)do_block,
"undo", 0, 0, (FPTR)do_undo,
"unmap", 1, CF_ICO|CF_COK, (FPTR)do_unmap,
"unset", 1, CF_ICO|CF_COK, (FPTR)do_unset,
"unsetenv", 1, CF_ICO|CF_COK, (FPTR)do_unsetenv,
"up", 0, 0, (FPTR)do_up,
"while", 2, CF_ICO|CF_COK, (FPTR)do_if,
"width", 1, CF_COK, (FPTR)do_windowparm,
"wleft", 0, CF_COK, (FPTR)do_wleft,
"wordwrap", 1, CF_COK, (FPTR)do_wordwrap,
"wright", 0, CF_COK, (FPTR)do_wright,
NULL, 0, 0, NULL
};
void
init_command()
{
register short hi;
register COMM *comm;
hi = sizeof(Comm)/sizeof(Comm[0]) - 2;
comm = Comm + hi;
while (hi >= 0) {
hindex[comm->name[0] - 'a'] = hi;
--hi;
--comm;
}
}
#define MAXIA 5
do_command(str)
char *str;
{
register char *arg;
char *aux1, *aux2;
char *repstr[MAXIA];
char quoted;
short repi = 0;
register short i, j;
static int level;
if (++level > 20) {
title("Recursion Too Deep!");
--level;
#if AREXX
foundcmd = 1; /* to prevent us from trying an ARexx macro */
#endif
return(0);
}
while (arg = breakout(&str, "ed, &aux1)) {
if (quoted) {
if (Ep->iconmode)
uniconify();
text_write(arg);
goto loop;
}
for (i = 0; arg[i]; ++i) {
if (arg[i] >= 'A' && arg[i] <= 'Z')
arg[i] += 'a' - 'A';
}
if (arg[0] >= 'a' && arg[0] <= 'z') {
register COMM *comm = &Comm[hindex[arg[0]-'a']];
for (; comm->name && comm->name[0] == arg[0]; ++comm) {
if (strcmp(arg, comm->name) == 0) {
#if AREXX
foundcmd = 1;
#endif
av[0] = (ubyte *)comm->name;
for (j = 1; j <= comm->args; ++j) {
av[j] = (ubyte *)breakout(&str, "ed, &aux2);
if (aux2) {
if (repi == MAXIA) {
free(aux2);
title("Command too complex");
goto fail;
} else {
repstr[repi++] = aux2;
}
}
if (!av[j]) {
title("Bad argument");
goto fail;
}
}
av[j] = NULL; /* end of arglist */
if ((comm->flags & CF_COK) || !Comlinemode) {
if (comm->flags & CF_PAR) {
if (Partial)
free(Partial);
Partial = (char *)malloc(strlen(str)+1);
strcpy(Partial, str);
str += strlen(str); /* skip string */
}
if (Ep->iconmode && !(comm->flags & CF_ICO))
uniconify();
(*comm->func)(-1);
}
if (Abortcommand)
goto fail;
goto loop;
}
}
}
/* Command not found, check for macro */
{
char *str;
int ret;
if ((str = keyspectomacro(arg)) || (str = menutomacro(arg))) {
str = (char *)strcpy(malloc(strlen(str)+1), str);
ret = do_command(str);
free(str);
#if AREXX
if (ret) {
foundcmd = 1; /* dunno about this yet for ARexx macros */
goto loop;
}
#else
if (ret)
goto loop;
#endif
goto fail;
}
}
/* Command still not found, check for public macro */
/* code to be added */
#if AREXX
do_rxImplied(arg, str);
#else
title("Unknown Command");
#endif
fail:
--level;
while (--repi >= 0)
free(repstr[repi]);
if (aux1)
free(aux1);
return(0);
loop:
if (aux1)
free(aux1);
}
--level;
while (--repi >= 0)
free(repstr[repi]);
return(1);
}
void
do_null()
{
}
void
do_source()
{
char buf[256];
void *xfi;
register char *str;
long oldlock = CurrentDir(DupLock(Ep->dirlock));
if (xfi = xfopen(av[1], "r", 512)) {
while (xfgets(xfi, buf, 256) >= 0) {
if (buf[0] == '#')
continue;
for (str = buf; *str; ++str) {
if (*str == 9)
*str = ' ';
}
do_command(buf);
}
xfclose(xfi);
} else {
if (av[0])
title("File not found");
}
UnLock(CurrentDir(oldlock));
}
void
do_quit()
{
extern char Quitflag;
Quitflag = 1;
}
void
do_execute()
{
long oldlock = CurrentDir(Ep->dirlock);
long NilFH = Open("null:", 1006);
PROC *proc = (PROC *)FindTask(NULL);
if (NilFH) {
proc->pr_ConsoleTask = (APTR)BTOCP(NilFH, struct FileHandle *)->fh_Port;
Execute(av[1], NilFH, NilFH);
Close(NilFH);
} else {
title("NULL: device required for (execute)");
}
CurrentDir(oldlock);
}
/*
* repeat X command
*
* Since repeat takes up 512+ stack, it should not be nested more than
* twice.
*
* (if X is not a number it can be abbr. with 2 chars)
*
* X = N -number of repeats
* line -current line # (lines begin at 1)
* lbot -#lines to the bottom, inc. current
* cleft -column # (columns begin at 0)
* (thus is also chars to the left)
* cright-#chars to eol, including current char
* tr -#char positions to get to next tab stop
* tl -#char positions to get to next backtab stop
*/
#define SC(a,b) ((a)<<8|(b))
void
do_repeat()
{
register ubyte *ptr = av[1];
register unsigned long n;
char buf1[256];
char buf2[256];
breakreset();
strcpy(buf1, av[2]);
switch((ptr[0]<<8)+ptr[1]) {
case SC('l','i'):
n = text_lineno();
break;
case SC('l','b'):
n = text_lines() - text_lineno() + 1;
break;
case SC('c','l'):
n = text_colno();
break;
case SC('c','r'):
n = text_cols() - text_colno();
break;
case SC('t','r'):
n = text_tabsize()-(text_colno() % text_tabsize());
break;
case SC('t','l'):
n = text_colno() % text_tabsize();
if (n == 0)
n = text_tabsize();
break;
default:
n = atoi(av[1]);
break;
}
while (n > 0) {
strcpy(buf2, buf1);
if (do_command(buf2) == 0 || breakcheck()) {
Abortcommand = 1;
break;
}
--n;
}
}
/*
* BREAKOUT()
*
* Break out the next argument. The argument is space delimited and
* might be quoted with `' or (), or single quoted as 'c or )c
*
* Also: $var -variable insertion
* ^c -control character
*/
char *
breakout(ptr, quoted, paux)
register char **ptr;
char **paux;
char *quoted;
{
register char *str = *ptr;
char *base;
short count = 0;
char opc = 0;
char clc = 0;
char immode = 0;
char isaux = 0;
char buf[256];
short di = 0;
*quoted = 0;
*paux = NULL;
while (*str == ' ')
++str;
if (!*str)
return(NULL);
*ptr = str;
base = str;
while (*str) {
if (immode) {
if (di != sizeof(buf)-1)
buf[di++] = *str;
++str;
continue;
}
if (count == 0) {
if (*str == ' ')
break;
if (*str == '\'' || *str == ')')
clc = *str;
if (*str == '`') {
opc = '`';
clc = '\'';
}
if (*str == '(') {
opc = '(';
clc = ')';
}
}
if (*str == opc) {
++count;
if (str == *ptr) {
*quoted = 1;
base = ++str;
continue;
}
}
if (*str == clc) {
--count;
if (count == 0 && *quoted) /* end of argument */
break;
if (str == *ptr && count < 0) {
immode = 1;
*quoted = 1;
base = ++str;
continue;
}
}
/*
* $varname $(varname) $`varname'. I.E. three forms are allowed,
* which allows one to insert the string almost anywhere. The
* first form names are limited to alpha-numerics, '-', and '_'.
*/
if (*str == '$') {
register char *ptr;
char *tmpptr;
char c, ce;
short len;
ce = 0; /* first form */
++str; /* skip $ */
if (*str == '(') { /* second form */
ce = ')';
++str;
} else if (*str == '`') { /* third form */
ce = '\'';
++str;
}
ptr = str; /* start of varname */
if (ce) { /* until end char OR */
while (*ptr && *ptr != ce)
++ptr;
} else { /* smart end-varname */
while ((*ptr >= 'a' && *ptr <= 'z') ||
(*ptr >= 'A' && *ptr <= 'Z') ||
(*ptr >= '0' && *ptr <= '9') ||
*ptr == '-' || *ptr == '_' ) {
++ptr;
}
}
len = ptr - str; /* length of variable */
c = *ptr; *ptr = 0; /* temp. terminate \0 */
if (strcmp(str, "scanf") == 0) {
*ptr = c;
isaux = 1;
if (di + strlen(String) < sizeof(buf)-1) {
strcpy(buf + di, String);
di += strlen(buf + di);
}
str += len; /* next string pos */
if (ce)
++str;
continue;
}
if (strcmp(str, "fpath") == 0) {
register short i;
for (i = strlen(Ep->Name); i >= 0; --i) {
if (Ep->Name[i] == ':' || Ep->Name[i] == '/')
break;
}
++i;
*ptr = c;
isaux = 1;
if (di + i < sizeof(buf)-1) {
BMov(Ep->Name, buf + di, i);
di += i;
buf[di] = 0;
}
str += len;
if (ce)
++str;
continue;
}
if (strcmp(str, "fname") == 0) {
register short i;
short j;
for (i = strlen(Ep->Name); i >= 0; --i) {
if (Ep->Name[i] == ':' || Ep->Name[i] == '/')
break;
}
++i;
j = strlen(Ep->Name + i);
*ptr = c;
isaux = 1;
if (di + j < sizeof(buf)-1) {
BMov(Ep->Name + i, buf + di, j);
di += j;
buf[di] = 0;
}
str += len;
if (ce)
++str;
continue;
}
if (strcmp(str, "filename") == 0) {
*ptr = c;
isaux = 1;
if (di + strlen(Ep->Name) < sizeof(buf)-1) {
strcpy(buf + di, Ep->Name);
di += strlen(buf + di);
}
str += len;
if (ce)
++str;
continue;
}
if (strcmp(str, "colno") == 0) {
*ptr = c;
isaux = 1;
if (di < sizeof(buf)-8) {
sprintf(buf + di, "%ld", Ep->Column + 1);
di += strlen(buf + di);
}
str += len;
if (ce)
++str;
continue;
}
if (strcmp(str, "lineno") == 0) {
*ptr = c;
isaux = 1;
if (di < sizeof(buf)-8) {
sprintf(buf + di, "%ld", Ep->Line + 1);
di += strlen(buf + di);
}
str += len;
if (ce)
++str;
continue;
}
if (tmpptr = getvar(str)) {
ptr = tmpptr;
str[len] = c;
isaux = 1;
if (di + strlen(ptr) < sizeof(buf)-1) {
strcpy(buf + di, ptr);
di += strlen(buf + di);
}
str += len;
if (ce)
++str;
free(ptr);
continue;
}
*ptr = c;
--str;
if (ce)
--str;
}
if (*str == '^' && (str[1] & 0x1F)) {
++str;
*str &= 0x1F;
isaux = 1;
}
if (*str == '\\' && str[1]) {
++str;
isaux = 1;
}
buf[di++] = *str++;
}
buf[di++] = 0;
if (isaux) {
*paux = malloc(di);
strcpy(*paux, buf);
base = *paux;
}
if (*str) { /* space ended */
*str = '\0';
*ptr = str + 1; /* next arg */
} else {
*ptr = str; /* last arg */
}
return(base);
}