FreeCalypso > hg > fc-sim-tools
diff libcommon/dispatch.c @ 14:b7ee2e85686b
command dispatch and scripting factored out into libcommon
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sun, 14 Mar 2021 07:34:35 +0000 |
parents | simtool/dispatch.c@ddd767f6e15b |
children |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libcommon/dispatch.c Sun Mar 14 07:34:35 2021 +0000 @@ -0,0 +1,149 @@ +/* + * This module implements common command dispatch for our SIM tools. + */ + +#include <ctype.h> +#include <stdio.h> +#include <string.h> +#include <strings.h> +#include <stdlib.h> +#include "cmdtab.h" + +extern struct cmdtab cmdtab[]; + +static FILE * +handle_output_redir(str) + char *str; +{ + char *cp, *fn; + FILE *outf; + + for (cp = str; isspace(*cp); cp++) + ; + if (!*cp || *cp == '#') { + fprintf(stderr, "error: no filename after '>'\n"); + return(0); + } + for (fn = cp; *cp && !isspace(*cp); cp++) + ; + if (*cp) + *cp++ = '\0'; + while (isspace(*cp)) + cp++; + if (*cp && *cp != '#') { + fprintf(stderr, "error: invalid syntax after '>'\n"); + return(0); + } + outf = fopen(fn, "w"); + if (!outf) + perror(fn); + return outf; +} + +simtool_dispatch_cmd(cmd, is_script) + char *cmd; +{ + char *argv[20]; + char *cp, **ap; + struct cmdtab *tp; + FILE *outf; + int rc; + + for (cp = cmd; isspace(*cp); cp++) + ; + if (!*cp || *cp == '#') + return(0); + if (is_script) + printf("Script command: %s\n", cp); + if (*cp == '!') + return system(cp + 1); + argv[0] = cp; + while (*cp && !isspace(*cp)) + cp++; + if (*cp) + *cp++ = '\0'; + for (tp = cmdtab; tp->cmd; tp++) + if (!strcmp(tp->cmd, argv[0])) + break; + if (!tp->func) { + fprintf(stderr, "error: no such command\n"); + return(-1); + } + for (ap = argv + 1; ; ) { + while (isspace(*cp)) + cp++; + if (!*cp || *cp == '#' || *cp == '>') + break; + if (ap - argv - 1 >= tp->maxargs) { + fprintf(stderr, "error: too many arguments\n"); + return(-1); + } + if (*cp == '"') { + *ap++ = ++cp; + for (;;) { + if (!*cp) { +unterm_qstring: fprintf(stderr, + "error: unterminated quoted string\n"); + return(-1); + } + if (*cp == '"') + break; + if (*cp++ == '\\') { + if (!*cp) + goto unterm_qstring; + cp++; + } + } + *cp++ = '\0'; + } else { + *ap++ = cp; + while (*cp && !isspace(*cp)) + cp++; + if (*cp) + *cp++ = '\0'; + } + } + if (ap - argv - 1 < tp->minargs) { + fprintf(stderr, "error: too few arguments\n"); + return(-1); + } + *ap = 0; + if (*cp == '>') { + if (!tp->allow_redir) { + fprintf(stderr, + "error: command does not support output redirection\n"); + return(-1); + } + outf = handle_output_redir(cp + 1); + if (!outf) + return(-1); + } else + outf = stdout; + rc = tp->func(ap - argv, argv, outf); + if (outf != stdout) + fclose(outf); + return rc; +} + +dispatch_ready_argv(argc, argv) + char **argv; +{ + struct cmdtab *tp; + + for (tp = cmdtab; tp->cmd; tp++) + if (!strcmp(tp->cmd, argv[0])) + break; + if (!tp->func) { + fprintf(stderr, "error: no such command\n"); + return(-1); + } + if (argc - 1 > tp->maxargs) { + fprintf(stderr, "error: too many arguments\n"); + return(-1); + } + if (argc - 1 < tp->minargs) { + fprintf(stderr, "error: too few arguments\n"); + return(-1); + } + return tp->func(argc, argv, stdout); +}