diff options
author | Sergey Poznyakoff <gray@gnu.org.ua> | 2014-10-28 15:40:20 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org.ua> | 2015-12-17 15:26:28 +0200 |
commit | 56a02e741cd8d8b9dce27a79ae9bbcaf1713c4f7 (patch) | |
tree | 1153a7dd5c15ab80f1ffa7da4eb9091685222445 /src | |
parent | 8383ec3a522a944969b3fc44069a3ff056da554a (diff) | |
download | grecs-56a02e741cd8d8b9dce27a79ae9bbcaf1713c4f7.tar.gz grecs-56a02e741cd8d8b9dce27a79ae9bbcaf1713c4f7.tar.bz2 |
Improve wordsplit
* src/wordsplit.c: Implement default assignment, word
expansion in variable defaults, distinction between
${variable:-word} and ${variable-word}.
* doc/wordsplit.3: New file.
* src/wordsplit.h (wordsplit)<ws_envbuf,ws_envidx>
<ws_envsiz>: New members.
(WRDSF_ARGV): Remove.
(WRDSF_OPTIONS): New flag.
(WRDSO_ARGV): New option bit.
* tests/wordsplit.at: Add new tests.
* tests/wsp.c: Set WRDSF_OPTIONS flag if one of the options is requested.
Diffstat (limited to 'src')
-rw-r--r-- | src/wordsplit.c | 367 | ||||
-rw-r--r-- | src/wordsplit.h | 37 |
2 files changed, 310 insertions, 94 deletions
diff --git a/src/wordsplit.c b/src/wordsplit.c index 4a69725..c726239 100644 --- a/src/wordsplit.c +++ b/src/wordsplit.c | |||
@@ -114,11 +114,30 @@ _wsplt_subsplit (struct wordsplit *wsp, struct wordsplit *wss, | |||
114 | wss->ws_error = wsp->ws_error; | 114 | wss->ws_error = wsp->ws_error; |
115 | wss->ws_alloc_die = wsp->ws_alloc_die; | 115 | wss->ws_alloc_die = wsp->ws_alloc_die; |
116 | 116 | ||
117 | if (!(flags & WRDSF_NOVAR)) | ||
118 | { | ||
119 | wss->ws_env = wsp->ws_env; | ||
120 | wss->ws_getvar = wsp->ws_getvar; | ||
121 | flags |= wsp->ws_flags & (WRDSF_ENV | WRDSF_ENV_KV | WRDSF_GETVAR); | ||
122 | } | ||
123 | if (!(flags & WRDSF_NOCMD)) | ||
124 | { | ||
125 | wss->ws_command = wsp->ws_command; | ||
126 | } | ||
127 | |||
128 | if ((flags & (WRDSF_NOVAR|WRDSF_NOCMD)) != (WRDSF_NOVAR|WRDSF_NOCMD)) | ||
129 | { | ||
130 | wss->ws_closure = wsp->ws_closure; | ||
131 | flags |= wsp->ws_flags & WRDSF_CLOSURE; | ||
132 | } | ||
133 | |||
134 | wss->ws_options = wsp->ws_options; | ||
135 | |||
117 | flags |= WRDSF_DELIM | 136 | flags |= WRDSF_DELIM |
118 | | WRDSF_ALLOC_DIE | 137 | | WRDSF_ALLOC_DIE |
119 | | WRDSF_ERROR | 138 | | WRDSF_ERROR |
120 | | WRDSF_DEBUG | 139 | | WRDSF_DEBUG |
121 | | (wsp->ws_flags & (WRDSF_SHOWDBG | WRDSF_SHOWERR)); | 140 | | (wsp->ws_flags & (WRDSF_SHOWDBG | WRDSF_SHOWERR | WRDSF_OPTIONS)); |
122 | 141 | ||
123 | return wordsplit_run (str, len, wss, flags, wsp->ws_lvl + 1); | 142 | return wordsplit_run (str, len, wss, flags, wsp->ws_lvl + 1); |
124 | } | 143 | } |
@@ -168,12 +187,11 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, | |||
168 | if (!(wsp->ws_flags & WRDSF_ERROR)) | 187 | if (!(wsp->ws_flags & WRDSF_ERROR)) |
169 | wsp->ws_error = _wsplt_error; | 188 | wsp->ws_error = _wsplt_error; |
170 | 189 | ||
171 | if (!(wsp->ws_flags & WRDSF_NOVAR) | 190 | if (!(wsp->ws_flags & WRDSF_NOVAR)) |
172 | && !(wsp->ws_flags & (WRDSF_ENV | WRDSF_GETVAR))) | ||
173 | { | 191 | { |
174 | _wsplt_seterr (wsp, WRDSE_USAGE); | 192 | /* These will be initialized on first variable assignment */ |
175 | errno = EINVAL; | 193 | wsp->ws_envidx = wsp->ws_envsiz = 0; |
176 | return wsp->ws_errno; | 194 | wsp->ws_envbuf = NULL; |
177 | } | 195 | } |
178 | 196 | ||
179 | if (!(wsp->ws_flags & WRDSF_NOCMD)) | 197 | if (!(wsp->ws_flags & WRDSF_NOCMD)) |
@@ -214,6 +232,9 @@ wordsplit_init (struct wordsplit *wsp, const char *input, size_t len, | |||
214 | if (!(wsp->ws_flags & WRDSF_CLOSURE)) | 232 | if (!(wsp->ws_flags & WRDSF_CLOSURE)) |
215 | wsp->ws_closure = NULL; | 233 | wsp->ws_closure = NULL; |
216 | 234 | ||
235 | if (!(wsp->ws_flags & WRDSF_OPTIONS)) | ||
236 | wsp->ws_options = 0; | ||
237 | |||
217 | wsp->ws_endp = 0; | 238 | wsp->ws_endp = 0; |
218 | 239 | ||
219 | wordsplit_init0 (wsp); | 240 | wordsplit_init0 (wsp); |
@@ -717,13 +738,14 @@ find_closing_paren (const char *str, size_t i, size_t len, size_t *poff, | |||
717 | return 1; | 738 | return 1; |
718 | } | 739 | } |
719 | 740 | ||
720 | static const char * | 741 | static int |
721 | wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len) | 742 | wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len, |
743 | char const **ret) | ||
722 | { | 744 | { |
723 | size_t i; | 745 | size_t i; |
724 | 746 | ||
725 | if (!(wsp->ws_flags & WRDSF_ENV)) | 747 | if (!(wsp->ws_flags & WRDSF_ENV)) |
726 | return NULL; | 748 | return WRDSE_UNDEF; |
727 | 749 | ||
728 | if (wsp->ws_flags & WRDSF_ENV_KV) | 750 | if (wsp->ws_flags & WRDSF_ENV_KV) |
729 | { | 751 | { |
@@ -732,14 +754,17 @@ wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len) | |||
732 | { | 754 | { |
733 | size_t elen = strlen (wsp->ws_env[i]); | 755 | size_t elen = strlen (wsp->ws_env[i]); |
734 | if (elen == len && memcmp (wsp->ws_env[i], name, elen) == 0) | 756 | if (elen == len && memcmp (wsp->ws_env[i], name, elen) == 0) |
735 | return wsp->ws_env[i + 1]; | 757 | { |
758 | *ret = wsp->ws_env[i + 1]; | ||
759 | return WRDSE_OK; | ||
760 | } | ||
736 | /* Skip the value. Break the loop if it is NULL. */ | 761 | /* Skip the value. Break the loop if it is NULL. */ |
737 | i++; | 762 | i++; |
738 | if (wsp->ws_env[i] == NULL) | 763 | if (wsp->ws_env[i] == NULL) |
739 | break; | 764 | break; |
740 | } | 765 | } |
741 | } | 766 | } |
742 | else | 767 | else if (wsp->ws_env) |
743 | { | 768 | { |
744 | /* Usual (A=B) environment. */ | 769 | /* Usual (A=B) environment. */ |
745 | for (i = 0; wsp->ws_env[i]; i++) | 770 | for (i = 0; wsp->ws_env[i]; i++) |
@@ -751,10 +776,117 @@ wordsplit_find_env (struct wordsplit *wsp, const char *name, size_t len) | |||
751 | if (name[j] != var[j]) | 776 | if (name[j] != var[j]) |
752 | break; | 777 | break; |
753 | if (j == len && var[j] == '=') | 778 | if (j == len && var[j] == '=') |
754 | return var + j + 1; | 779 | { |
780 | *ret = var + j + 1; | ||
781 | return WRDSE_OK; | ||
782 | } | ||
783 | } | ||
784 | } | ||
785 | return WRDSE_UNDEF; | ||
786 | } | ||
787 | |||
788 | static int | ||
789 | wsplt_assign_var (struct wordsplit *wsp, const char *name, size_t namelen, | ||
790 | char *value) | ||
791 | { | ||
792 | int n = (wsp->ws_flags & WRDSF_ENV_KV) ? 2 : 1; | ||
793 | char *v; | ||
794 | |||
795 | if (wsp->ws_envidx + n >= wsp->ws_envsiz) | ||
796 | { | ||
797 | size_t sz; | ||
798 | char **newenv; | ||
799 | |||
800 | if (!wsp->ws_envbuf) | ||
801 | { | ||
802 | if (wsp->ws_flags & WRDSF_ENV) | ||
803 | { | ||
804 | size_t i = 0, j; | ||
805 | |||
806 | if (wsp->ws_env) | ||
807 | { | ||
808 | for (; wsp->ws_env[i]; i++) | ||
809 | ; | ||
810 | } | ||
811 | |||
812 | sz = i + n + 1; | ||
813 | |||
814 | newenv = calloc (sz, sizeof(newenv[0])); | ||
815 | if (!newenv) | ||
816 | return _wsplt_nomem (wsp); | ||
817 | |||
818 | for (j = 0; j < i; j++) | ||
819 | { | ||
820 | newenv[j] = strdup (wsp->ws_env[j]); | ||
821 | if (!newenv[j]) | ||
822 | { | ||
823 | for (; j > 1; j--) | ||
824 | free (newenv[j-1]); | ||
825 | free (newenv[j-1]); | ||
826 | return _wsplt_nomem (wsp); | ||
827 | } | ||
828 | } | ||
829 | newenv[j] = NULL; | ||
830 | |||
831 | wsp->ws_envbuf = newenv; | ||
832 | wsp->ws_envidx = i; | ||
833 | wsp->ws_envsiz = sz; | ||
834 | wsp->ws_env = (const char**) wsp->ws_envbuf; | ||
835 | } | ||
836 | else | ||
837 | { | ||
838 | newenv = calloc (WORDSPLIT_ENV_INIT, sizeof(newenv[0])); | ||
839 | if (!newenv) | ||
840 | return _wsplt_nomem (wsp); | ||
841 | wsp->ws_envbuf = newenv; | ||
842 | wsp->ws_envidx = 0; | ||
843 | wsp->ws_envsiz = WORDSPLIT_ENV_INIT; | ||
844 | wsp->ws_env = (const char**) wsp->ws_envbuf; | ||
845 | wsp->ws_flags |= WRDSF_ENV; | ||
846 | } | ||
847 | } | ||
848 | else | ||
849 | { | ||
850 | wsp->ws_envsiz *= 2; | ||
851 | newenv = realloc (wsp->ws_envbuf, | ||
852 | wsp->ws_envsiz * sizeof (wsp->ws_envbuf[0])); | ||
853 | if (!newenv) | ||
854 | return _wsplt_nomem (wsp); | ||
855 | wsp->ws_envbuf = newenv; | ||
856 | wsp->ws_env = (const char**) wsp->ws_envbuf; | ||
755 | } | 857 | } |
756 | } | 858 | } |
757 | return NULL; | 859 | |
860 | if (wsp->ws_flags & WRDSF_ENV_KV) | ||
861 | { | ||
862 | /* A key-value pair environment */ | ||
863 | char *p = malloc (namelen + 1); | ||
864 | if (!p) | ||
865 | return _wsplt_nomem (wsp); | ||
866 | memcpy (p, name, namelen); | ||
867 | p[namelen] = 0; | ||
868 | |||
869 | v = strdup (value); | ||
870 | if (!v) | ||
871 | { | ||
872 | free (p); | ||
873 | return _wsplt_nomem (wsp); | ||
874 | } | ||
875 | wsp->ws_env[wsp->ws_envidx++] = p; | ||
876 | wsp->ws_env[wsp->ws_envidx++] = v; | ||
877 | } | ||
878 | else | ||
879 | { | ||
880 | v = malloc (namelen + strlen(value) + 2); | ||
881 | if (!v) | ||
882 | return _wsplt_nomem (wsp); | ||
883 | memcpy (v, name, namelen); | ||
884 | v[namelen++] = '='; | ||
885 | strcpy(v + namelen, value); | ||
886 | wsp->ws_env[wsp->ws_envidx++] = v; | ||
887 | } | ||
888 | wsp->ws_env[wsp->ws_envidx++] = NULL; | ||
889 | return WRDSE_OK; | ||