home *** CD-ROM | disk | FTP | other *** search
/ Source Code 1992 March / Source_Code_CD-ROM_Walnut_Creek_March_1992.iso / usenet / altsrcs / 3 / 3422 < prev    next >
Encoding:
Text File  |  1991-05-26  |  9.1 KB  |  374 lines

  1. Newsgroups: alt.sources
  2. From: peter@ficc.ferranti.com (Peter da Silva)
  3. Subject: Re: (yet Another test AND a PD getopt) AND symbol table routines
  4. Message-ID: <G4KBF.D@xds13.ferranti.com>
  5. Date: Sat, 25 May 91 16:24:46 GMT
  6.  
  7. In article <1078@isgtec.UUCP> robert@isgtec.UUCP writes:
  8. > In article <3454@travis.csd.harris.com>, brad@SSD.CSD.HARRIS.COM (Brad Appleton) writes:
  9. > |> getopt is a piece of crap.
  10.  
  11. > You seem very, uumh, emotional about this.
  12.  
  13. > |>Take Parseargs for example (which I released).
  14.  
  15. > Ahhh,  I see why.
  16.  
  17. Actually, Parseargs was written by Eric Allman at Berkeley. I read his article
  18. in Unix Review about it, and got all excited (I've been very emotional about
  19. getopt myself for many years: it doesn't do enough to make it worth the
  20. hassle of remembering the options. Some of you might remember me flaming
  21. about it at Usenix a few years back). I got a copy of the program, adapted
  22. it to MS-DOS and AmigaOS, and released it as a portable argument parsing
  23. program. It enhances portability by using the native command line syntax
  24. no matter what O/S you're running it on.
  25.  
  26. Anyway, after I released it Brad got all excited (apparently he had been
  27. bummed out about getopt too) and further enhanced it.
  28.  
  29. So, he released it because he was emotional about it. Not the other way
  30. around.
  31.  
  32. > For simple,  ten line test programs,  getopt is a quick way to
  33. > modify the way the program runs.   Besides it pretty standard,
  34. > everybody knows how it works.
  35.  
  36. Getopt reduces the coding effort over just banging the argv itself by
  37. about 10%. Why bother? Parseargs is a different kind of flying altogether.
  38. I use it all the time... for simple 10-line test programs even. And I get
  39. better programs than you do using getopt. For example:
  40.  
  41. $ USAGE=3 userrep
  42. userrep: flag -x unknown
  43. Usage: userrep [-q] (quiet) [-g] (GeoTRIM) [-t] (ticks) [<FILES>]...
  44. Options:
  45.     -q (quiet)   Don't print headers
  46.     -g (GeoTRIM) don't display users below geometric mean
  47.     -t (ticks)   Show time in raw ticks
  48.        FILES     file containing acctusers output
  49.  
  50. All this is automatically generated by the parseargs program based on
  51. the argument descriptor table.
  52.  
  53. The code? The program as a whole is pretty boring. I'll just provide the
  54. relevant fragments:
  55.  
  56. /* process acctusers output file and generate summary statistics */
  57.  
  58. ...
  59.  
  60. #include <useful.h>
  61. #include <parseargs.h>
  62.  
  63. BOOL killmeans = 0;
  64. BOOL quiet = 0;
  65. BOOL showticks = 0;
  66. struct arglist *Files = NULL;
  67.  
  68. ARGDESC    ArgDesc[] =
  69. {
  70.     'q',    ARGOPT,        argBool,    __ &quiet,
  71.         "quiet (Don't print headers)",
  72.     'g',    ARGOPT,        argBool,    __ &killmeans,
  73.         "GeoTRIM (don't display users below geometric mean)",
  74.     't',    ARGOPT,        argBool,    __ &showticks,
  75.         "ticks (Show time in raw ticks)",
  76.     ' ',    ARGOPT|ARGLIST,    listStr,    __ &Files,
  77.         "FILES (file containing acctusers output)",
  78.     ENDOFARGS
  79. };
  80.  
  81. ...
  82.  
  83. main(ac, av)
  84. int ac;
  85. char **av;
  86. {
  87.     parseargs(av, ArgDesc);
  88.     ...
  89. }
  90.  
  91. OBcode: a set of handy little symbol table routines that I also found
  92. useful in this same program. The actual implementation is a little
  93. simplistic, but I haven't found any need to go into balanced binary
  94. trees or anything. The "char *" in symtab.h was supposed to be "void *",
  95. but one of our compilers barfed on that. Docco is minimal (basically,
  96. comments in the symtab.h file and the test program itself), but the code
  97. itself is pretty solid. Tested on System III and System V only, but
  98. runs on 286, 386 and 68000, so there are no promotion or byte order
  99. problems. 
  100.  
  101. #! /bin/sh
  102. # This is a shell archive.  Remove anything before this line, then feed it
  103. # into a shell via "sh file" or similar.  To overwrite existing files,
  104. # type "sh file -c".
  105. # The tool that generated this appeared in the comp.sources.unix newsgroup;
  106. # send mail to comp-sources-unix@uunet.uu.net if you want that tool.
  107. # If this archive is complete, you will see the following message at the end:
  108. #        "End of shell archive."
  109. # Contents:  symtab.h symtab.c symtest.c
  110. # Wrapped by peter@ficc.uu.net on Sat May 25 11:17:55 1991
  111. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  112. if test -f 'symtab.h' -a "${1}" != "-c" ; then 
  113.   echo shar: Will not clobber existing file \"'symtab.h'\"
  114. else
  115. echo shar: Extracting \"'symtab.h'\" \(248 characters\)
  116. sed "s/^X//" >'symtab.h' <<'END_OF_FILE'
  117. Xtypedef char *symtab;
  118. X
  119. Xsymtab table(); /* table(int size, void (*init)(), void (*dispose)()) */
  120. Xchar *lookup(); /* lookup(symtab t, char *name); */
  121. Xvoid traverse(); /* traverse(symtab t, void (*func)()); */
  122. Xvoid dispose(); /* dispose(symtab t); */
  123. END_OF_FILE
  124. if test 248 -ne `wc -c <'symtab.h'`; then
  125.     echo shar: \"'symtab.h'\" unpacked with wrong size!
  126. fi
  127. # end of 'symtab.h'
  128. fi
  129. if test -f 'symtab.c' -a "${1}" != "-c" ; then 
  130.   echo shar: Will not clobber existing file \"'symtab.c'\"
  131. else
  132. echo shar: Extracting \"'symtab.c'\" \(1960 characters\)
  133. sed "s/^X//" >'symtab.c' <<'END_OF_FILE'
  134. X#include <stdio.h>
  135. X
  136. Xchar *malloc();
  137. X
  138. Xstruct _e {
  139. X    struct _e *left, *right;
  140. X    char *name;
  141. X    char data[1];
  142. X};
  143. X
  144. Xstruct _s {
  145. X    struct _e *tree;
  146. X    int size;
  147. X    void (*init)();
  148. X    void (*dispose)();
  149. X};
  150. X
  151. Xtypedef struct _s *symtab;
  152. X
  153. Xsymtab table(size, init, dispose)
  154. Xint size;
  155. Xvoid (*init)(), (*dispose)();
  156. X{
  157. X    symtab t = (struct _s *) malloc(sizeof (struct _s));
  158. X    if(!t) return 0;
  159. X    t->tree = NULL;
  160. X    t->size = size;
  161. X    t->init = init;
  162. X    t->dispose = dispose;
  163. X    return t;
  164. X}
  165. X
  166. Xstatic struct _e *new_e(t, name)
  167. Xsymtab t;
  168. Xchar *name;
  169. X{
  170. X    struct _e *tmp;
  171. X    tmp = (struct _e *)malloc(sizeof(struct _e) + t->size);
  172. X    if(!tmp) return NULL;
  173. X    tmp->left = tmp->right = NULL;
  174. X    tmp->name = (char *)malloc(strlen(name) + 1);
  175. X    if(!tmp->name) {
  176. X        free(tmp);
  177. X        return NULL;
  178. X    }
  179. X    strcpy(tmp->name, name);
  180. X    if(t->init) (*t->init)(tmp->data);
  181. X    else {
  182. X        /* Replace by bset or memset if you have it */
  183. X        int i;
  184. X        char *s;
  185. X        for(s=tmp->data, i = t->size; i > 0; i--, s++)
  186. X            *s = 0;
  187. X    }
  188. X    return tmp;
  189. X}
  190. X
  191. Xchar *lookup(t, name)
  192. Xsymtab t;
  193. Xchar *name;
  194. X{
  195. X    struct _e *ptr, *parent;
  196. X    int diff;
  197. X
  198. X    ptr = t->tree;
  199. X    parent = NULL;
  200. X    if(!ptr) {
  201. X        ptr = new_e(t, name);
  202. X        if(!ptr) return NULL;
  203. X        t->tree = ptr;
  204. X        return ptr->data;
  205. X    }
  206. X    while(ptr) {
  207. X        diff = strcmp(name, ptr->name);
  208. X        if(diff==0) return ptr->data;
  209. X        parent = ptr;
  210. X        if(diff<0) ptr = ptr->left;
  211. X        else ptr = ptr->right;
  212. X    }
  213. X    /* assert: parent != NULL */
  214. X    ptr = new_e(t, name);
  215. X    if(!ptr) return NULL;
  216. X    if(diff<0) parent->left = ptr;
  217. X    else parent->right = ptr;
  218. X    return ptr->data;
  219. X}
  220. X
  221. Xstatic void dispose_e(t, e)
  222. Xsymtab t;
  223. Xstruct _e *e;
  224. X{
  225. X    if(e->left) dispose_e(t, e->left);
  226. X    if(e->right) dispose_e(t, e->right);
  227. X    free(e->name);
  228. X    if(t->dispose) (*t->dispose)(e->data);
  229. X    free(e);
  230. X}
  231. X
  232. Xvoid dispose(t)
  233. Xsymtab t;
  234. X{
  235. X    if(t->tree) dispose_e(t, t->tree);
  236. X    free(t);
  237. X}
  238. X
  239. Xstatic void traverse_e(e, f)
  240. Xstruct _e *e;
  241. Xvoid (*f)();
  242. X{
  243. X    if(e->left) traverse_e(e->left, f);
  244. X    (*f)(e->name, e->data);
  245. X    if(e->right) traverse_e(e->right, f);
  246. X}
  247. X
  248. Xvoid traverse(t, func)
  249. Xsymtab t;
  250. Xvoid (*func)();
  251. X{
  252. X    if(t->tree) traverse_e(t->tree, func);
  253. X}
  254. END_OF_FILE
  255. if test 1960 -ne `wc -c <'symtab.c'`; then
  256.     echo shar: \"'symtab.c'\" unpacked with wrong size!
  257. fi
  258. # end of 'symtab.c'
  259. fi
  260. if test -f 'symtest.c' -a "${1}" != "-c" ; then 
  261.   echo shar: Will not clobber existing file \"'symtest.c'\"
  262. else
  263. echo shar: Extracting \"'symtest.c'\" \(1600 characters\)
  264. sed "s/^X//" >'symtest.c' <<'END_OF_FILE'
  265. X/* Test symtab code */
  266. X#include <stdio.h>
  267. X#include <ctype.h>
  268. X#include "symtab.h"
  269. X
  270. Xchar *malloc();
  271. X
  272. Xstruct val {
  273. X    int t;
  274. X    union {
  275. X        int i;
  276. X        char *s;
  277. X    } u;
  278. X};
  279. X
  280. X#define UNKNOWN 0
  281. X#define INT 1
  282. X#define STRING 2
  283. X
  284. Xval_init(v)
  285. Xstruct val *v;
  286. X{
  287. X    v->t = UNKNOWN;
  288. X    printf("Init\n");
  289. X}
  290. X
  291. Xval_dispose(v)
  292. Xstruct val *v;
  293. X{
  294. X    if(v->t == STRING) {
  295. X        printf("Disposing string \"%s\"\n", v->u.s);
  296. X        free(v->u.s);
  297. X    } else if(v->t == INT) {
  298. X        printf("Disposing integer %d\n", v->u.i);
  299. X    } else {
  300. X        printf("Disposing unknown\n");
  301. X    }
  302. X}
  303. X
  304. Xlist(n, v)
  305. Xchar *n;
  306. Xstruct val *v;
  307. X{
  308. X    printf("%s ", n);
  309. X    if(v->t == STRING) {
  310. X        printf("\"%s\"\n", v->u.s);
  311. X    } else if(v->t == INT) {
  312. X        printf("%d\n", v->u.i);
  313. X    } else {
  314. X        printf("unknown\n");
  315. X    }
  316. X}
  317. X
  318. Xmain()
  319. X{
  320. X    char buf[BUFSIZ];
  321. X    symtab valtab;
  322. X    char *s, *name;
  323. X    struct val *v;
  324. X    valtab = table(sizeof(struct val), val_init, val_dispose);
  325. X    if(!valtab) perror("table"), exit(1);
  326. X    while(gets(buf)) {
  327. X        s = buf;
  328. X        while(isspace(*s)) s++;
  329. X        name = s;
  330. X        while(*s && !isspace(*s)) s++;
  331. X        if(*s) {
  332. X            *s = 0;
  333. X            s++;
  334. X        }
  335. X        v = (struct val *)lookup(valtab, name);
  336. X        if(!v) perror("lookup"), exit(1);
  337. X        switch(v->t) {
  338. X            case UNKNOWN:
  339. X                if(!*s)
  340. X                    printf("%s Undefined\n", name);
  341. X                else if(isdigit(*s)) {
  342. X                    v->t = INT;
  343. X                    v->u.i = atoi(s);
  344. X                    break;
  345. X                } else {
  346. X                    v->u.s = malloc(strlen(s)+1);
  347. X                    if(!v->u.s) perror("copy"), exit(1);
  348. X                    strcpy(v->u.s, s);
  349. X                    v->t = STRING;
  350. X                }
  351. X                break;
  352. X            case INT:
  353. X                printf("%s = %d\n", name, v->u.i);
  354. X                break;
  355. X            case STRING:
  356. X                printf("%s = \"%s\"\n", name, v->u.s);
  357. X                break;
  358. X        }
  359. X    }
  360. X    traverse(valtab, list);
  361. X    dispose(valtab);
  362. X}
  363. END_OF_FILE
  364. if test 1600 -ne `wc -c <'symtest.c'`; then
  365.     echo shar: \"'symtest.c'\" unpacked with wrong size!
  366. fi
  367. # end of 'symtest.c'
  368. fi
  369. echo shar: End of shell archive.
  370. exit 0
  371. -- 
  372. Peter da Silva; Ferranti International Controls Corporation; +1 713 274 5180;
  373. Sugar Land, TX  77487-5012;         `-_-' "Have you hugged your wolf, today?"
  374.