home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fish 'n' More 2
/
fishmore-publicdomainlibraryvol.ii1991xetec.iso
/
fish
/
text
/
editors
/
dme_441
/
src
/
command.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-24
|
20KB
|
787 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"
Prototype void init_command (void);
Prototype int do_command (char *);
Prototype void do_null (void);
Prototype void do_source (void);
Prototype void do_quit (void);
Prototype void do_execute (void);
Prototype void do_repeat (void);
Prototype char *breakout (char **, char *, char **);
typedef struct Process PROC;
#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))
typedef void (*FPTR) ARGS((long));
typedef struct {
const char *name; /* command name */
ubyte args;
ubyte flags;
void (*func) ARGS((long)); /* function */
} COMM;
/*============================================================================*/
/*
* 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
*/
static unsigned char hindex[26]; /* alpha hash into table */
/* args flags */
static const 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,
"bgpen", 1, 0, (FPTR)do_bgpen,
"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,
"fgpen", 1, 0, (FPTR)do_fgpen,
"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,
"hgpen", 1, 0, (FPTR)do_hgpen,
"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,
"join", 0, 0, (FPTR)do_join,
"justify", 1, 0, (FPTR)do_justify,
"last", 0, CF_COK, (FPTR)do_lastcolumn,
"left", 0, CF_COK, (FPTR)do_left,
/*
"lrow", 1, CF_COK, (FPTR)do_lrow,
*/
"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,
"modified", 1, 0, (FPTR)do_modified,
"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,
"openwindow", 1, CF_ICO, (FPTR)do_openwindow,
"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,
"saveconfig", 0, CF_ICO|CF_COK, (FPTR)do_saveconfig,
"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,
"setparcol", 1, CF_COK, (FPTR)do_setparcol,
"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,
"title", 1, 0, (FPTR)do_title,
"tlate", 1, CF_COK, (FPTR)do_tlate,
"toggle", 1, CF_COK, (FPTR)do_toggle,
"tomouse", 0, 0, (FPTR)do_tomouse,
"top", 0, 0, (FPTR)do_top,
"tpen", 1, 0, (FPTR)do_tpen,
"unblock", 0, 0, (FPTR)do_block,
"undeline", 0, 0, (FPTR)do_undeline,
"undo", 0, 0, (FPTR)do_undo,
"unjustify", 0, 0, (FPTR)do_unjustify,
"unmap", 1, CF_ICO|CF_COK, (FPTR)do_unmap,
/*
"urow", 1, CF_COK, (FPTR)do_urow,
*/
"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,
"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()
{
short hi;
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;
{
char *arg;
char *aux1, *aux2;
char *repstr[MAXIA];
char quoted;
short repi = 0;
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') {
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];
FILE *fi;
char *str;
BPTR oldlock = CurrentDir(DupLock((BPTR)Ep->dirlock));
if (fi = fopen(av[1], "r")) {
while (fgets(buf, 256, fi)) {
if (buf[0] == '#')
continue;
for (str = buf; *str; ++str) {
if (*str == 9)
*str = ' ';
}
if (str > buf && str[-1] == '\n')
str[-1] = 0;
do_command(buf);
}
fclose(fi);
} else {
if (av[0])
title("File not found");
}
UnLock(CurrentDir(oldlock));
}
void
do_quit()
{
extern char Quitflag;
Quitflag = 1;
}
void
do_execute()
{
BPTR oldlock = CurrentDir((BPTR)Ep->dirlock);
BPTR NilFH = Open("null:", 1006);
PROC *proc = (PROC *)FindTask(NULL);
if (NilFH) {
void *oldConsoleTask = proc->pr_ConsoleTask;
proc->pr_ConsoleTask = (APTR)BTOCP(NilFH, struct FileHandle *)->fh_Port;
Execute(av[1], NilFH, NilFH);
proc->pr_ConsoleTask = oldConsoleTask;
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()
{
ubyte *ptr = av[1];
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)
char **ptr;
char **paux;
char *quoted;
{
char *str = *ptr;
char *base;
short count;
char opc;
char clc;
char immode;
char isaux;
char buf[256];
short di;
{
short z = 0;
count = z;
opc = z;
clc = z;
immode= z;
isaux = z;
di = z;
}
*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 == '$') {
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) {
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) {
movmem(Ep->Name, buf + di, i);
di += i;
buf[di] = 0;
}
str += len;
if (ce)
++str;
continue;
}
if (strcmp(str, "fname") == 0) {
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) {
movmem(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 (strcmp(str, "margin") == 0) { /* MMW */
*ptr = c;
isaux = 1;
if (di < sizeof(buf)-8) {
sprintf(buf + di, "%ld", Ep->Margin);
di += strlen(buf + di);
}
str += len;
if (ce)
++str;
continue;
}
if (strcmp(str, "modified") == 0) { /* MMW */
*ptr = c;
isaux = 1;
if (di < sizeof(buf)-8) {
sprintf(buf + di, "%ld", Ep->Modified ? 1 : 0);
di += strlen(buf + di);
}
str += len;
if (ce)
++str;
continue;
}
if (strcmp(str, "currentline") == 0) {
short i;
*ptr = c;
isaux = 1;
if (di < sizeof(buf)-8) {
for (i = strlen(Current) - 1; i >= 0 && Current[i] == ' '; --i);
++i;
if (i > 0)
strncpy(buf + di, Current, i);
*(buf + di + i) = 0;
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);
}