1/* 2 * Macros for processing command arguments. 3 * 4 * Conforms closely to the command option requirements of intro(1) in System V 5 * and intro(C) in Xenix. 6 * 7 * A command consists of: cmdname [ options ] [ cmdarguments ] 8 * 9 * Options consist of a leading dash '-' and a flag letter. An argument may 10 * follow optionally preceded by white space. 11 * Options without arguments may be grouped behind a single dash. 12 * A dash on its own is interpreted as the end of the options and is retained 13 * as a command argument. 14 * A double dash '--' is interpreted as the end of the options and is discarded. 15 * 16 * For example: 17 * zap -xz -f flame -q34 -- -x 18 * 19 * where zap.c contains the following in main(): 20 * 21 * OPTIONS("[-xz] [-q queue-id] [-f dump-file] user") 22 * FLAG('x', xecute) 23 * FLAG('z', zot) 24 * STRING('f', file) 25 * fp = fopen(file, "w"); 26 * NUMBER('q', queue) 27 * ENDOPTS 28 * 29 * Results in: 30 * xecute = 1 31 * zot = 1 32 * file = "flame" 33 * fp = fopen("flame", "w") 34 * queue = 34 35 * argc = 2 36 * argv[0] = "zap" 37 * argv[1] = "-x" 38 * 39 * Should the user enter unknown flags or leave out required arguments, 40 * the message: 41 * 42 * Usage: zap [-xz] [-q queue-id] [-f dump-file] user 43 * 44 * will be printed. This message can be printed by calling pusage(), or 45 * usage(). usage() will also cause program termination with exit code 1. 46 * 47 * Author: Stephen McKay, February 1991 48 * 49 * Based on recollection of the original options.h produced at the University 50 * of Queensland by Ross Patterson (and possibly others). 51 * 52 * $FreeBSD$ 53 */ 54 55static char *O_usage; 56static char *O_name; 57extern long atol(); 58 59void 60pusage() 61 { 62 /* 63 * Avoid gratuitously loading stdio. 64 */ 65 write(STDERR_FILENO, "usage: ", 7); 66 write(STDERR_FILENO, O_name, strlen(O_name)); 67 write(STDERR_FILENO, " ", 1); 68 write(STDERR_FILENO, O_usage, strlen(O_usage)); 69 write(STDERR_FILENO, "\n", 1); 70 } 71 72#define usage() (pusage(), exit(1)) 73 74#define OPTIONS(usage_msg) \ 75 { \ 76 char O_cont; \ 77 O_usage = (usage_msg); \ 78 O_name = argv[0]; \ 79 while (*++argv && **argv == '-') \ 80 { \ 81 if ((*argv)[1] == '\0') \ 82 break; \ 83 argc--; \ 84 if ((*argv)[1] == '-' && (*argv)[2] == '\0') \ 85 { \ 86 argv++; \ 87 break; \ 88 } \ 89 O_cont = 1; \ 90 while (O_cont) \ 91 switch (*++*argv) \ 92 { \ 93 default: \ 94 case '-': \ 95 usage(); \ 96 case '\0': \ 97 O_cont = 0; 98 99#define FLAG(x,flag) \ 100 break; \ 101 case (x): \ 102 (flag) = 1; 103 104#define CHAR(x,ch) \ 105 break; \ 106 case (x): \ 107 O_cont = 0; \ 108 if (*++*argv == '\0' && (--argc, *++argv == 0)) \ 109 usage(); \ 110 (ch) = **argv; 111 112#define NUMBER(x,n) \ 113 break; \ 114 case (x): \ 115 O_cont = 0; \ 116 if (*++*argv == '\0' && (--argc, *++argv == 0)) \ 117 usage(); \ 118 (n) = atol(*argv); 119 120#define STRING(x,str) \ 121 break; \ 122 case (x): \ 123 O_cont = 0; \ 124 if (*++*argv == '\0' && (--argc, *++argv == 0)) \ 125 usage(); \ 126 (str) = *argv; 127 128#define SUFFIX(x,str) \ 129 break; \ 130 case (x): \ 131 (str) = ++*argv; \ 132 O_cont = 0; 133 134#define ENDOPTS \ 135 break; \ 136 } \ 137 } \ 138 *--argv = O_name; \ 139 } 140