diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2019-05-14 15:31:59 +0300 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2019-05-14 15:43:25 +0300 |
commit | 8652a500669059d77ce7bace6e9e9da1b30c54b0 (patch) | |
tree | 54ee082e3804c0574e67252be8fbceb48b8f156a /include | |
parent | 65f41a742e025487f8ec7f2e7ca2a3af3283fc96 (diff) | |
download | grecs-8652a500669059d77ce7bace6e9e9da1b30c54b0.tar.gz grecs-8652a500669059d77ce7bace6e9e9da1b30c54b0.tar.bz2 |
wordsplit: rewrite positional parameters implementation
This improves 3e07e3ad
* include/wordsplit.h (ws_paramv,ws_paramc)
(ws_parambuf,ws_paramidx,ws_paramsiz): New fields.
(WRDSO_PARAMV,WRDSO_PARAM_NEGIDX): New options.
(WRDSE_BADPARAM): New error code.
(wordsplit_free_parambuf): New proto.
* src/wordsplit.c (wordsplit_init): Initialize new fields.
(wsplt_assign_var): Fix double-free and memory leak.
(expvar): Expand positional parameters.
(begin_var_p): Add '#'
(wordsplit_free_envbuf): Fix condition.
(wordsplit_free_parambuf): New function.
(wordsplit_free): Call wordsplit_free_parambuf.
(_wordsplit_errstr): New error description.
* tests/wordsplit.at: Update wsp invocations.
Test positional parameters.
* tests/wsp.c: Rewrite.
Diffstat (limited to 'include')
-rw-r--r-- | include/wordsplit.h | 20 |
1 files changed, 19 insertions, 1 deletions
diff --git a/include/wordsplit.h b/include/wordsplit.h index a175275..d7eb26f 100644 --- a/include/wordsplit.h +++ b/include/wordsplit.h @@ -66,49 +66,59 @@ struct wordsplit const char **ws_env; /* [Input] (WRDSF_ENV, !WRDSF_NOVAR) Array of environment variables. */ /* Temporary storage for environment variables. It is initialized upon first assignment which occurs during the parsing process (e.g. ${x:=2}). When this happens, all variables from ws_env are moved to ws_envbuf first, and the ws_envbuf address is assigned to ws_env. From this moment on, all variable expansions are served from ws_envbuf. */ char **ws_envbuf; /* Storage for variables */ size_t ws_envidx; /* Index of first free slot */ size_t ws_envsiz; /* Size of the ws_envbuf array */ + + char const **ws_paramv; /* [WRDSO_PARAMV] User-supplied positional + parameters */ + size_t ws_paramc; /* Number of positional parameters */ + + /* Temporary storage for parameters. Works similarly to ws_enbuf. + */ + char **ws_parambuf; + size_t ws_paramidx; + size_t ws_paramsiz; int (*ws_getvar) (char **ret, const char *var, size_t len, void *clos); /* [Input] (WRDSF_GETVAR, !WRDSF_NOVAR) Looks up the name VAR (LEN bytes long) in the table of variables and if found returns in memory location pointed to by RET the value of that variable. Returns WRDSE_OK (0) on success, and an error code (see WRDSE_* defines below) on error. User-specific errors can be returned by storing the error diagnostic string in RET and returning WRDSE_USERERR. Whatever is stored in RET, it must be allocated using malloc(3). */ void *ws_closure; /* [Input] (WRDSF_CLOSURE) Passed as the CLOS argument to ws_getvar and ws_command. */ int (*ws_command) (char **ret, const char *cmd, size_t len, char **argv, void *clos); /* [Input] (!WRDSF_NOCMD) Returns in the memory location pointed to by RET the expansion of the command CMD (LEN bytes long). On input, ARGV contains CMD split out to words. See ws_getvar for a discussion of possible return values. */ - + const char *ws_input; /* Input string (the S argument to wordsplit. */ size_t ws_len; /* Length of ws_input. */ size_t ws_endp; /* Points past the last processed byte in ws_input. */ int ws_errno; /* [Output] Error code, if an error occurred. */ char *ws_usererr; /* Points to textual description of the error, if ws_errno is WRDSE_USERERR. Must be allocated with malloc(3). */ struct wordsplit_node *ws_head, *ws_tail; /* Doubly-linked list of parsed out nodes. */ int ws_lvl; /* Invocation nesting level. */ }; @@ -217,54 +227,62 @@ struct wordsplit /* Handle octal escapes in quoted strings */ #define WRDSO_OESC_QUOTE 0x00000200 /* Handle hex escapes in quoted strings */ #define WRDSO_XESC_QUOTE 0x00000400 /* Unused: 0x00000800 */ /* Don't split variable references, even if they contain whitespace (e.g. ${VAR:-foo bar}) */ #define WRDSO_NOVARSPLIT 0x00001000 /* Don't split commands, even containing whitespace, e.g. $(echo foo bar) */ #define WRDSO_NOCMDSPLIT 0x00002000 +/* Enable positional parameters */ +#define WRDSO_PARAMV 0x00004000 +/* Enable negative positional indices (${-1} is the last positional + parameter) */ +#define WRDSO_PARAM_NEGIDX 0x00008000 + #define WRDSO_BSKEEP WRDSO_BSKEEP_WORD #define WRDSO_OESC WRDSO_OESC_WORD #define WRDSO_XESC WRDSO_XESC_WORD /* Indices into ws_escape */ #define WRDSX_WORD 0 #define WRDSX_QUOTE 1 /* Set escape option F in WS for words (Q==0) or quoted strings (Q==1) */ #define WRDSO_ESC_SET(ws,q,f) ((ws)->ws_options |= ((f) << 4*(q))) /* Test WS for escape option F for words (Q==0) or quoted strings (Q==1) */ #define WRDSO_ESC_TEST(ws,q,f) ((ws)->ws_options & ((f) << 4*(q))) #define WRDSE_OK 0 #define WRDSE_EOF WRDSE_OK #define WRDSE_QUOTE 1 #define WRDSE_NOSPACE 2 #define WRDSE_USAGE 3 #define WRDSE_CBRACE 4 #define WRDSE_UNDEF 5 #define WRDSE_NOINPUT 6 #define WRDSE_PAREN 7 #define WRDSE_GLOBERR 8 #define WRDSE_USERERR 9 +#define WRDSE_BADPARAM 10 int wordsplit (const char *s, wordsplit_t *ws, int flags); int wordsplit_len (const char *s, size_t len, wordsplit_t *ws, int flags); void wordsplit_free (wordsplit_t *ws); void wordsplit_free_words (wordsplit_t *ws); void wordsplit_free_envbuf (wordsplit_t *ws); +void wordsplit_free_parambuf (struct wordsplit *ws); int wordsplit_get_words (wordsplit_t *ws, size_t *wordc, char ***wordv); static inline void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv) __attribute__ ((deprecated)); static inline void wordsplit_getwords (wordsplit_t *ws, size_t *wordc, char ***wordv) { wordsplit_get_words (ws, wordc, wordv); } int wordsplit_append (wordsplit_t *wsp, int argc, char **argv); |