]>
Commit | Line | Data |
---|---|---|
7b5e8039 | 1 | /* wordsplit - a word splitter |
c7b3f021 | 2 | Copyright (C) 2009-2018 Sergey Poznyakoff |
7b5e8039 SP |
3 | |
4 | This program is free software; you can redistribute it and/or modify it | |
5 | under the terms of the GNU General Public License as published by the | |
6 | Free Software Foundation; either version 3 of the License, or (at your | |
7 | option) any later version. | |
8 | ||
9 | This program is distributed in the hope that it will be useful, | |
10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
12 | GNU General Public License for more details. | |
13 | ||
14 | You should have received a copy of the GNU General Public License along | |
c7b3f021 | 15 | with this program. If not, see <http://www.gnu.org/licenses/>. */ |
7b5e8039 SP |
16 | |
17 | #ifndef __WORDSPLIT_H | |
18 | #define __WORDSPLIT_H | |
19 | ||
20 | #include <stddef.h> | |
21 | ||
55fb2fc3 PE |
22 | #if 2 < __GNUC__ + (7 <= __GNUC_MINOR__) |
23 | # define __WORDSPLIT_ATTRIBUTE_FORMAT(spec) __attribute__ ((__format__ spec)) | |
24 | #else | |
25 | # define __WORDSPLIT_ATTRIBUTE_FORMAT(spec) /* empty */ | |
26 | #endif | |
27 | ||
c7b3f021 SP |
28 | typedef struct wordsplit wordsplit_t; |
29 | ||
30 | /* Structure used to direct the splitting. Members marked with [Input] | |
31 | can be defined before calling wordsplit(), those marked with [Output] | |
32 | provide return values when the function returns. If neither mark is | |
33 | used, the member is internal and must not be used by the caller. | |
34 | ||
35 | In the comments below, the identifiers in parentheses indicate bits that | |
36 | must be set (or unset, if starting with !) in ws_flags (if starting with | |
37 | WRDSF_) or ws_options (if starting with WRDSO_) to initialize or use the | |
38 | given member. | |
39 | ||
40 | If not redefined explicitly, most of them are set to some reasonable | |
41 | default value upon entry to wordsplit(). */ | |
42 | struct wordsplit | |
7b5e8039 | 43 | { |
c7b3f021 SP |
44 | size_t ws_wordc; /* [Output] Number of words in ws_wordv. */ |
45 | char **ws_wordv; /* [Output] Array of parsed out words. */ | |
46 | size_t ws_offs; /* [Input] (WRDSF_DOOFFS) Number of initial | |
47 | elements in ws_wordv to fill with NULLs. */ | |
48 | size_t ws_wordn; /* Number of elements ws_wordv can accomodate. */ | |
e5474174 SP |
49 | unsigned ws_flags; /* [Input] Flags passed to wordsplit. */ |
50 | unsigned ws_options; /* [Input] (WRDSF_OPTIONS) | |
c7b3f021 SP |
51 | Additional options. */ |
52 | size_t ws_maxwords; /* [Input] (WRDSO_MAXWORDS) Return at most that | |
53 | many words */ | |
54 | size_t ws_wordi; /* [Output] (WRDSF_INCREMENTAL) Total number of | |
55 | words returned so far */ | |
56 | ||
57 | const char *ws_delim; /* [Input] (WRDSF_DELIM) Word delimiters. */ | |
58 | const char *ws_comment; /* [Input] (WRDSF_COMMENT) Comment characters. */ | |
59 | const char *ws_escape[2]; /* [Input] (WRDSF_ESCAPE) Characters to be escaped | |
60 | with backslash. */ | |
61 | void (*ws_alloc_die) (wordsplit_t *wsp); | |
62 | /* [Input] (WRDSF_ALLOC_DIE) Function called when | |
63 | out of memory. Must not return. */ | |
7b5e8039 | 64 | void (*ws_error) (const char *, ...) |
c7b3f021 SP |
65 | __attribute__ ((__format__ (__printf__, 1, 2))); |
66 | /* [Input] (WRDSF_ERROR) Function used for error | |
67 | reporting */ | |
7b5e8039 | 68 | void (*ws_debug) (const char *, ...) |
c7b3f021 SP |
69 | __attribute__ ((__format__ (__printf__, 1, 2))); |
70 | /* [Input] (WRDSF_DEBUG) Function used for debug | |
71 | output. */ | |
72 | const char **ws_env; /* [Input] (WRDSF_ENV, !WRDSF_NOVAR) Array of | |
73 | environment variables. */ | |
7b5e8039 | 74 | |
c7b3f021 SP |
75 | char **ws_envbuf; |
76 | size_t ws_envidx; | |
77 | size_t ws_envsiz; | |
78 | ||
79 | int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos); | |
80 | /* [Input] (WRDSF_GETVAR, !WRDSF_NOVAR) Looks up | |
81 | the name VAR (LEN bytes long) in the table of | |
82 | variables and if found returns in memory | |
83 | location pointed to by RET the value of that | |
84 | variable. Returns WRDSE_OK (0) on success, | |
85 | and an error code (see WRDSE_* defines below) | |
86 | on error. User-specific errors can be returned | |
87 | by storing the error diagnostic string in RET | |
88 | and returning WRDSE_USERERR. | |
89 | Whatever is stored in RET, it must be allocated | |
90 | using malloc(3). */ | |
91 | void *ws_closure; /* [Input] (WRDSF_CLOSURE) Passed as the CLOS | |
92 | argument to ws_getvar and ws_command. */ | |
93 | int (*ws_command) (char **ret, const char *cmd, size_t len, char **argv, | |
94 | void *clos); | |
95 | /* [Input] (!WRDSF_NOCMD) Returns in the memory | |
96 | location pointed to by RET the expansion of | |
97 | the command CMD (LEN bytes long). If WRDSO_ARGV | |
98 | option is set, ARGV contains CMD split out to | |
99 | words. Otherwise ARGV is NULL. | |
7b5e8039 | 100 | |
c7b3f021 SP |
101 | See ws_getvar for a discussion of possible |
102 | return values. */ | |
103 | ||
104 | const char *ws_input; /* Input string (the S argument to wordsplit. */ | |
105 | size_t ws_len; /* Length of ws_input. */ | |
106 | size_t ws_endp; /* Points past the last processed byte in | |
107 | ws_input. */ | |
108 | int ws_errno; /* [Output] Error code, if an error occurred. */ | |
109 | char *ws_usererr; /* Points to textual description of | |
110 | the error, if ws_errno is WRDSE_USERERR. Must | |
111 | be allocated with malloc(3). */ | |
7b5e8039 | 112 | struct wordsplit_node *ws_head, *ws_tail; |
c7b3f021 SP |
113 | /* Doubly-linked list of parsed out nodes. */ |
114 | int ws_lvl; /* Invocation nesting level. */ | |
7b5e8039 SP |
115 | }; |
116 | ||
c7b3f021 SP |
117 | /* Initial size for ws_env, if allocated automatically */ |
118 | #define WORDSPLIT_ENV_INIT 16 | |
119 | ||
120 | /* Wordsplit flags. */ | |
7b5e8039 SP |
121 | /* Append the words found to the array resulting from a previous |
122 | call. */ | |
123 | #define WRDSF_APPEND 0x00000001 | |
c7b3f021 | 124 | /* Insert ws_offs initial NULLs in the array ws_wordv. |
7b5e8039 SP |
125 | (These are not counted in the returned ws_wordc.) */ |
126 | #define WRDSF_DOOFFS 0x00000002 | |
c7b3f021 | 127 | /* Don't do command substitution. */ |
7b5e8039 SP |
128 | #define WRDSF_NOCMD 0x00000004 |
129 | /* The parameter p resulted from a previous call to | |
130 | wordsplit(), and wordsplit_free() was not called. Reuse the | |
131 | allocated storage. */ | |
132 | #define WRDSF_REUSE 0x00000008 | |
133 | /* Print errors */ | |
134 | #define WRDSF_SHOWERR 0x00000010 | |
c7b3f021 | 135 | /* Consider it an error if an undefined variable is expanded. */ |
7b5e8039 | 136 | #define WRDSF_UNDEF 0x00000020 |
7b5e8039 SP |
137 | /* Don't do variable expansion. */ |
138 | #define WRDSF_NOVAR 0x00000040 | |
139 | /* Abort on ENOMEM error */ | |
140 | #define WRDSF_ENOMEMABRT 0x00000080 | |
141 | /* Trim off any leading and trailind whitespace */ | |
142 | #define WRDSF_WS 0x00000100 | |
143 | /* Handle single quotes */ | |
144 | #define WRDSF_SQUOTE 0x00000200 | |
145 | /* Handle double quotes */ | |
146 | #define WRDSF_DQUOTE 0x00000400 | |
c7b3f021 | 147 | /* Handle single and double quotes */ |
7b5e8039 SP |
148 | #define WRDSF_QUOTE (WRDSF_SQUOTE|WRDSF_DQUOTE) |
149 | /* Replace each input sequence of repeated delimiters with a single | |
150 | delimiter */ | |
151 | #define WRDSF_SQUEEZE_DELIMS 0x00000800 | |
152 | /* Return delimiters */ | |
153 | #define WRDSF_RETURN_DELIMS 0x00001000 | |
154 | /* Treat sed expressions as words */ | |
155 | #define WRDSF_SED_EXPR 0x00002000 | |
156 | /* ws_delim field is initialized */ | |
157 | #define WRDSF_DELIM 0x00004000 | |
158 | /* ws_comment field is initialized */ | |
159 | #define WRDSF_COMMENT 0x00008000 | |
160 | /* ws_alloc_die field is initialized */ | |
161 | #define WRDSF_ALLOC_DIE 0x00010000 | |
162 | /* ws_error field is initialized */ | |
163 | #define WRDSF_ERROR 0x00020000 | |
164 | /* ws_debug field is initialized */ | |
165 | #define WRDSF_DEBUG 0x00040000 | |
166 | /* ws_env field is initialized */ | |
167 | #define WRDSF_ENV 0x00080000 | |
168 | /* ws_getvar field is initialized */ | |
169 | #define WRDSF_GETVAR 0x00100000 | |
170 | /* enable debugging */ | |
171 | #define WRDSF_SHOWDBG 0x00200000 | |
172 | /* Don't split input into words. Useful for side effects. */ | |
173 | #define WRDSF_NOSPLIT 0x00400000 | |
174 | /* Keep undefined variables in place, instead of expanding them to | |
c7b3f021 | 175 | empty strings. */ |
7b5e8039 SP |
176 | #define WRDSF_KEEPUNDEF 0x00800000 |
177 | /* Warn about undefined variables */ | |
178 | #define WRDSF_WARNUNDEF 0x01000000 | |
179 | /* Handle C escapes */ | |
180 | #define WRDSF_CESCAPES 0x02000000 | |
7b5e8039 SP |
181 | /* ws_closure is set */ |
182 | #define WRDSF_CLOSURE 0x04000000 | |
183 | /* ws_env is a Key/Value environment, i.e. the value of a variable is | |
184 | stored in the element that follows its name. */ | |
185 | #define WRDSF_ENV_KV 0x08000000 | |
7b5e8039 SP |
186 | /* ws_escape is set */ |
187 | #define WRDSF_ESCAPE 0x10000000 | |
7b5e8039 SP |
188 | /* Incremental mode */ |
189 | #define WRDSF_INCREMENTAL 0x20000000 | |
c7b3f021 SP |
190 | /* Perform pathname and tilde expansion */ |
191 | #define WRDSF_PATHEXPAND 0x40000000 | |
192 | /* ws_options is initialized */ | |
193 | #define WRDSF_OPTIONS 0x80000000 | |
7b5e8039 SP |
194 | |
195 | #define WRDSF_DEFFLAGS \ | |
196 | (WRDSF_NOVAR | WRDSF_NOCMD | \ | |
197 | WRDSF_QUOTE | WRDSF_SQUEEZE_DELIMS | WRDSF_CESCAPES) | |
198 | ||
c7b3f021 SP |
199 | /* Remove the word that produces empty string after path expansion */ |
200 | #define WRDSO_NULLGLOB 0x00000001 | |
201 | /* Print error message if path expansion produces empty string */ | |
202 | #define WRDSO_FAILGLOB 0x00000002 | |
203 | /* Allow a leading period to be matched by metacharacters. */ | |
204 | #define WRDSO_DOTGLOB 0x00000004 | |
205 | /* ws_command needs argv parameter */ | |
206 | #define WRDSO_ARGV 0x00000008 | |
207 | /* Keep backslash in unrecognized escape sequences in words */ | |
208 | #define WRDSO_BSKEEP_WORD 0x00000010 | |
209 | /* Handle octal escapes in words */ | |
210 | #define WRDSO_OESC_WORD 0x00000020 | |
211 | /* Handle hex escapes in words */ | |
212 | #define WRDSO_XESC_WORD 0x00000040 | |
213 | ||
214 | /* ws_maxwords field is initialized */ | |
215 | #define WRDSO_MAXWORDS 0x00000080 | |
216 | ||
217 | /* Keep backslash in unrecognized escape sequences in quoted strings */ | |
218 | #define WRDSO_BSKEEP_QUOTE 0x00000100 | |
219 | /* Handle octal escapes in quoted strings */ | |
220 | #define WRDSO_OESC_QUOTE 0x00000200 | |
221 | /* Handle hex escapes in quoted strings */ | |
222 | #define WRDSO_XESC_QUOTE 0x00000400 | |
223 | ||
224 | #define WRDSO_BSKEEP WRDSO_BSKEEP_WORD | |
225 | #define WRDSO_OESC WRDSO_OESC_WORD | |
226 | #define WRDSO_XESC WRDSO_XESC_WORD | |
227 | ||
228 | /* Indices into ws_escape */ | |
229 | #define WRDSX_WORD 0 | |
230 | #define WRDSX_QUOTE 1 | |
231 | ||
232 | /* Set escape option F in WS for words (Q==0) or quoted strings (Q==1) */ | |
233 | #define WRDSO_ESC_SET(ws,q,f) ((ws)->ws_options |= ((f) << 4*(q))) | |
234 | /* Test WS for escape option F for words (Q==0) or quoted strings (Q==1) */ | |
235 | #define WRDSO_ESC_TEST(ws,q,f) ((ws)->ws_options & ((f) << 4*(q))) | |
236 | ||
237 | #define WRDSE_OK 0 | |
238 | #define WRDSE_EOF WRDSE_OK | |
7b5e8039 SP |
239 | #define WRDSE_QUOTE 1 |
240 | #define WRDSE_NOSPACE 2 | |
c7b3f021 SP |
241 | #define WRDSE_USAGE 3 |
242 | #define WRDSE_CBRACE 4 | |
243 | #define WRDSE_UNDEF 5 | |
244 | #define WRDSE_NOINPUT 6 | |
245 | #define WRDSE_PAREN 7 | |
246 | #define WRDSE_GLOBERR 8 | |
247 | #define WRDSE_USERERR 9 | |
248 | ||
e5474174 SP |
249 | int wordsplit (const char *s, wordsplit_t *ws, unsigned flags); |
250 | int wordsplit_len (const char *s, size_t len, wordsplit_t *ws, unsigned flags); | |
c7b3f021 SP |
251 | void wordsplit_free (wordsplit_t *ws); |
252 | void wordsplit_free_words (wordsplit_t *ws); | |
253 | void wordsplit_free_envbuf (wordsplit_t *ws); | |
254 | int wordsplit_get_words (wordsplit_t *ws, size_t *wordc, char ***wordv); | |
255 | ||
256 | static inline void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv) | |
257 | __attribute__ ((deprecated)); | |
258 | ||
259 | static inline void | |
260 | wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv) | |
261 | { | |
262 | wordsplit_get_words (ws, wordc, wordv); | |
263 | } | |
264 | ||
265 | int wordsplit_append (wordsplit_t *wsp, int argc, char **argv); | |
7b5e8039 SP |
266 | |
267 | int wordsplit_c_unquote_char (int c); | |
268 | int wordsplit_c_quote_char (int c); | |
c7b3f021 | 269 | size_t wordsplit_c_quoted_length (const char *str, int quote_hex, int *quote); |
7b5e8039 SP |
270 | void wordsplit_c_quote_copy (char *dst, const char *src, int quote_hex); |
271 | ||
c7b3f021 SP |
272 | void wordsplit_perror (wordsplit_t *ws); |
273 | const char *wordsplit_strerror (wordsplit_t *ws); | |
7b5e8039 | 274 | |
c7b3f021 | 275 | void wordsplit_clearerr (wordsplit_t *ws); |
7b5e8039 SP |
276 | |
277 | #endif |