[code/idea] Argument interpreter

From: Daniel Koepke (dkoepke@california.com)
Date: 02/21/97


I was trying to think of a newer way to parse arguments, in which you
wouldn't have to do the argument parsing from within each command
function. What I came up was an argument parser/interpreter. What it
does is takes a string and depending upon what the function is
expecting either splits it up into words or sends the string on (with
or without leading spaces trimmed).

Specifications:

  STRING : String with leading spaces removed
  STRING_SPACES : String with leading spaces intact
  WORDS : Split into words

  struct ArgType {
     int argc;
     char **argv;
  };

Argc is only zero when there is no arguments passed to the function.
argv[0] always holds the string, even for WORDS. In the case of
STRING and STRING_SPACES, argc equals 1 when a string was passed.
Note that OneWord and SkipSpaces are from CircleMud, they are not
the functions I use in my own mud, but I didn't want to include my
functions (after all, I'm not releasing my mud's code). Here goes
the code (note this in an individual program that demonstrates how
the ArgInterpreter() works, you'll have to implement into CircleMud
yourself):

  #include <stdio.h>
  #include <stdlib.h>

  #define STRING	0	// string w/o leading spaces
  #define STRING_SPACES	1	// string w/ leading spaces
  #define WORDS		2	// split string into words

  struct ArgType {
     int argc;
     char **argv;
  };

  void SkipSpaces(char **argument) {
    for (; **argument && isspace(**argument); (*argument)++);
  }

  char *OneWord(char *argument, char *first) {
    SkipSpaces(&argument);

    while (*argument && !isspace(*argument)) {
      *(first++) = tolower(*argument);
      argument++;
    }

    *first = '\0';
    return argument;
  }

  struct ArgType ArgInterpreter(char *str, int arg_data) {
    int was_space = 1, i = 0;
    struct ArgType ap;
    char word[256];
    char *tmp;

    const char *arg_types[] = {
      "STRING",
      "STRING_SPACES",
      "WORDS",
      "\n"
    };

    at.argc = 0;
    if (!str || !*str)
      return (at);

    if (arg_data != WORDS) {
      at.argc = 1;
      at.argv = (char **) calloc(1, sizeof(char *));
      if (arg_data == STRING) SkipSpaces(&str);
      at.argv[0] = strdup(str);
      printf("%s:%s\n", arg_types[arg_data], at.argv[0]);
      return (at);
    }

    SkipSpaces(&str);
    for (tmp = str; *tmp; tmp++)
      if (isspace(*tmp))
        was_space = 1;
      else if (was_space) {
        at.argc++;
        was_space = 0;
      }

    printf("%s: %d words\n", arg_types[arg_data], at.argc);
    at.argv = (char **) calloc(at.argc, sizeof(char *));

    do {
      i++; str = OneWord(str, word);
      if (word && *word) at.argv[i] = strdup(word);
      printf("%s: argv[%d]=%s\n", arg_types[arg_data], i, argv[i]);
    } while (*word && *str);

    return (at);
  }

  void main(void) {
    char *msg = "  Enter test string here.";
    struct ArgType argd;

    argd = ArgInterpreter(msg, STRING);
    argd = ArgInterpreter(msg, STRING_SPACES);
    argd = ArgInterpreter(msg, WORDS);
  }

This might make a good snippet. If anyone gets it into CircleMud,
then don't hesistate to inform me. Note, though, that it wouldn't be
a small task, as you'd have to change all the ACMD functions to
support it and the command table to include the arg_data thing (to
specify if the function should get STRING/STRING_SPACES/WORDS). But,
after those two things, changing the command_interpreter() to use
ArgInterpreter() is trivial.


--
Daniel Koepke
dkoepke@california.com
Forgive me father, for I am sin.
char m[35]="Yano eu!r'!dr!\ne!! !!!!!";void main(){int i=0,p;for(;i<3;i++,
p=0){for(;m[3*p+i]!='!';p++)printf("%c",m[3*p+i]);}}

+-----------------------------------------------------------+
| Ensure that you have read the CircleMUD Mailing List FAQ: |
|   http://cspo.queensu.ca/~fletcher/Circle/list_faq.html   |
|    Or send 'info circle' to majordomo@cspo.queensu.ca     |
+-----------------------------------------------------------+



This archive was generated by hypermail 2b30 : 12/18/00 PST