]> git.mdlowis.com Git - proto/rc.git/commitdiff
switched option parseing to OPTBEGIN macro and deleted getop.c
authorMichael D. Lowis <mike.lowis@gentex.com>
Wed, 15 Mar 2017 12:43:07 +0000 (08:43 -0400)
committerMichael D. Lowis <mike.lowis@gentex.com>
Wed, 15 Mar 2017 12:43:07 +0000 (08:43 -0400)
Makefile
builtins.c
getopt.c [deleted file]
glom.c
input.c
main.c
rc.h
wait.c

index b9d28dec55eb45e95190883586debba430e939c8..f9df45913b6a8d9dd72d693b2971c9c4e95b59c5 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 CC = c99
 CPPFLAGS = -I.
 CCCMD = $(CC) $(CPPFLAGS) $(CFLAGS) -o $@ $^ $(LDFLAGS) $(LDLIBS)
-RCOBJS = builtins.o except.o exec.o fn.o footobar.o getopt.o glob.o glom.o hash.o heredoc.o input.o lex.o list.o main.o match.o nalloc.o open.o y.tab.o print.o redir.o signal.o status.o tree.o utils.o var.o wait.o walk.o which.o sigmsgs.o system.o
+RCOBJS = builtins.o except.o exec.o fn.o footobar.o glob.o glom.o hash.o heredoc.o input.o lex.o list.o main.o match.o nalloc.o open.o y.tab.o print.o redir.o signal.o status.o tree.o utils.o var.o wait.o walk.o which.o sigmsgs.o system.o
 
 all: rc
 
index 5349c22bac423aefb3e9b270d51b5fc371f3caca..9c56e40b2ff497508ceff64fb43c80c3c09ed9fc 100644 (file)
@@ -30,7 +30,6 @@ static struct {
        { b_shift,       "shift" },
        { b_umask,       "umask" },
        { b_wait,        "wait" },
-       { b_whatis,      "whatis" },
        { b_dot,         "." },
 };
 
@@ -261,70 +260,6 @@ static bool issig(char *s) {
        return FALSE;
 }
 
-static void b_whatis(char **av) {
-       bool ess, eff, vee, pee, bee;
-       bool f, found;
-       int i, ac, c;
-       List *s;
-       Node *n;
-       char *e;
-       for (rc_optind = ac = 0; av[ac] != NULL; ac++)
-               ; /* count the arguments for getopt */
-       ess = eff = vee = pee = bee = FALSE;
-       while ((c = rc_getopt(ac, av, "sfvpb")) != -1)
-               switch (c) {
-               default: set(FALSE); return;
-               case 's': ess = TRUE; break;
-               case 'f': eff = TRUE; break;
-               case 'v': vee = TRUE; break;
-               case 'p': pee = TRUE; break;
-               case 'b': bee = TRUE; break;
-               }
-       av += rc_optind;
-       if (*av == NULL) {
-               if (vee|eff)
-                       whatare_all_vars(eff, vee);
-               if (ess)
-                       whatare_all_signals();
-               if (bee)
-                       for (i = 0; i < arraysize(builtins); i++)
-                               fprint(1, "builtin %s\n", builtins[i].name);
-               if (pee)
-                       fprint(2, "whatis -p: must specify argument\n");
-               if (show(FALSE)) /* no options? */
-                       whatare_all_vars(TRUE, TRUE);
-               set(TRUE);
-               return;
-       }
-       found = TRUE;
-       for (i = 0; av[i] != NULL; i++) {
-               f = FALSE;
-               errno = ENOENT;
-               if (show(vee) && (s = varlookup(av[i])) != NULL) {
-                       f = TRUE;
-                       prettyprint_var(1, av[i], s);
-               }
-               if (((show(ess)&&issig(av[i])) || show(eff)) && (n = fnlookup(av[i])) != NULL) {
-                       f = TRUE;
-                       prettyprint_fn(1, av[i], n);
-               } else if (show(bee) && isbuiltin(av[i]) != NULL) {
-                       f = TRUE;
-                       fprint(1, "builtin %s\n", av[i]);
-               } else if (show(pee) && (e = which(av[i], FALSE)) != NULL) {
-                       f = TRUE;
-                       fprint(1, "%S\n", e);
-               }
-               if (!f) {
-                       found = FALSE;
-                       if (errno != ENOENT)
-                               uerror(av[i]);
-                       else
-                               fprint(2, "%s not found\n", av[i]);
-               }
-       }
-       set(found);
-}
-
 /* push a string to be eval'ed onto the input stack. evaluate it */
 
 static void b_eval(char **av) {
diff --git a/getopt.c b/getopt.c
deleted file mode 100644 (file)
index 3c54f53..0000000
--- a/getopt.c
+++ /dev/null
@@ -1,51 +0,0 @@
-#include "rc.h"
-
-int     rc_opterr = 1;
-int     rc_optind = 1;
-int     rc_optopt;
-char    *rc_optarg;
-
-/* getopt routine courtesy of David Sanderson */
-extern int rc_getopt(int argc, char **argv, char *opts) {
-        static int sp = 1;
-       int c;
-       char *cp;
-       if (rc_optind == 0) /* reset rc_getopt() */
-               rc_optind = sp = 1;
-       if (sp == 1) {
-               if (rc_optind >= argc || argv[rc_optind][0] != '-' || argv[rc_optind][1] == '\0') {
-                       return -1;
-               } else if (strcmp(argv[rc_optind], "--") == 0) {
-                       rc_optind++;
-                       return -1;
-               }
-       }
-       rc_optopt = c = argv[rc_optind][sp];
-       if (c == ':' || (cp=strchr(opts, c)) == 0) {
-               fprint(2, "%s: bad option: -%c\n", argv[0], c);
-               if (argv[rc_optind][++sp] == '\0') {
-                       rc_optind++;
-                       sp = 1;
-               }
-               return '?';
-       }
-       if (*++cp == ':') {
-               if (argv[rc_optind][sp+1] != '\0') {
-                       rc_optarg = &argv[rc_optind++][sp+1];
-               } else if (++rc_optind >= argc) {
-                       fprint(2, "%s: option requires an argument -- %c\n", argv[0], c);
-                       sp = 1;
-                       return '?';
-               } else
-                       rc_optarg = argv[rc_optind++];
-               sp = 1;
-       } else {
-               if (argv[rc_optind][++sp] == '\0') {
-                       sp = 1;
-                       rc_optind++;
-               }
-               rc_optarg = NULL;
-       }
-       return c;
-}
diff --git a/glom.c b/glom.c
index 86d3cf16198cd327112255ae6ee8967db8733364..1d4ebe1cead02daead6472a3a8c33134a1093e6f 100644 (file)
--- a/glom.c
+++ b/glom.c
@@ -200,7 +200,7 @@ static List *bqinput(List *ifs, int fd) {
                        end = &buf[m];
                        remain = bufsize - m;
                }
-               if ((n = rc_read(fd, end, remain)) <= 0) {
+               if ((n = read(fd, end, remain)) <= 0) {
                        if (n == 0)
        /* break */             break;
                        else if (errno == EINTR)
diff --git a/input.c b/input.c
index 697a04195f09917e1a07aa3659b4c55fc74a505c..ddd6c038692c52d54dd0de2f5d174e208243fc18 100644 (file)
--- a/input.c
+++ b/input.c
@@ -93,7 +93,7 @@ static int fdgchar() {
        if (chars_out >= chars_in) { /* replenish empty buffer */
                ssize_t r;
                do {
-                       r = rc_read(istack->fd, inbuf, BUFSIZE);
+                       r = read(istack->fd, inbuf, BUFSIZE);
                        sigchk();
                        if (r == -1)
                                switch (errno) {
diff --git a/main.c b/main.c
index 72f309c73d7e498b42d77af96a5a23c0cd436da3..aac9ddcffdcf7a4f63e6fade12d59ee514200352 100644 (file)
--- a/main.c
+++ b/main.c
@@ -2,6 +2,7 @@
 
 #include "rc.h"
 
+char* ARGV0;
 bool dashdee, dashee, dashvee, dashex, dasheye,
        dashen, dashpee, interactive;
 pid_t rc_pid;
@@ -11,58 +12,41 @@ static bool dashEYE, dashell, dashoh, dashess;
 static void assigndefault(char *,...);
 static void checkfd(int, enum redirtype);
 
+void usage(void) {
+       printf("Usage: %s [OPTION...] [FILE [ARG...]]\n", ARGV0);
+}
+
 extern int main(int argc, char *argv[], char *envp[]) {
        char *dashsee[2], *dollarzero, *null[1];
-       int c;
        initprint();
        dashsee[0] = dashsee[1] = NULL;
        dollarzero = argv[0];
        rc_pid = getpid();
-       dashell = (*argv[0] == '-'); /* Unix tradition */
-       while ((c = rc_getopt(argc, argv, "c:deiIlnopsvx")) != -1)
-               switch (c) {
-               case 'c':
-                       dashsee[0] = rc_optarg;
-                       goto quitopts;
-               case 'd':
-                       dashdee = TRUE;
-                       break;
-               case 'e':
-                       dashee = TRUE;
+       dashell = (*argv[0] == '-'); /* login shell, per unix tradition */
+       
+       OPTBEGIN {
+               case 'd': dashdee = TRUE; break;
+               case 'e': dashee  = TRUE; break;
+               case 'l': dashell = TRUE; break;
+               case 'n': dashen  = TRUE; break;
+               case 'o': dashoh  = TRUE; break;
+               case 'p': dashpee = TRUE; break;
+               case 's': dashess = TRUE; break;
+               case 'v': dashvee = TRUE; break;
+               case 'x': dashex  = TRUE; break;
+               case 'i': 
+                       dasheye = TRUE;
+                       interactive = TRUE; 
                        break;
                case 'I':
                        dashEYE = TRUE;
                        interactive = FALSE;
                        break;
-               case 'i':
-                       dasheye = interactive = TRUE;
-                       break;
-               case 'l':
-                       dashell = TRUE;
-                       break;
-               case 'n':
-                       dashen = TRUE;
-                       break;
-               case 'o':
-                       dashoh = TRUE;
-                       break;
-               case 'p':
-                       dashpee = TRUE;
-                       break;
-               case 's':
-                       dashess = TRUE;
-                       break;
-               case 'v':
-                       dashvee = TRUE;
-                       break;
-               case 'x':
-                       dashex = TRUE;
+               case 'c':
+                       dashsee[0] = EOPTARG(usage());
                        break;
-               case '?':
-                       exit(1);
-               }
-quitopts:
-       argv += rc_optind;
+       } OPTEND;
+
        /* use isatty() iff neither -i nor -I is set, and iff the input is not from a script or -c flags */
        if (!dasheye && !dashEYE && dashsee[0] == NULL && (dashess || *argv == NULL))
                interactive = isatty(0);
diff --git a/rc.h b/rc.h
index a3f3f229ade43d89469a91921f327b1893352753..29f51ae7e966a599a098bee12ae3eea6ad515bd5 100644 (file)
--- a/rc.h
+++ b/rc.h
@@ -7,6 +7,8 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <stdarg.h>
+#include <stdio.h>
+#include <stddef.h>
 #include <string.h>
 #include <errno.h>
 #include <assert.h>
@@ -83,6 +85,8 @@ struct Limit {
 
 #ifdef __DARWIN_NSIG 
        #define NSIG __DARWIN_NSIG
+#elif _NSIG
+       #define NSIG _NSIG
 #endif
 
 typedef struct {
@@ -225,10 +229,6 @@ enum {
 };
 
 /* macros */
-#define EOF (-1)
-#ifndef NULL
-#define NULL 0
-#endif
 #define a2u(x) n2u(x, 10)
 #define o2u(x) n2u(x, 8)
 #define arraysize(a) ((int)(sizeof(a)/sizeof(*a)))
@@ -402,7 +402,6 @@ extern struct Jbwrap rl_buf;
 /* redir.c */
 extern void doredirs(void);
 
-
 /* signal.c */
 extern void initsignal(void);
 extern void catcher(int);
@@ -411,7 +410,6 @@ extern void (*rc_signal(int, void (*)(int)))(int);
 extern void (*sys_signal(int, void (*)(int)))(int);
 extern void (*sighandlers[])(int);
 
-
 /* status.c */
 extern int istrue(void);
 extern int getstatus(void);
@@ -423,23 +421,9 @@ extern void statprint(pid_t, int);
 extern void ssetstatus(char **);
 extern char *strstatus(int s);
 
-
 /* system.c or system-bsd.c */
 extern void writeall(int, char *, size_t);
 
-#if HAVE_RESTARTABLE_SYSCALLS
-extern int rc_read(int, char *, size_t);
-extern pid_t rc_wait(int *);
-extern Jbwrap slowbuf;
-extern volatile sig_atomic_t slow;
-
-#else /* HAVE_RESTARTABLE_SYSCALLS */
-
-#define rc_read read
-#define rc_wait wait
-#endif /* HAVE_RESTARTABLE_SYSCALLS */
-
-
 /* tree.c */
 extern Node *mk(int /*nodetype*/,...);
 extern Node *treecpy(Node *, void *(*)(size_t));
@@ -483,9 +467,6 @@ extern void popinput(void);
 extern int gchar(void);
 extern void ugchar(int);
 
-/* $TERM or $TERMCAP has changed */
-extern void termchange(void);
-
 /* parse a function from the environment */
 extern Node *parseline(char *);
 
@@ -505,3 +486,102 @@ extern void closefds(void);
 extern int lastchar;
 
 
+/* Option Parsing
+ *
+ * This following macros implement a simple POSIX-style option parsing strategy.
+ * They are heavily influenced and inspired by the arg.h file from suckless.org
+ * (http://git.suckless.org/libsl/tree/arg.h). That file is in turn inspired by
+ * the corresponding macros defined in plan9.
+ *
+ * The interface assumes that the main function will have the following
+ * prototype:
+ *
+ * int main(int argc, char** argv);
+ *
+ * An example usage of the interface would look something like the follwoing:
+ *
+ * char* ARGV0;
+ * int main(int argc, char** argv) {
+ *     OPTBEGIN {
+ *         case 'a': printf("Simple option\n"); break;
+ *         case 'b': printf("Option with arg: %s\n", OPTARG()); break;
+ *         default:  printf("Unknown option!\n");
+ *     } OPTEND;
+ *     return 0;
+ * }
+ */
+
+/* This variable contains the value of argv[0] so that it can be referenced
+ * again once the option parsing is done. This variable must be defined by the
+ * program.
+ *
+ * NOTE: Ensure that you define this variable with external linkage (i.e. not
+ * static) */
+extern char* ARGV0;
+
+/* This is a helper function used by the following macros to parse the next
+ * option from the command line. */
+static inline char* _getopt_(int* p_argc, char*** p_argv) {
+    if (!(*p_argv)[0][1] && !(*p_argv)[1]) {
+        return (char*)0;
+    } else if ((*p_argv)[0][1]) {
+        return &(*p_argv)[0][1];
+    } else {
+        *p_argv = *p_argv + 1;
+        *p_argc = *p_argc - 1;
+        return (*p_argv)[0];
+    }
+}
+
+/* This macro is almost identical to the ARGBEGIN macro from suckless.org. If
+ * it ain't broke, don't fix it. */
+#define OPTBEGIN                                                              \
+    for (                                                                     \
+        ARGV0 = *argv, argc--, argv++;                                        \
+        argv[0] && argv[0][1] && argv[0][0] == '-';                           \
+        argc--, argv++                                                        \
+    ) {                                                                       \
+        int brk_; char argc_ , **argv_, *optarg_;                             \
+        if (argv[0][1] == '-' && !argv[0][2]) {                               \
+            argv++, argc--; break;                                            \
+        }                                                                     \
+        for (brk_=0, argv[0]++, argv_=argv; argv[0][0] && !brk_; argv[0]++) { \
+            if (argv_ != argv) break;                                         \
+            argc_ = argv[0][0];                                               \
+            switch (argc_)
+
+/* Terminate the option parsing. */
+#define OPTEND }}
+
+/* Get the current option character */
+#define OPTC() (argc_)
+
+/* Get an argument from the command line and return it as a string. If no
+ * argument is available, this macro returns NULL */
+#define OPTARG() \
+    (optarg_ = _getopt_(&argc,&argv), brk_ = (optarg_!=0), optarg_)
+
+/* Get an argument from the command line and return it as a string. If no
+ * argument is available, this macro executes the provided code. If that code
+ * returns, then abort is called. */
+#define EOPTARG(code) \
+    (optarg_ = _getopt_(&argc,&argv), \
+    (!optarg_ ? ((code), abort(), (char*)0) : (brk_ = 1, optarg_)))
+
+/* Helper macro to recognize number options */
+#define OPTNUM \
+    case '0':  \
+    case '1':  \
+    case '2':  \
+    case '3':  \
+    case '4':  \
+    case '5':  \
+    case '6':  \
+    case '7':  \
+    case '8':  \
+    case '9'
+
+/* Helper macro to recognize "long" options ala GNU style. */
+#define OPTLONG \
+    case '-'
+
diff --git a/wait.c b/wait.c
index 06d6271b1a5df6f68f07e3dd3cd84f6fd8c7d23f..91679b6d0416fce0901a9321cc0b08394a45089c 100644 (file)
--- a/wait.c
+++ b/wait.c
@@ -64,7 +64,7 @@ extern pid_t rc_wait4(pid_t pid, int *stat, bool nointr) {
                int ret;
                Pid *q;
 
-               ret = rc_wait(stat);
+               ret = wait(stat);
 
                if (ret < 0) {
                        if (errno == ECHILD)