This is mshell.c in view mode; [Download] [Up]
/*
* $Id: mshell.c,v 1.3.1.1 1997/05/22 20:16:34 ettore Exp $
*
* This file is part of VICE, the Versatile Commodore Emulator.
* See README for copyright notice
*
* This file contains simple user interface for the ML monitor in x64.
* Included are:
* o Input line
* o Split line
* o Evaluate numeric values
* o Evaluate command
*
*
* Written by
* Jarkko Sonninen (sonninen@lut.fi)
* Jouko Valta (jopi@stekt.oulu.fi)
*
*
* $Log: mshell.c,v $
* Revision 1.3.1.1 1997/05/22 20:16:34 ettore
* #include "vice.h" instead of the old "config.h".
*
* Revision 1.3 1996/04/01 09:01:41 jopi
* *** empty log message ***
*
* Revision 1.2 1995/04/01 07:54:09 jopi
* X64 0.3 PL 0
* In case of argument count mismatch, now shows all possible commands.
*
* Revision 1.1 1994/12/12 16:59:44 jopi
* Initial revision
*
*
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include "vice.h"
#include "types.h"
#include "mshell.h"
/* extern */
/*static void pack_args( int start );*/
#ifdef EDIT
extern void add_history ( char *str );
extern char *readline ( char *prompt );
#endif
/*
* Terminal Interface
*/
char *read_line(char *prompt, int mode)
{
char *linep, *r_linep;
#ifndef EDIT
static char line[256];
fputs(prompt, stdout);
fflush(stdout);
r_linep = linep = fgets(line, 255, stdin);
#else
r_linep = linep = readline(prompt);
if (linep && *linep)
add_history(linep);
#endif
while (r_linep && *r_linep && isspace((int)*r_linep))
r_linep++;
return (r_linep);
}
int split_args(char *line, int mode, int maxarg, int maxval, char **args, int *values, int *types)
{
int len, i, count;
int quote = 0;
char *p, *r;
if (!line || !*line)
return (0);
len = strlen(line);
/* split command line to table and parse possible numeric values */
quote = count = 0;
for (i = 0; i < maxarg; i++) {
values[i] = 0;
types[i] = 0;
args[i] = NULL;
}
p = r = line;
do {
if (*p == '\'' && quote != 1) {
if (!quote && p[1] && p[2] == '\'') { /* Single byte */
values[count] = p[1];
types[count] = T_NUMBER;
p += 2;
} else {
quote ^= 2;
types[count] = T_QUOTED;
}
} else if (*p == '"' && quote != 2) {
quote ^= 1;
types[count] = T_QUOTED;
} else if (!*p || (!quote && strchr(" \t\n,", *p))) {
*p = '\0';
/* r points to start of current word */
if (*r) {
if (*r == '\'' || *r == '"') {
if (*(p-1) == *r)
*(p-1) = 0;
r++;
}
args[count] = r;
if (types[count] == T_QUOTED) {
values[count] = strlen(r);
} else {
int cb = 0;
if (*r == '+') {
cb++; r++;
}
if (count && sconv(r, 0, mode | MODE_QUERY)) {
values[count] = sconv(r, 0, mode);
if (cb) values[count] += values[count-1];
if (values[count] > maxval+1) {
values[count] &= maxval;
printf("Value too large\n");
}
types[count] = T_NUMBER;
/* formats: "m 400 4ff", "m 400,4ff"
* ("m 400-4ff"), ("m 400+ff"), "m 400 +ff"
*/
} else {
values[count] = strlen(r);
types[count] = T_OTHER;
}
} /* if (types */
count++;
} /* if (*r) */
r = p+1; /* skips leading whitespace */
} /* else discard character */
} while (++p && len-- && count < maxarg);
#if 0
for (i = 0; i < maxarg; i++) {
printf ("arg %2d = '%s' \ttype %01s value %d\n",
i, args[i] ? args[i] :"", (types[i])+"-QNS", values[i]);
}
#endif
return (count);
}
/*
* Execute Command
* Find the nearest match for given command and execute it. Finally,
* return the result or error.
*/
int eval_command(char *command, int nargs, struct ms_table *cmds)
{
int i, j, b = 0, bi = 0;
char *p=NULL, *q;
if (!nargs || !command || !*command)
return (0);
/* now search through command table and find nearest command */
b = 0;
for (i = 0; cmds[i].command; i++) {
for (p = cmds[i].command, q = command, j = 0;
*p && *q && *p == *q; p++, q++, j++);
/*
* printf ("compare %s %s - %d %d %d\n", cmds[i].command,
* command, j, b, bi);
*/
if (j > b && !*q) {
b = j;
bi = i;
/* found an exact command */
if (*p == *q)
break;
}
} /* for */
/* command should have been identified by now */
if (b) {
if (nargs - 1 > cmds[bi].max_args ||
nargs - 1 < cmds[bi].min_args) {
printf("\nWrong number of arguments.\n");
if (!*p) /* exact */
printf("%s\n", cmds[bi].help_line);
else {
j = strlen(command);
/*printf("Precedence is as follows:\n\n");*/
for (i = 0; cmds[i].command; i++) {
if (!strncmp(cmds[i].command, command, j))
printf(" %s", cmds[i].help_line);
}
}
printf("\n");
return (0);
}
return ( (*cmds[bi].funcp)() );
}
return (-1); /* Command not recognized */
}
/*
* Numeric evaluation with error checking
*
* char *s; pointer to input string
* int level; recursion level
* int mode; flag: dec/hex mode
*/
int sconv(char *s, int level, int mode)
{
static char hexas[] = "0123456789abcdefg";
char *p = s;
int base = 0;
int result = 0, sign = 1;
int i = 0;
if (!p)
return (0);
switch (tolower(*p)) {
case '\'':
if (*(++p) == '\\' && p[2] == '\'') { /* Single Escaped byte */
++p;
*p = *p & 0x1f;
}
if (p[1] != '\'') { /* Single ASCII byte */
if (!(mode & MODE_QUERY))
printf ("Bad character near '\n");
return (0);
}
return ((mode & MODE_QUERY) ? 1 : *p);
case '%':
p++;
base = 2;
break;
case 'o':
case '&':
p++;
base = 8;
break;
case 'x':
case '$':
p++;
base = 16;
break;
case 'u':
case 'i':
case '#':
p++;
base = 10;
break;
case '0': /* 0x 0b 0d */
if (!*++p) return ((mode & MODE_QUERY) ? 1 : 0);
if (!isdigit((int)*p))
return (sconv(p, level+1, mode));
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
base = (mode & MODE_HEX) ? 16 : 10;
break;
case 'a':
case 'c':
case 'e':
case 'f':
if (mode & MODE_HEX)
base = 16;
break;
case 'b': /* hex or binary */
if (mode & MODE_HEX)
base = 16;
else {
base = 2;
p++;
}
break;
case 'd': /* hex or decimal */
if (mode & MODE_HEX)
base = 16;
else {
base = 10;
p++;
}
break;
default:
break;
}
/*
* now p points to start of string to convert and base hold its base
* number 2, 8, 10 or 16
*/
if (!base)
return (0);
if (*p == '-') {
sign = -1;
p++;
}
while (tolower(*p)) {
for (i = 0; i < base; i++)
if (tolower(*p) == hexas[i]) {
result = result * base + i;
break;
}
if (i >= base) {
/* unknown char has occurred, return value or error */
if (strchr(",-+()", *p) || isspace((int)*p))
i = 0;
else if (!level && !(mode & MODE_QUERY))
printf ("Bad character near '%s'\n", p);
break;
}
p++;
}
/* printf ("mode %02X last %d base %d value %d\n",
mode, i, base, result); */
/* return final value */
return ((mode & MODE_QUERY) ? (i < base) : result * sign);
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.