aboutsummaryrefslogtreecommitdiff
path: root/jim-regexp.c
diff options
context:
space:
mode:
Diffstat (limited to 'jim-regexp.c')
-rw-r--r--jim-regexp.c147
1 files changed, 102 insertions, 45 deletions
diff --git a/jim-regexp.c b/jim-regexp.c
index 1486c3a..f370e5e 100644
--- a/jim-regexp.c
+++ b/jim-regexp.c
@@ -348,27 +348,30 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
int regcomp_flags = 0;
int regexec_flags = 0;
int opt_all = 0;
+ int opt_command = 0;
int offset = 0;
regex_t *regex;
const char *p;
- int result;
+ int result = JIM_OK;
regmatch_t pmatch[MAX_SUB_MATCHES + 1];
int num_matches = 0;
int i, j, n;
Jim_Obj *varname;
Jim_Obj *resultObj;
+ Jim_Obj *cmd_prefix = NULL;
+ Jim_Obj *regcomp_obj = NULL;
const char *source_str;
int source_len;
- const char *replace_str;
+ const char *replace_str = NULL;
int replace_len;
const char *pattern;
int option;
enum {
- OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_END
+ OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_COMMAND, OPT_END
};
static const char * const options[] = {
- "-nocase", "-line", "-all", "-start", "--", NULL
+ "-nocase", "-line", "-all", "-start", "-command", "--", NULL
};
if (argc < 4) {
@@ -412,20 +415,39 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_ERR;
}
break;
+
+ case OPT_COMMAND:
+ opt_command = 1;
+ break;
}
}
if (argc - i != 3 && argc - i != 4) {
goto wrongNumArgs;
}
- regex = SetRegexpFromAny(interp, argv[i], regcomp_flags);
+ /* Need to ensure that this is unshared, so just duplicate it always */
+ regcomp_obj = Jim_DuplicateObj(interp, argv[i]);
+ Jim_IncrRefCount(regcomp_obj);
+ regex = SetRegexpFromAny(interp, regcomp_obj, regcomp_flags);
if (!regex) {
+ Jim_DecrRefCount(interp, regcomp_obj);
return JIM_ERR;
}
pattern = Jim_String(argv[i]);
source_str = Jim_GetString(argv[i + 1], &source_len);
- replace_str = Jim_GetString(argv[i + 2], &replace_len);
+ if (opt_command) {
+ cmd_prefix = argv[i + 2];
+ if (Jim_ListLength(interp, cmd_prefix) == 0) {
+ Jim_SetResultString(interp, "command prefix must be a list of at least one element", -1);
+ Jim_DecrRefCount(interp, regcomp_obj);
+ return JIM_ERR;
+ }
+ Jim_IncrRefCount(cmd_prefix);
+ }
+ else {
+ replace_str = Jim_GetString(argv[i + 2], &replace_len);
+ }
varname = argv[i + 3];
/* Create the result string */
@@ -482,44 +504,67 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
*/
Jim_AppendString(interp, resultObj, p, pmatch[0].rm_so);
- /*
- * Append the subSpec (replace_str) argument to the variable, making appropriate
- * substitutions. This code is a bit hairy because of the backslash
- * conventions and because the code saves up ranges of characters in
- * subSpec to reduce the number of calls to Jim_SetVar.
- */
-
- for (j = 0; j < replace_len; j++) {
- int idx;
- int c = replace_str[j];
+ if (opt_command) {
+ /* construct the command as a list */
+ Jim_Obj *cmdListObj = Jim_DuplicateObj(interp, cmd_prefix);
+ for (j = 0; j < MAX_SUB_MATCHES; j++) {
+ if (pmatch[j].rm_so == -1) {
+ break;
+ }
+ else {
+ Jim_Obj *srcObj = Jim_NewStringObj(interp, p + pmatch[j].rm_so, pmatch[j].rm_eo - pmatch[j].rm_so);
+ Jim_ListAppendElement(interp, cmdListObj, srcObj);
+ }
+ }
+ Jim_IncrRefCount(cmdListObj);
- if (c == '&') {
- idx = 0;
+ result = Jim_EvalObj(interp, cmdListObj);
+ Jim_DecrRefCount(interp, cmdListObj);
+ if (result != JIM_OK) {
+ goto cmd_error;
}
- else if (c == '\\' && j < replace_len) {
- c = replace_str[++j];
- if ((c >= '0') && (c <= '9')) {
- idx = c - '0';
+ Jim_AppendString(interp, resultObj, Jim_String(Jim_GetResult(interp)), -1);
+ }
+ else {
+ /*
+ * Append the subSpec (replace_str) argument to the variable, making appropriate
+ * substitutions. This code is a bit hairy because of the backslash
+ * conventions and because the code saves up ranges of characters in
+ * subSpec to reduce the number of calls to Jim_SetVar.
+ */
+
+ for (j = 0; j < replace_len; j++) {
+ int idx;
+ int c = replace_str[j];
+
+ if (c == '&') {
+ idx = 0;
}
- else if ((c == '\\') || (c == '&')) {
- Jim_AppendString(interp, resultObj, replace_str + j, 1);
- continue;
+ else if (c == '\\' && j < replace_len) {
+ c = replace_str[++j];
+ if ((c >= '0') && (c <= '9')) {
+ idx = c - '0';
+ }
+ else if ((c == '\\') || (c == '&')) {
+ Jim_AppendString(interp, resultObj, replace_str + j, 1);
+ continue;
+ }
+ else {
+ /* If the replacement is a trailing backslash, just replace with a backslash, otherwise
+ * with the literal backslash and the following character
+ */
+ Jim_AppendString(interp, resultObj, replace_str + j - 1, (j == replace_len) ? 1 : 2);
+ continue;
+ }
}
else {
- /* If the replacement is a trailing backslash, just replace with a backslash, otherwise
- * with the literal backslash and the following character
- */
- Jim_AppendString(interp, resultObj, replace_str + j - 1, (j == replace_len) ? 1 : 2);
+ Jim_AppendString(interp, resultObj, replace_str + j, 1);
continue;
}
- }
- else {
- Jim_AppendString(interp, resultObj, replace_str + j, 1);
- continue;
- }
- if ((idx < MAX_SUB_MATCHES) && pmatch[idx].rm_so != -1 && pmatch[idx].rm_eo != -1) {
- Jim_AppendString(interp, resultObj, p + pmatch[idx].rm_so,
- pmatch[idx].rm_eo - pmatch[idx].rm_so);
+ if ((idx < MAX_SUB_MATCHES) && pmatch[idx].rm_so != -1 && pmatch[idx].rm_eo != -1) {
+ Jim_AppendString(interp, resultObj, p + pmatch[idx].rm_so,
+ pmatch[idx].rm_eo - pmatch[idx].rm_so);
+ }
}
}
@@ -560,22 +605,34 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
*/
Jim_AppendString(interp, resultObj, p, -1);
- /* And now set or return the result variable */
- if (argc - i == 4) {
- result = Jim_SetVariable(interp, varname, resultObj);
+cmd_error:
+ if (result == JIM_OK) {
+ /* And now set or return the result variable */
+ if (argc - i == 4) {
+ result = Jim_SetVariable(interp, varname, resultObj);
- if (result == JIM_OK) {
- Jim_SetResultInt(interp, num_matches);
+ if (result == JIM_OK) {
+ Jim_SetResultInt(interp, num_matches);
+ }
+ else {
+ Jim_FreeObj(interp, resultObj);
+ }
}
else {
- Jim_FreeObj(interp, resultObj);
+ Jim_SetResult(interp, resultObj);
+ result = JIM_OK;
}
}
else {
- Jim_SetResult(interp, resultObj);
- result = JIM_OK;
+ Jim_FreeObj(interp, resultObj);
+ }
+
+ if (opt_command) {
+ Jim_DecrRefCount(interp, cmd_prefix);
}
+ Jim_DecrRefCount(interp, regcomp_obj);
+
return result;
}