[Commit] nickle parse-args.5c, NONE, 1.1 ChangeLog, 1.44, 1.45 Makefile.am, 1.51, 1.52 version.m4, 1.11, 1.12

Bart Massey commit at keithp.com
Mon May 17 23:26:06 PDT 2004


Committed by: bart

Update of /local/src/CVS/nickle
In directory home.keithp.com:/tmp/cvs-serv32507

Modified Files:
	ChangeLog Makefile.am version.m4 
Added Files:
	parse-args.5c 
Log Message:
New argument parsing library.



--- NEW FILE: parse-args.5c ---
import File;
import String;

namespace ParseArgs {

    public typedef union {
	&bool arg_flag;
	&string arg_string;
	&int arg_int;
	&real arg_real;
	&(string[*]) arg_list;
    } arg_var;

    public typedef struct {
	arg_var var;
        int abbr;
	string name;
	string expr_name;
	string desc;
    } arg;

    public typedef struct {
	string prog_name;
	arg[*] args;
	&(string[*]) rest;
	&int unknown;
    } argdesc;

    string arg_string(arg a) {
	string stdarg() {
	    if (is_uninit(&a.name))
		return a.expr_name;
	    string s = "";
	    if (!is_uninit(&a.abbr))
		s += sprintf("-%c,", a.abbr);
	    s += sprintf("--%s", a.name);
	    return s;
	}
	union switch (a.var) {
	case arg_list:
	    return sprintf("%s ...", a.expr_name);
	case arg_flag:
	    return stdarg();
	default:
	    return sprintf("%s <%s>", stdarg(), a.expr_name);
	}
	abort("internal error");
    }

    void print_options(&(arg[*]) a) {
    }

    public string basename(string path) {
	int p = rindex(path, "/");
	if (p == -1)
	    return path;
	return substr(path, p + 1, length(path) - p - 1);
    }

    public void parseargs(&argdesc argd, &(string[*]) argv) {
	argd.prog_name = basename(argv[0]);

	arg[int] arg_abbr_hash = {};
	arg[string] arg_name_hash = {};
	for (int i = 0; i < dim(argd.args); i++) {
	    &arg d = &argd.args[i];
	    if (!is_uninit(&d.abbr))
		arg_abbr_hash[d.abbr] = d;
	    if (!is_uninit(&d.name))
		arg_name_hash[d.name] = d;
	}

	void usage() {
	    fprintf(stderr, "%s: usage: ", argd.prog_name);
	    fprintf(stderr, "%s <options>", argd.prog_name);
	    for (int i = 0; i < dim(argd.args); i++)
		if (is_uninit(&argd.args[i].name))
		    fprintf(stderr, " %s", arg_string(argd.args[i]));
	    fprintf(stderr, "\n");
	    for (int i = 0; i < dim(argd.args); i++)
		if (is_uninit(&argd.args[i].name))
		    fprintf(stderr, "    %s   %s\n",
			    argd.args[i].expr_name,
			    argd.args[i].desc);
	    for (int i = 0; i < dim(argd.args); i++)
		if (!is_uninit(&argd.args[i].name))
		    fprintf(stderr, "    %s   %s\n",
			    arg_string(argd.args[i]),
			    argd.args[i].desc);
	    exit(1);
	}

	int argi = 1;

	void save_value(&arg a, string value) {
	    union switch(a.var) {
	    case arg_flag var:
		var = true;
		break;
	    case arg_string var:
		var = value;
		break;
	    case arg_int var:
		var = atoi(value);
		break;
	    case arg_real var:
		var = atof(value);
		break;
	    case arg_list:
		abort("flagged list in argument description");
	    }
	}

	void process_flag(&arg a) {
	    if (argi >= dim(argv)) {
		fprintf(stderr, "%s: missing value for --%s\n",
			argd.prog_name, a.name);
		usage();
	    }
	    save_value(&a, argv[argi]);
	    argi++;
	}

	while(argi < dim(argv)) {
	    string a = argv[argi];
	    if (a == "" || a == "-" || a == "--") {
		if (is_uninit(&argd.unknown)) {
		    fprintf(stderr,
			    "%s: don't know what to do with arg \"%s\"\n",
			    argd.prog_name,
			    a);
			usage();
		}
		argd.unknown = argi + 1;
		return;
	    }
	    if (a[0] == '-' && a[1] != '-') {
		argi++;
		for (int i = 1; i < length(a); i++) {
		    if (!hash_test(arg_abbr_hash, a[i])) {
			fprintf(stderr, "%s: unknown flag char '-%c'\n",
				argd.prog_name,
				a[i]);
			usage();
		    }
		    process_flag(&arg_abbr_hash[a[i]]);
		}
		continue;
	    }
	    if (a[0] == '-' && a[1] == '-') {
		string argname = substr(a, 2, length(a) - 2);
		if (!hash_test(arg_name_hash, argname)) {
			fprintf(stderr, "%s: unknown flag \"--%s\"\n",
				argd.prog_name,
				argname);
			usage();
		}
		argi++;
		process_flag(&arg_name_hash[argname]);
		continue;
	    }
	    break;
	}
	for (int i = 0; i < dim(argd.args); i++) {
	    if (!is_uninit(&argd.args[i].name))
		continue;
	    if (argi >= dim(argv)) {
		fprintf(stderr, "%s: missing required argument %s\n",
			argd.prog_name, argd.args[i].expr_name);
		usage();
	    }
	    union switch (argd.args[i].var) {
	    case arg_list v:
		string[...] rest = {};
		v = rest;
		while(argi < dim(argv)) {
		    rest[argi] = argv[argi];
		    argi++;
		}
		return;
	    case arg_flag:
		abort("fixed flag in argument description");
	    default:
		save_value(&argd.args[i], argv[argi]);
		argi++;
	    }
	}
	if (argi < dim(argv)) {
	    fprintf(stderr, "%s: unknown or extra argument \"%s\"\n",
		    argv[argi],
		    argd.prog_name);
	    usage();
	}
    }
}

Index: ChangeLog
===================================================================
RCS file: /local/src/CVS/nickle/ChangeLog,v
retrieving revision 1.44
retrieving revision 1.45
diff -u -d -r1.44 -r1.45
--- a/ChangeLog	13 May 2004 22:17:20 -0000	1.44
+++ b/ChangeLog	18 May 2004 06:26:03 -0000	1.45
@@ -1,3 +1,12 @@
+2004-05-17  Bart Massey  <bart at cs.pdx.edu>
+
+	* parse-args.5c:
+	Added argument parser library.
+	* Makefile.am:
+	parse-args.5c will be installed.
+	* version.m4
+	Bumped the version to 2.32.
+
 2004-05-13  Bart Massey  <bart at cs.pdx.edu>
 
 	* string.5c:

Index: Makefile.am
===================================================================
RCS file: /local/src/CVS/nickle/Makefile.am,v
retrieving revision 1.51
retrieving revision 1.52
diff -u -d -r1.51 -r1.52
--- a/Makefile.am	1 Apr 2004 19:49:56 -0000	1.51
+++ b/Makefile.am	18 May 2004 06:26:03 -0000	1.52
@@ -9,7 +9,7 @@
 NICKLEFILES = builtin.5c math.5c scanf.5c mutex.5c \
 	arc4.5c prng.5c command.5c abort.5c \
         printf.5c history.5c ctype.5c string.5c socket.5c \
-	file.5c
+	file.5c parse-args.5c
 EXAMPLES = examples/circle.5c examples/comb.5c examples/kaiser.5c \
 	examples/miller-rabin.5c examples/numbers.5c examples/prime.5c \
 	examples/qbrating.5c examples/roman.5c examples/rsa-demo.5c \

Index: version.m4
===================================================================
RCS file: /local/src/CVS/nickle/version.m4,v
retrieving revision 1.11
retrieving revision 1.12
diff -u -d -r1.11 -r1.12
--- a/version.m4	16 Apr 2004 06:02:07 -0000	1.11
+++ b/version.m4	18 May 2004 06:26:03 -0000	1.12
@@ -1,7 +1,6 @@
-dnl This file is maintained automatically by update-version.sh
+dnl This file is used by update-version.sh
 dnl The file format is finicky, so do not hand-edit lightly.
-dnl Last updated Thu Apr 15 22:28:55 PDT 2004
 dnl CURHEADER $Header$
 dnl OLDHEADER <Header: /local/src/CVS/nickle/version.m4,v 1.10 2004/04/11 07:02:11 keithp Exp >
-dnl CURVERSION 2.31
-define([VERSION_NUMBER],[2.31])
+dnl CURVERSION 2.32
+define([VERSION_NUMBER],[2.32])




More information about the Commit mailing list