diff options
Diffstat (limited to 'tests/wsp.c')
-rw-r--r-- | tests/wsp.c | 832 |
1 files changed, 444 insertions, 388 deletions
diff --git a/tests/wsp.c b/tests/wsp.c index bd13e63..958d01f 100644 --- a/tests/wsp.c +++ b/tests/wsp.c | |||
@@ -1,3 +1,3 @@ | |||
1 | /* grecs - Gray's Extensible Configuration System | 1 | /* grecs - Gray's Extensible Configuration System |
2 | Copyright (C) 2014-2016 Sergey Poznyakoff | 2 | Copyright (C) 2014-2019 Sergey Poznyakoff |
3 | 3 | ||
@@ -31,62 +31,180 @@ char *progname; | |||
31 | 31 | ||
32 | struct kwd | 32 | /* Global options */ |
33 | enum | ||
34 | { | ||
35 | TRIMNL_OPTION = 0x01, /* Remove trailing newline */ | ||
36 | PLAINTEXT_OPTION = 0x02 /* Print intput verbatim (no escapes) */ | ||
37 | }; | ||
38 | |||
39 | /* Environment types */ | ||
40 | enum env_type | ||
41 | { | ||
42 | env_none, /* No environment */ | ||
43 | env_null, /* Null environment */ | ||
44 | env_sys /* Use system environment */ | ||
45 | }; | ||
46 | |||
47 | struct wsclosure | ||
33 | { | 48 | { |
34 | const char *name; | 49 | int options; /* Global options */ |
35 | int tok; | 50 | struct wordsplit ws; /* The wordsplit structure */ |
51 | int wsflags; /* Wordsplit flags */ | ||
52 | enum env_type env_type; /* Environment type */ | ||
53 | int offarg; /* Index of the first of the initial words in | ||
54 | the argv array. The ws.ws_dooffs field gives | ||
55 | the number of such variables. Forces the | ||
56 | WRDSF_DOOFFS flag. */ | ||
57 | char **fenvbase; /* Environment for testing the ws_getenv function */ | ||
58 | int fenvidx; /* Number of variables in fenvbase */ | ||
59 | int fenvmax; /* Size of fenbase (entries) */ | ||
60 | int append_start; /* First argument to append (index in argv) */ | ||
61 | int append_count; /* Number of arguments to append */ | ||
36 | }; | 62 | }; |
37 | 63 | ||
38 | struct kwd bool_keytab[] = { | 64 | /* Command line option types */ |
39 | { "append", WRDSF_APPEND }, | 65 | enum |
40 | /*{ "reuse", WRDSF_REUSE },*/ | 66 | { |
41 | { "undef", WRDSF_UNDEF }, | 67 | ws_no_argument, /* Option requires no arguments */ |
42 | { "novar", WRDSF_NOVAR }, | 68 | ws_boolean, /* Option is boolean (can be prefixed with -no) */ |
43 | { "nocmd", WRDSF_NOCMD }, | 69 | ws_required_argument, /* Option requires one argument */ |
44 | { "ws", WRDSF_WS }, | 70 | ws_multiple_arguments /* Option takes multiple arguments, terminated with |
45 | { "quote", WRDSF_QUOTE }, | 71 | "--" or end of argument list */ |
46 | { "squote", WRDSF_SQUOTE }, | 72 | }; |
47 | { "dquote", WRDSF_DQUOTE }, | ||
48 | { "squeeze_delims", WRDSF_SQUEEZE_DELIMS }, | ||
49 | { "return_delims", WRDSF_RETURN_DELIMS }, | ||
50 | { "sed", WRDSF_SED_EXPR }, | ||
51 | { "debug", WRDSF_SHOWDBG }, | ||
52 | { "nosplit", WRDSF_NOSPLIT }, | ||
53 | { "keepundef", WRDSF_KEEPUNDEF }, | ||
54 | { "warnundef", WRDSF_WARNUNDEF }, | ||
55 | { "cescapes", WRDSF_CESCAPES }, | ||
56 | { "default", WRDSF_DEFFLAGS }, | ||
57 | { "env_kv", WRDSF_ENV_KV }, | ||
58 | { "incremental", WRDSF_INCREMENTAL }, | ||
59 | { "pathexpand", WRDSF_PATHEXPAND }, | ||
60 | { NULL, 0 } | ||
61 | }; | ||
62 | 73 | ||
63 | struct kwd opt_keytab[] = { | 74 | /* Structure describing a single command-line option */ |
64 | { "nullglob", WRDSO_NULLGLOB }, | 75 | struct wsopt |
65 | { "failglob", WRDSO_FAILGLOB }, | 76 | { |
66 | { "dotglob", WRDSO_DOTGLOB }, | 77 | const char *name; /* Option name */ |
67 | { "bskeep_words", WRDSO_BSKEEP_WORD }, | 78 | int tok; /* Corresponding flag */ |
68 | { "bskeep_quote", WRDSO_BSKEEP_QUOTE }, | 79 | int arg; /* Option type (see the enum above) */ |
69 | { "bskeep", WRDSO_BSKEEP_WORD|WRDSO_BSKEEP_QUOTE }, | 80 | void (*setfn) (int tok, int neg, char *arg, struct wsclosure *wsc); |
70 | { "novarsplit", WRDSO_NOVARSPLIT }, | 81 | /* Setter function */ |
71 | { "nocmdsplit", WRDSO_NOCMDSPLIT }, | ||
72 | { NULL, 0 } | ||
73 | }; | 82 | }; |
74 | 83 | ||
75 | struct kwd string_keytab[] = { | 84 | /* Index of the next argument in the argv */ |
76 | { "delim", WRDSF_DELIM }, | 85 | static int wsoptind = -1; |
77 | { "comment", WRDSF_COMMENT }, | ||
78 | { "escape", WRDSF_ESCAPE }, | ||
79 | { NULL, 0 } | ||
80 | }; | ||
81 | 86 | ||
87 | /* Parse next argument from the command line. Return EOF on end of arguments | ||
88 | or when the "--" argument is seen. */ | ||
82 | static int | 89 | static int |
83 | kwxlat (struct kwd *kwp, const char *str, int *res) | 90 | getwsopt (int argc, char **argv, struct wsopt *wso, struct wsclosure *wsc) |
84 | { | 91 | { |
85 | for (; kwp->name; kwp++) | 92 | int negate = 0; |
86 | if (strcmp (kwp->name, str) == 0) | 93 | char *opt; |
87 | { | 94 | |
88 | *res = kwp->tok; | 95 | if (wsoptind == -1) |
89 | return 0; | 96 | wsoptind = 1; |
90 | } | 97 | if (wsoptind == argc) |
91 | return -1; | 98 | return EOF; |
99 | |||
100 | opt = argv[wsoptind++]; | ||
101 | if (strcmp (opt, "--") == 0) | ||
102 | return EOF; | ||
103 | if (*opt != '-') | ||
104 | { | ||
105 | if (strchr (opt, '=')) | ||
106 | { | ||
107 | assert (wsc->fenvidx < wsc->fenvmax - 1); | ||
108 | wsc->fenvbase[wsc->fenvidx++] = opt; | ||
109 | return 0; | ||
110 | } | ||
111 | wsoptind--; | ||
112 | return EOF; | ||
113 | } | ||
114 | opt++; /* skip past initial dash */ | ||
115 | if (strncmp (opt, "no-", 3) == 0) | ||
116 | { | ||
117 | negate = 1; | ||
118 | opt += 3; | ||
119 | } | ||
120 | else if (strncmp (opt, "no", 2) == 0) | ||
121 | { | ||
122 | negate = 1; | ||
123 | opt += 2; | ||
124 | } | ||
125 | |||
126 | for (; wso->name; wso++) | ||
127 | { | ||
128 | if (wso->arg == ws_boolean && wso->name[0] == 'n' && wso->name[1] == 'o' | ||
129 | && strcmp (wso->name + 2, opt) == 0) | ||
130 | { | ||
131 | negate ^= 1; | ||
132 | break; | ||
133 | } | ||
134 | if (strcmp (wso->name, opt) == 0) | ||
135 | break; | ||
136 | } | ||
137 | |||
138 | if (wso->name) | ||
139 | { | ||
140 | char *arg; | ||
141 | if (wso->arg == ws_multiple_arguments) | ||
142 | { | ||
143 | while (1) | ||
144 | { | ||
145 | if (wsoptind == argc) | ||
146 | break; | ||
147 | arg = argv[wsoptind++]; | ||
148 | if (strcmp (arg, "--") == 0) | ||
149 | break; | ||
150 | wso->setfn (wso->tok, negate, arg, wsc); | ||
151 | } | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | if (wso->arg == ws_required_argument) | ||
156 | { | ||
157 | if (wsoptind == argc) | ||
158 | { | ||
159 | fprintf (stderr, "%s: missing arguments for -%s\n", | ||
160 | progname, opt); | ||
161 | exit (1); | ||
162 | } | ||
163 | arg = argv[wsoptind++]; | ||
164 | } | ||
165 | wso->setfn (wso->tok, negate, arg, wsc); | ||
166 | } | ||
167 | return 0; | ||
168 | } | ||
169 | |||
170 | fprintf (stderr, "%s: unrecognized option: -%s\n", | ||
171 | progname, opt); | ||
172 | fprintf (stderr, "%s: try %s -help for more detail\n", | ||
173 | progname, progname); | ||
174 | exit (1); | ||
175 | } | ||
176 | |||
177 | /* Setter functions for various options */ | ||
178 | |||
179 | static void | ||
180 | setfn_flag (int flag, int neg, char *arg, struct wsclosure *wsc) | ||
181 | { | ||
182 | if (neg) | ||
183 | wsc->wsflags &= ~flag; | ||
184 | else | ||
185 | wsc->wsflags |= flag; | ||
186 | } | ||
187 | |||
188 | static void | ||
189 | setfn_option (int flag, int neg, char *arg, struct wsclosure *wsc) | ||
190 | { | ||
191 | wsc->wsflags |= WRDSF_OPTIONS; | ||
192 | if (neg) | ||
193 | wsc->ws.ws_options &= ~flag; | ||
194 | else | ||
195 | wsc->ws.ws_options |= flag; | ||
196 | } | ||
197 | |||
198 | static void | ||
199 | setfn_delim (int flag, int neg, char *arg, struct wsclosure *wsc) | ||
200 | { | ||
201 | wsc->wsflags |= flag; | ||
202 | wsc->ws.ws_delim = arg; | ||
203 | } | ||
204 | |||
205 | static void | ||
206 | setfn_comment (int flag, int neg, char *arg, struct wsclosure *wsc) | ||
207 | { | ||
208 | wsc->wsflags |= flag; | ||
209 | wsc->ws.ws_comment = arg; | ||
92 | } | 210 | } |
@@ -94,3 +212,195 @@ kwxlat (struct kwd *kwp, const char *str, int *res) | |||
94 | static void | 212 | static void |
95 | help () | 213 | set_escape_string (wordsplit_t *ws, int *wsflags, int q, const char *str) |
214 | { | ||
215 | if (*str == ':') | ||
216 | { | ||
217 | while (*++str != ':') | ||
218 | { | ||
219 | int f; | ||
220 | switch (*str) | ||
221 | { | ||
222 | case '+': | ||
223 | f = WRDSO_BSKEEP; | ||
224 | break; | ||
225 | |||
226 | case '0': | ||
227 | f = WRDSO_OESC; | ||
228 | break; | ||