summaryrefslogtreecommitdiff
path: root/src/token.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/token.c')
-rw-r--r--src/token.c257
1 files changed, 257 insertions, 0 deletions
diff --git a/src/token.c b/src/token.c
new file mode 100644
index 0000000..b71a6cb
--- /dev/null
+++ b/src/token.c
@@ -0,0 +1,257 @@
+/*
+
+ atarisio - A UNIX backend for an Atari SIO2PC lead.
+
+ Copyright (C) 2004 Ian Cowburn (ianc@noddybox.demon.co.uk)
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ -------------------------------------------------------------------------
+
+ Command parsing and execution
+
+*/
+static const char ident[]="$Id$";
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "token.h"
+
+static const char ident_h[]=ATARIOSIO_TOKEN_H;
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+#define MAX_ARGS 128
+
+
+/* ---------------------------------------- STATICS
+*/
+
+static int no_cmds=0;
+static Command *cmd_table=NULL;
+
+
+/* ---------------------------------------- PRIVATE FUNCTIONS
+*/
+static int QCompare(const void *a, const void *b)
+{
+ const Command *ca;
+ const Command *cb;
+
+ ca=a;
+ cb=b;
+
+ return strcmp(ca->cmd,cb->cmd);
+}
+
+
+static int BCompare(const void *a, const void *b)
+{
+ const Command *cb;
+
+ cb=b;
+
+ return strcmp(a,cb->cmd);
+}
+
+
+static char *GetToken(char **ptr)
+{
+ char qu=0;
+ char *tok;
+ char *p;
+
+ p=*ptr;
+
+ while(*p && isspace(*p))
+ p++;
+
+ if (!*p)
+ return NULL;
+
+ if (*p=='\'' || *p=='"')
+ qu=*p++;
+
+ tok=p;
+
+ if (qu)
+ {
+ while(*p && *p!=qu)
+ p++;
+
+ if (*p)
+ *p++=0;
+ else
+ printf("Warning: unterminated quotes\n");
+ }
+ else
+ {
+ while(*p && !isspace(*p))
+ p++;
+
+ if (*p)
+ *p++=0;
+ }
+
+ *ptr=p;
+
+ return tok;
+}
+
+static int Split(char *p, char **argv)
+{
+ int argc=0;
+
+ while((argv[argc]=GetToken(&p)))
+ {
+ if (argc==MAX_ARGS)
+ {
+ argv[argc]=0;
+ return argc;
+ }
+
+ argc++;
+ }
+
+ return argc;
+}
+
+
+static void ShowHelp(const char *usage, const char *help)
+{
+ int l;
+
+ printf("%s ",usage);
+
+ for(l=strlen(usage);l<35;l++)
+ putchar('.');
+
+ printf(" %s\n",help);
+}
+
+
+static void HelpCommand(int argc, char *argv[])
+{
+ if (argc==1)
+ {
+ int f;
+
+ for(f=0;f<no_cmds;f++)
+ ShowHelp(cmd_table[f].usage,cmd_table[f].help);
+ }
+ else
+ {
+ Command *cmd;
+
+ cmd=bsearch(argv[1],cmd_table,no_cmds,sizeof *cmd_table,BCompare);
+
+ if (!cmd)
+ printf("Unknown command: %s\n",argv[1]);
+ else
+ ShowHelp(cmd->usage,cmd->help);
+ }
+}
+
+
+static void Init(void)
+{
+ static Command cmd[]=
+ {
+ {"help",1,2,"help [command]","Get help on commands",HelpCommand}
+ };
+
+ static int init=FALSE;
+
+ if (!init)
+ {
+ init=TRUE;
+ TokenRegister(sizeof cmd/sizeof cmd[0],cmd);
+ }
+}
+
+
+/* ---------------------------------------- EXPORTED INTERFACES
+*/
+void TokenRegister(int no, const Command *cmds)
+{
+ Init();
+
+ cmd_table=Realloc(cmd_table,sizeof(*cmds)*(no+no_cmds));
+ memcpy(cmd_table+no_cmds,cmds,sizeof(*cmds)*no);
+ no_cmds+=no;
+ qsort(cmd_table,no_cmds,sizeof *cmd_table,QCompare);
+}
+
+
+int TokenRun(const char *line)
+{
+ char *p;
+ char *argv[MAX_ARGS];
+ int argc;
+ int res;
+ int l;
+
+ if (!(l=strlen(line)))
+ return FALSE;
+
+ res=FALSE;
+
+ p=StrCopy(line);
+
+ if (p[l-1]=='\n')
+ p[--l]=0;
+
+ argc=Split(p,argv);
+
+ if (argc)
+ {
+ Command *cmd;
+
+ cmd=bsearch(argv[0],cmd_table,no_cmds,sizeof *cmd_table,BCompare);
+
+ if (cmd)
+ {
+ if (argc>=cmd->min_args && argc<=cmd->max_args)
+ {
+ res=TRUE;
+ cmd->func(argc,argv);
+ }
+ else
+ {
+ printf("usage: %s\n",cmd->usage);
+ }
+ }
+ else
+ {
+ printf("Unrecognised command %s\n",argv[0]);
+ }
+ }
+
+ free(p);
+
+ return res;
+}
+
+
+/* END OF FILE */