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
53static char *O_usage;
54static char *O_name;
55extern long atol();
56
57void
58pusage()
59 {
60 /*
61 * Avoid gratuitously loading stdio.
62 */
63 write(2, "Usage: ", 7);
64 write(2, O_name, strlen(O_name));
65 write(2, " ", 1);
66 write(2, O_usage, strlen(O_usage));
67 write(2, "\n", 1);
68 }
69
70#define usage() (pusage(), exit(1))
71
72#define OPTIONS(usage_msg) \
73 { \
74 char O_cont; \
75 O_usage = (usage_msg); \
76 O_name = argv[0]; \
77 while (*++argv && **argv == '-') \
78 { \
79 if ((*argv)[1] == '\0') \
80 break; \
81 argc--; \
82 if ((*argv)[1] == '-' && (*argv)[2] == '\0') \
83 { \
84 argv++; \
85 break; \
86 } \
87 O_cont = 1; \
88 while (O_cont) \
89 switch (*++*argv) \
90 { \
91 case '-': \
92 usage(); \
93 case '\0': \
94 O_cont = 0;
95
96#define FLAG(x,flag) \
97 break; \
98 case (x): \
99 (flag) = 1;
100
101#define CHAR(x,ch) \
102 break; \
103 case (x): \
104 O_cont = 0; \
105 if (*++*argv == '\0' && (--argc, *++argv == 0)) \
106 usage(); \
107 (ch) = **argv;
108
109#define NUMBER(x,n) \
110 break; \
111 case (x): \
112 O_cont = 0; \
113 if (*++*argv == '\0' && (--argc, *++argv == 0)) \
114 usage(); \
115 (n) = atol(*argv);
116
117#define STRING(x,str) \
118 break; \
119 case (x): \
120 O_cont = 0; \
121 if (*++*argv == '\0' && (--argc, *++argv == 0)) \
122 usage(); \
123 (str) = *argv;
124
125#define SUFFIX(x,str) \
126 break; \
127 case (x): \
128 (str) = ++*argv; \
129 O_cont = 0;
130
131#define ENDOPTS \
132 break; \
133 default: \
134 usage(); \
135 } \
136 } \
137 *--argv = O_name; \
138 }
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
53static char *O_usage;
54static char *O_name;
55extern long atol();
56
57void
58pusage()
59 {
60 /*
61 * Avoid gratuitously loading stdio.
62 */
63 write(2, "Usage: ", 7);
64 write(2, O_name, strlen(O_name));
65 write(2, " ", 1);
66 write(2, O_usage, strlen(O_usage));
67 write(2, "\n", 1);
68 }
69
70#define usage() (pusage(), exit(1))
71
72#define OPTIONS(usage_msg) \
73 { \
74 char O_cont; \
75 O_usage = (usage_msg); \
76 O_name = argv[0]; \
77 while (*++argv && **argv == '-') \
78 { \
79 if ((*argv)[1] == '\0') \
80 break; \
81 argc--; \
82 if ((*argv)[1] == '-' && (*argv)[2] == '\0') \
83 { \
84 argv++; \
85 break; \
86 } \
87 O_cont = 1; \
88 while (O_cont) \
89 switch (*++*argv) \
90 { \
91 case '-': \
92 usage(); \
93 case '\0': \
94 O_cont = 0;
95
96#define FLAG(x,flag) \
97 break; \
98 case (x): \
99 (flag) = 1;
100
101#define CHAR(x,ch) \
102 break; \
103 case (x): \
104 O_cont = 0; \
105 if (*++*argv == '\0' && (--argc, *++argv == 0)) \
106 usage(); \
107 (ch) = **argv;
108
109#define NUMBER(x,n) \
110 break; \
111 case (x): \
112 O_cont = 0; \
113 if (*++*argv == '\0' && (--argc, *++argv == 0)) \
114 usage(); \
115 (n) = atol(*argv);
116
117#define STRING(x,str) \
118 break; \
119 case (x): \
120 O_cont = 0; \
121 if (*++*argv == '\0' && (--argc, *++argv == 0)) \
122 usage(); \
123 (str) = *argv;
124
125#define SUFFIX(x,str) \
126 break; \
127 case (x): \
128 (str) = ++*argv; \
129 O_cont = 0;
130
131#define ENDOPTS \
132 break; \
133 default: \
134 usage(); \
135 } \
136 } \
137 *--argv = O_name; \
138 }