home *** CD-ROM | disk | FTP | other *** search
- Newsgroups: alt.sources
- From: peter@ficc.ferranti.com (Peter da Silva)
- Subject: Re: (yet Another test AND a PD getopt) AND symbol table routines
- Message-ID: <G4KBF.D@xds13.ferranti.com>
- Date: Sat, 25 May 91 16:24:46 GMT
-
- In article <1078@isgtec.UUCP> robert@isgtec.UUCP writes:
- > In article <3454@travis.csd.harris.com>, brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes:
- > |> getopt is a piece of crap.
-
- > You seem very, uumh, emotional about this.
-
- > |>Take Parseargs for example (which I released).
-
- > Ahhh, I see why.
-
- Actually, Parseargs was written by Eric Allman at Berkeley. I read his article
- in Unix Review about it, and got all excited (I've been very emotional about
- getopt myself for many years: it doesn't do enough to make it worth the
- hassle of remembering the options. Some of you might remember me flaming
- about it at Usenix a few years back). I got a copy of the program, adapted
- it to MS-DOS and AmigaOS, and released it as a portable argument parsing
- program. It enhances portability by using the native command line syntax
- no matter what O/S you're running it on.
-
- Anyway, after I released it Brad got all excited (apparently he had been
- bummed out about getopt too) and further enhanced it.
-
- So, he released it because he was emotional about it. Not the other way
- around.
-
- > For simple, ten line test programs, getopt is a quick way to
- > modify the way the program runs. Besides it pretty standard,
- > everybody knows how it works.
-
- Getopt reduces the coding effort over just banging the argv itself by
- about 10%. Why bother? Parseargs is a different kind of flying altogether.
- I use it all the time... for simple 10-line test programs even. And I get
- better programs than you do using getopt. For example:
-
- $ USAGE=3 userrep
- userrep: flag -x unknown
- Usage: userrep [-q] (quiet) [-g] (GeoTRIM) [-t] (ticks) [<FILES>]...
- Options:
- -q (quiet) Don't print headers
- -g (GeoTRIM) don't display users below geometric mean
- -t (ticks) Show time in raw ticks
- FILES file containing acctusers output
-
- All this is automatically generated by the parseargs program based on
- the argument descriptor table.
-
- The code? The program as a whole is pretty boring. I'll just provide the
- relevant fragments:
-
- /* process acctusers output file and generate summary statistics */
-
- ...
-
- #include <useful.h>
- #include <parseargs.h>
-
- BOOL killmeans = 0;
- BOOL quiet = 0;
- BOOL showticks = 0;
- struct arglist *Files = NULL;
-
- ARGDESC ArgDesc[] =
- {
- 'q', ARGOPT, argBool, __ &quiet,
- "quiet (Don't print headers)",
- 'g', ARGOPT, argBool, __ &killmeans,
- "GeoTRIM (don't display users below geometric mean)",
- 't', ARGOPT, argBool, __ &showticks,
- "ticks (Show time in raw ticks)",
- ' ', ARGOPT|ARGLIST, listStr, __ &Files,
- "FILES (file containing acctusers output)",
- ENDOFARGS
- };
-
- ...
-
- main(ac, av)
- int ac;
- char **av;
- {
- parseargs(av, ArgDesc);
- ...
- }
-
- OBcode: a set of handy little symbol table routines that I also found
- useful in this same program. The actual implementation is a little
- simplistic, but I haven't found any need to go into balanced binary
- trees or anything. The "char *" in symtab.h was supposed to be "void *",
- but one of our compilers barfed on that. Docco is minimal (basically,
- comments in the symtab.h file and the test program itself), but the code
- itself is pretty solid. Tested on System III and System V only, but
- runs on 286, 386 and 68000, so there are no promotion or byte order
- problems.
-
- #! /bin/sh
- # This is a shell archive. Remove anything before this line, then feed it
- # into a shell via "sh file" or similar. To overwrite existing files,
- # type "sh file -c".
- # The tool that generated this appeared in the comp.sources.unix newsgroup;
- # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
- # If this archive is complete, you will see the following message at the end:
- # "End of shell archive."
- # Contents: symtab.h symtab.c symtest.c
- # Wrapped by peter@ficc.uu.net on Sat May 25 11:17:55 1991
- PATH=/bin:/usr/bin:/usr/ucb ; export PATH
- if test -f 'symtab.h' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'symtab.h'\"
- else
- echo shar: Extracting \"'symtab.h'\" \(248 characters\)
- sed "s/^X//" >'symtab.h' <<'END_OF_FILE'
- Xtypedef char *symtab;
- X
- Xsymtab table(); /* table(int size, void (*init)(), void (*dispose)()) */
- Xchar *lookup(); /* lookup(symtab t, char *name); */
- Xvoid traverse(); /* traverse(symtab t, void (*func)()); */
- Xvoid dispose(); /* dispose(symtab t); */
- END_OF_FILE
- if test 248 -ne `wc -c <'symtab.h'`; then
- echo shar: \"'symtab.h'\" unpacked with wrong size!
- fi
- # end of 'symtab.h'
- fi
- if test -f 'symtab.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'symtab.c'\"
- else
- echo shar: Extracting \"'symtab.c'\" \(1960 characters\)
- sed "s/^X//" >'symtab.c' <<'END_OF_FILE'
- X#include <stdio.h>
- X
- Xchar *malloc();
- X
- Xstruct _e {
- X struct _e *left, *right;
- X char *name;
- X char data[1];
- X};
- X
- Xstruct _s {
- X struct _e *tree;
- X int size;
- X void (*init)();
- X void (*dispose)();
- X};
- X
- Xtypedef struct _s *symtab;
- X
- Xsymtab table(size, init, dispose)
- Xint size;
- Xvoid (*init)(), (*dispose)();
- X{
- X symtab t = (struct _s *) malloc(sizeof (struct _s));
- X if(!t) return 0;
- X t->tree = NULL;
- X t->size = size;
- X t->init = init;
- X t->dispose = dispose;
- X return t;
- X}
- X
- Xstatic struct _e *new_e(t, name)
- Xsymtab t;
- Xchar *name;
- X{
- X struct _e *tmp;
- X tmp = (struct _e *)malloc(sizeof(struct _e) + t->size);
- X if(!tmp) return NULL;
- X tmp->left = tmp->right = NULL;
- X tmp->name = (char *)malloc(strlen(name) + 1);
- X if(!tmp->name) {
- X free(tmp);
- X return NULL;
- X }
- X strcpy(tmp->name, name);
- X if(t->init) (*t->init)(tmp->data);
- X else {
- X /* Replace by bset or memset if you have it */
- X int i;
- X char *s;
- X for(s=tmp->data, i = t->size; i > 0; i--, s++)
- X *s = 0;
- X }
- X return tmp;
- X}
- X
- Xchar *lookup(t, name)
- Xsymtab t;
- Xchar *name;
- X{
- X struct _e *ptr, *parent;
- X int diff;
- X
- X ptr = t->tree;
- X parent = NULL;
- X if(!ptr) {
- X ptr = new_e(t, name);
- X if(!ptr) return NULL;
- X t->tree = ptr;
- X return ptr->data;
- X }
- X while(ptr) {
- X diff = strcmp(name, ptr->name);
- X if(diff==0) return ptr->data;
- X parent = ptr;
- X if(diff<0) ptr = ptr->left;
- X else ptr = ptr->right;
- X }
- X /* assert: parent != NULL */
- X ptr = new_e(t, name);
- X if(!ptr) return NULL;
- X if(diff<0) parent->left = ptr;
- X else parent->right = ptr;
- X return ptr->data;
- X}
- X
- Xstatic void dispose_e(t, e)
- Xsymtab t;
- Xstruct _e *e;
- X{
- X if(e->left) dispose_e(t, e->left);
- X if(e->right) dispose_e(t, e->right);
- X free(e->name);
- X if(t->dispose) (*t->dispose)(e->data);
- X free(e);
- X}
- X
- Xvoid dispose(t)
- Xsymtab t;
- X{
- X if(t->tree) dispose_e(t, t->tree);
- X free(t);
- X}
- X
- Xstatic void traverse_e(e, f)
- Xstruct _e *e;
- Xvoid (*f)();
- X{
- X if(e->left) traverse_e(e->left, f);
- X (*f)(e->name, e->data);
- X if(e->right) traverse_e(e->right, f);
- X}
- X
- Xvoid traverse(t, func)
- Xsymtab t;
- Xvoid (*func)();
- X{
- X if(t->tree) traverse_e(t->tree, func);
- X}
- END_OF_FILE
- if test 1960 -ne `wc -c <'symtab.c'`; then
- echo shar: \"'symtab.c'\" unpacked with wrong size!
- fi
- # end of 'symtab.c'
- fi
- if test -f 'symtest.c' -a "${1}" != "-c" ; then
- echo shar: Will not clobber existing file \"'symtest.c'\"
- else
- echo shar: Extracting \"'symtest.c'\" \(1600 characters\)
- sed "s/^X//" >'symtest.c' <<'END_OF_FILE'
- X/* Test symtab code */
- X#include <stdio.h>
- X#include <ctype.h>
- X#include "symtab.h"
- X
- Xchar *malloc();
- X
- Xstruct val {
- X int t;
- X union {
- X int i;
- X char *s;
- X } u;
- X};
- X
- X#define UNKNOWN 0
- X#define INT 1
- X#define STRING 2
- X
- Xval_init(v)
- Xstruct val *v;
- X{
- X v->t = UNKNOWN;
- X printf("Init\n");
- X}
- X
- Xval_dispose(v)
- Xstruct val *v;
- X{
- X if(v->t == STRING) {
- X printf("Disposing string \"%s\"\n", v->u.s);
- X free(v->u.s);
- X } else if(v->t == INT) {
- X printf("Disposing integer %d\n", v->u.i);
- X } else {
- X printf("Disposing unknown\n");
- X }
- X}
- X
- Xlist(n, v)
- Xchar *n;
- Xstruct val *v;
- X{
- X printf("%s ", n);
- X if(v->t == STRING) {
- X printf("\"%s\"\n", v->u.s);
- X } else if(v->t == INT) {
- X printf("%d\n", v->u.i);
- X } else {
- X printf("unknown\n");
- X }
- X}
- X
- Xmain()
- X{
- X char buf[BUFSIZ];
- X symtab valtab;
- X char *s, *name;
- X struct val *v;
- X valtab = table(sizeof(struct val), val_init, val_dispose);
- X if(!valtab) perror("table"), exit(1);
- X while(gets(buf)) {
- X s = buf;
- X while(isspace(*s)) s++;
- X name = s;
- X while(*s && !isspace(*s)) s++;
- X if(*s) {
- X *s = 0;
- X s++;
- X }
- X v = (struct val *)lookup(valtab, name);
- X if(!v) perror("lookup"), exit(1);
- X switch(v->t) {
- X case UNKNOWN:
- X if(!*s)
- X printf("%s Undefined\n", name);
- X else if(isdigit(*s)) {
- X v->t = INT;
- X v->u.i = atoi(s);
- X break;
- X } else {
- X v->u.s = malloc(strlen(s)+1);
- X if(!v->u.s) perror("copy"), exit(1);
- X strcpy(v->u.s, s);
- X v->t = STRING;
- X }
- X break;
- X case INT:
- X printf("%s = %d\n", name, v->u.i);
- X break;
- X case STRING:
- X printf("%s = \"%s\"\n", name, v->u.s);
- X break;
- X }
- X }
- X traverse(valtab, list);
- X dispose(valtab);
- X}
- END_OF_FILE
- if test 1600 -ne `wc -c <'symtest.c'`; then
- echo shar: \"'symtest.c'\" unpacked with wrong size!
- fi
- # end of 'symtest.c'
- fi
- echo shar: End of shell archive.
- exit 0
- --
- Peter da Silva; Ferranti International Controls Corporation; +1 713 274 5180;
- Sugar Land, TX 77487-5012; `-_-' "Have you hugged your wolf, today?"
-