void prim_array_regsub(PRIM_PROTOTYPE) { struct inst *in; stk_array *arr; stk_array *nw; int matches[MATCH_ARR_SIZE]; int flags = 0; char* write_ptr = buf; int write_left = BUFFER_LEN - 1; muf_re* re; char* text; char* textstart; const char* errstr; int matchcnt, len; CHECKOP(4); oper4 = POP(); /* int:Flags */ oper3 = POP(); /* str:Replace */ oper2 = POP(); /* str:Pattern */ oper1 = POP(); /* str:Text */ if (oper1->type != PROG_ARRAY) abort_interp("Argument not an array of strings. (1)"); if (!array_is_homogenous(oper1->data.array, PROG_STRING)) abort_interp("Argument not an array of strings. (1)"); if (oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (oper3->type != PROG_STRING) abort_interp("Non-string argument (3)"); if (oper4->type != PROG_INTEGER) abort_interp("Non-integer argument (4)"); if (!oper2->data.string) abort_interp("Empty string argument (2)"); if (oper4->data.number & MUF_RE_ICASE) flags |= PCRE_CASELESS; if (oper4->data.number & MUF_RE_EXTENDED) flags |= PCRE_EXTENDED; if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL) abort_interp(errstr); nw = new_array_dictionary(); arr = oper1->data.array; if (!re->extra && ((oper4->data.number & MUF_RE_ALL ) || array_count(arr) > 2)) { /* Study the pattern if the user requested recursive substitution, or * if the input array contains at least three items. */ re->extra = pcre_study(re->re, 0, &errstr); if (errstr) abort_interp(errstr); } if (array_first(arr, &temp1)) { do { write_ptr = buf; write_left = BUFFER_LEN - 1; in = array_getitem(arr, &temp1); textstart = text = (char *)DoNullInd(in->data.string); len = strlen(textstart); while((*text != '\0') && (write_left > 0)) { if ((matchcnt = pcre_exec(re->re, re->extra, textstart, len, text-textstart, 0, matches, MATCH_ARR_SIZE)) < 0) { if (matchcnt != PCRE_ERROR_NOMATCH) { abort_interp(muf_re_error(matchcnt)); } while((write_left > 0) && (*text != '\0')) { *write_ptr++ = *text++; write_left--; } break; } else { int allstart = matches[0]; int allend = matches[1]; int substart = -1; int subend = -1; char* read_ptr = (char *)DoNullInd(oper3->data.string); int count; for(count = allstart-(text-textstart); (write_left > 0) && (*text != '\0') && (count > 0); count--) { *write_ptr++ = *text++; write_left--; } while((write_left > 0) && (*read_ptr != '\0')) { if (*read_ptr == '\\') { if (!isdigit(*(++read_ptr))) { *write_ptr++ = *read_ptr++; write_left--; } else { int idx = (*read_ptr++) - '0'; if ((idx < 0) || (idx >= matchcnt)) { abort_interp("Invalid \\subexp in substitution string. (3)"); } substart = matches[idx*2]; subend = matches[idx*2+1]; if ((substart >= 0) && (subend >= 0) && (substart < len)) { char* ptr = &textstart[substart]; count = subend - substart; if (count > write_left) { abort_interp("Operation would result in overflow"); } for(; (write_left > 0) && (count > 0) && (*ptr != '\0'); count--) { *write_ptr++ = *ptr++; write_left--; } } } } else { *write_ptr++ = *read_ptr++; write_left--; } } for(count = allend - allstart; (*text != '\0') && (count > 0); count--) text++; if (allstart == allend && *text) { *write_ptr++ = *text++; write_left--; } } if ((oper4->data.number & MUF_RE_ALL) == 0) { while((write_left > 0) && (*text != '\0')) { *write_ptr++ = *text++; write_left--; } break; } } if (*text != '\0') abort_interp("Operation would result in overflow"); *write_ptr = '\0'; temp2.type = PROG_STRING; temp2.data.string = alloc_prog_string(buf); array_setitem(&nw, &temp1, &temp2); CLEAR(&temp2); } while (array_next(arr, &temp1)); } CLEAR(oper4); CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushArrayRaw(nw); }
void prim_regsub(PRIM_PROTOTYPE) { int matches[MATCH_ARR_SIZE]; int flags = 0; char* write_ptr = buf; int write_left = BUFFER_LEN - 1; muf_re* re; char* text; char* textstart; const char* errstr; int matchcnt, len; CHECKOP(4); oper4 = POP(); /* int:Flags */ oper3 = POP(); /* str:Replace */ oper2 = POP(); /* str:Pattern */ oper1 = POP(); /* str:Text */ if (oper1->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (oper3->type != PROG_STRING) abort_interp("Non-string argument (3)"); if (oper4->type != PROG_INTEGER) abort_interp("Non-integer argument (4)"); if (!oper2->data.string) abort_interp("Empty string argument (2)"); if (oper4->data.number & MUF_RE_ICASE) flags |= PCRE_CASELESS; if (oper4->data.number & MUF_RE_EXTENDED) flags |= PCRE_EXTENDED; if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL) abort_interp(errstr); if (!re->extra && (oper4->data.number & MUF_RE_ALL)) { /* User requested a recursive pattern search. This generally means * pcre_exec will be called at least twice unless the pattern doesn't * exist in the string at all. Presence of this option suggests that * the user anticipates the pattern occurring at least once, so it's * safest to go ahead and study the pattern. -brevantes */ re->extra = pcre_study(re->re, 0, &errstr); if (errstr) abort_interp(errstr); } textstart = text = (char *)DoNullInd(oper1->data.string); len = strlen(textstart); while((*text != '\0') && (write_left > 0)) { if ((matchcnt = pcre_exec(re->re, re->extra, textstart, len, text-textstart, 0, matches, MATCH_ARR_SIZE)) < 0) { if (matchcnt != PCRE_ERROR_NOMATCH) { abort_interp(muf_re_error(matchcnt)); } while((write_left > 0) && (*text != '\0')) { *write_ptr++ = *text++; write_left--; } break; } else { int allstart = matches[0]; int allend = matches[1]; int substart = -1; int subend = -1; char* read_ptr = (char *)DoNullInd(oper3->data.string); int count; for(count = allstart-(text-textstart); (write_left > 0) && (*text != '\0') && (count > 0); count--) { *write_ptr++ = *text++; write_left--; } while((write_left > 0) && (*read_ptr != '\0')) { if (*read_ptr == '\\') { if (!isdigit(*(++read_ptr))) { *write_ptr++ = *read_ptr++; write_left--; } else { int idx = (*read_ptr++) - '0'; if ((idx < 0) || (idx >= matchcnt)) { abort_interp("Invalid \\subexp in substitution string. (3)"); } substart = matches[idx*2]; subend = matches[idx*2+1]; if ((substart >= 0) && (subend >= 0) && (substart < len)) { char* ptr = &textstart[substart]; count = subend - substart; if (count > write_left) { abort_interp("Operation would result in overflow"); } for(; (write_left > 0) && (count > 0) && (*ptr != '\0'); count--) { *write_ptr++ = *ptr++; write_left--; } } } } else { *write_ptr++ = *read_ptr++; write_left--; } } for(count = allend - allstart; (*text != '\0') && (count > 0); count--) text++; if (allstart == allend && *text) { *write_ptr++ = *text++; write_left--; } } if ((oper4->data.number & MUF_RE_ALL) == 0) { while((write_left > 0) && (*text != '\0')) { *write_ptr++ = *text++; write_left--; } break; } } if (*text != '\0') abort_interp("Operation would result in overflow"); *write_ptr = '\0'; CLEAR(oper4); CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushString(buf); }
void prim_regexp(PRIM_PROTOTYPE) { stk_array* nu_val = 0; stk_array* nu_idx = 0; int matches[MATCH_ARR_SIZE]; muf_re* re; char* text; int flags = 0; int len, i; int matchcnt = 0; const char* errstr; CHECKOP(3); oper3 = POP(); /* int:Flags */ oper2 = POP(); /* str:Pattern */ oper1 = POP(); /* str:Text */ if (oper1->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (oper3->type != PROG_INTEGER) abort_interp("Non-integer argument (3)"); if (!oper2->data.string) abort_interp("Empty string argument (2)"); if (oper3->data.number & MUF_RE_ICASE) flags |= PCRE_CASELESS; if (oper3->data.number & MUF_RE_EXTENDED) flags |= PCRE_EXTENDED; if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL) abort_interp(errstr); text = (char *)DoNullInd(oper1->data.string); len = strlen(text); if ((matchcnt = pcre_exec(re->re, re->extra, text, len, 0, 0, matches, MATCH_ARR_SIZE)) < 0) { if (matchcnt != PCRE_ERROR_NOMATCH) { abort_interp(muf_re_error(matchcnt)); } if (((nu_val = new_array_packed(0)) == NULL) || ((nu_idx = new_array_packed(0)) == NULL)) { if (nu_val != NULL) array_free(nu_val); if (nu_idx != NULL) array_free(nu_idx); abort_interp("Out of memory"); } } else { if (((nu_val = new_array_packed(matchcnt)) == NULL) || ((nu_idx = new_array_packed(matchcnt)) == NULL)) { if (nu_val != NULL) array_free(nu_val); if (nu_idx != NULL) array_free(nu_idx); abort_interp("Out of memory"); } for(i = 0; i < matchcnt; i++) { int substart = matches[i*2]; int subend = matches[i*2+1]; struct inst idx, val; stk_array* nu; if ((substart >= 0) && (subend >= 0) && (substart < len)) snprintf(buf, BUFFER_LEN, "%.*s", (int)(subend - substart), &text[substart]); else buf[0] = '\0'; idx.type = PROG_INTEGER; idx.data.number = i; val.type = PROG_STRING; val.data.string = alloc_prog_string(buf); array_setitem(&nu_val, &idx, &val); CLEAR(&idx); CLEAR(&val); if ((nu = new_array_packed(2)) == NULL) { array_free(nu_val); array_free(nu_idx); abort_interp("Out of memory"); } idx.type = PROG_INTEGER; idx.data.number = 0; val.type = PROG_INTEGER; val.data.number = substart + 1; array_setitem(&nu, &idx, &val); CLEAR(&idx); CLEAR(&val); idx.type = PROG_INTEGER; idx.data.number = 1; val.type = PROG_INTEGER; val.data.number = subend - substart; array_setitem(&nu, &idx, &val); CLEAR(&idx); CLEAR(&val); idx.type = PROG_INTEGER; idx.data.number = i; val.type = PROG_ARRAY; val.data.array = nu; array_setitem(&nu_idx, &idx, &val); CLEAR(&idx); CLEAR(&val); } } CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushArrayRaw(nu_val); PushArrayRaw(nu_idx); }
void prim_regsub(PRIM_PROTOTYPE) { int matches[MATCH_ARR_SIZE]; int flags = 0; char* write_ptr = buf; int write_left = BUFFER_LEN - 1; muf_re* re; char* text; char* textstart; const char* errstr; int matchcnt, len; CHECKOP(4); oper4 = POP(); /* int:Flags */ oper3 = POP(); /* str:Replace */ oper2 = POP(); /* str:Pattern */ oper1 = POP(); /* str:Text */ if (oper1->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (oper3->type != PROG_STRING) abort_interp("Non-string argument (3)"); if (oper4->type != PROG_INTEGER) abort_interp("Non-integer argument (4)"); if (!oper2->data.string) abort_interp("Empty string argument (2)"); if (oper4->data.number & MUF_RE_ICASE) flags |= PCRE_CASELESS; if (oper4->data.number & MUF_RE_EXTENDED) flags |= PCRE_EXTENDED; if ((re = muf_re_get(oper2->data.string, flags, &errstr)) == NULL) abort_interp(errstr); textstart = text = DoNullInd(oper1->data.string); len = strlen(textstart); while((*text != '\0') && (write_left > 0)) { if ((matchcnt = pcre_exec(re->re, NULL, textstart, len, text-textstart, 0, matches, MATCH_ARR_SIZE)) < 0) { if (matchcnt != PCRE_ERROR_NOMATCH) { abort_interp(muf_re_error(matchcnt)); } while((write_left > 0) && (*text != '\0')) { *write_ptr++ = *text++; write_left--; } break; } else { int allstart = matches[0]; int allend = matches[1]; int substart = -1; int subend = -1; char* read_ptr = DoNullInd(oper3->data.string); int count; for(count = allstart-(text-textstart); (write_left > 0) && (*text != '\0') && (count > 0); count--) { *write_ptr++ = *text++; write_left--; } while((write_left > 0) && (*read_ptr != '\0')) { if (*read_ptr == '\\') { if (!isdigit(*(++read_ptr))) { *write_ptr++ = *read_ptr++; write_left--; } else { int idx = (*read_ptr++) - '0'; if ((idx < 0) || (idx >= matchcnt)) { abort_interp("Invalid \\subexp in substitution string. (3)"); } substart = matches[idx*2]; subend = matches[idx*2+1]; if ((substart >= 0) && (subend >= 0) && (substart < len)) { char* ptr = &textstart[substart]; count = subend - substart; if (count > write_left) { abort_interp("Operation would result in overflow"); } for(; (write_left > 0) && (count > 0) && (*ptr != '\0'); count--) { *write_ptr++ = *ptr++; write_left--; } } } } else { *write_ptr++ = *read_ptr++; write_left--; } } for(count = allend - allstart; (*text != '\0') && (count > 0); count--) text++; if (allstart == allend && *text) { *write_ptr++ = *text++; write_left--; } } if ((oper4->data.number & MUF_RE_ALL) == 0) { while((write_left > 0) && (*text != '\0')) { *write_ptr++ = *text++; write_left--; } break; } } if (*text != '\0') abort_interp("Operation would result in overflow"); *write_ptr = '\0'; CLEAR(oper4); CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushString(buf); }
void prim_regsub(PRIM_PROTOTYPE) { regmatch_t *matches = 0; int flags = 0; char *write_ptr = buf; int write_left = BUFFER_LEN - 1; muf_re *re; char *text; int nosubs, err, len, i; CHECKOP(4); oper4 = POP(); /* int:Flags */ oper3 = POP(); /* str:Replace */ oper2 = POP(); /* str:Pattern */ oper1 = POP(); /* str:Text */ if (oper1->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (oper3->type != PROG_STRING) abort_interp("Non-string argument (3)"); if (oper4->type != PROG_INTEGER) abort_interp("Non-integer argument (4)"); if (!oper2->data.string) abort_interp("Empty string argument (2)"); if (oper4->data.number & MUF_RE_ICASE) flags |= REG_ICASE; if ((re = muf_re_get(oper2->data.string, flags, &err)) == NULL) abort_interp(muf_re_error(err)); text = DoNullInd(oper1->data.string); nosubs = re->re.re_nsub + 1; if ((matches = (regmatch_t *) malloc(sizeof(regmatch_t) * nosubs)) == NULL) abort_interp("Out of memory"); while ((*text != '\0') && (write_left > 0)) { len = strlen(text); if ((err = regexec(&re->re, text, nosubs, matches, 0)) != 0) { if (err != REG_NOMATCH) { free(matches); abort_interp(muf_re_error(err)); } while ((write_left > 0) && (*text != '\0')) { *write_ptr++ = *text++; write_left--; } break; } else { regmatch_t *cm = &matches[0]; char *read_ptr = DoNullInd(oper3->data.string); int soff = cm->rm_so; int count; for (count = cm->rm_so; (write_left > 0) && (*text != '\0') && (count > 0); count--) { *write_ptr++ = *text++; write_left--; } while ((write_left > 0) && (*read_ptr != '\0')) { if (*read_ptr == '\\') { if (!isdigit(*(++read_ptr))) { *write_ptr++ = *read_ptr++; write_left--; } else { int idx = (*read_ptr++) - '0'; if ((idx < 0) || (idx >= nosubs)) { free(matches); abort_interp("Invalid \\subexp (3)"); } cm = &matches[idx]; if ((cm->rm_so >= 0) && (cm->rm_eo >= 0) && (cm->rm_so < len)) { char *ptr = &text[cm->rm_so - soff]; count = cm->rm_eo - cm->rm_so; if (count > write_left) { free(matches); abort_interp ("Operation would result in overflow"); } for (; (write_left > 0) && (count > 0) && (*ptr != '\0'); count--) { *write_ptr++ = *ptr++; write_left--; } } } } else { *write_ptr++ = *read_ptr++; write_left--; } } cm = &matches[0]; for (count = cm->rm_eo - cm->rm_so; (*text != '\0') && (count > 0); count--) text++; } if ((oper4->data.number & MUF_RE_ALL) == 0) { while ((write_left > 0) && (*text != '\0')) { *write_ptr++ = *text++; write_left--; } break; } } free(matches); if (*text != '\0') abort_interp("Operation would result in overflow"); *write_ptr = '\0'; CLEAR(oper4); CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushString(buf); }
void prim_regexp(PRIM_PROTOTYPE) { stk_array *nu_val = 0; stk_array *nu_idx = 0; regmatch_t *matches = 0; muf_re *re; char *text; int flags = 0; int nosubs, err, len, i; CHECKOP(3); oper3 = POP(); /* int:Flags */ oper2 = POP(); /* str:Pattern */ oper1 = POP(); /* str:Text */ if (oper1->type != PROG_STRING) abort_interp("Non-string argument (1)"); if (oper2->type != PROG_STRING) abort_interp("Non-string argument (2)"); if (oper3->type != PROG_INTEGER) abort_interp("Non-integer argument (3)"); if (!oper2->data.string) abort_interp("Empty string argument (2)"); if (oper3->data.number & MUF_RE_ICASE) flags |= REG_ICASE; if ((re = muf_re_get(oper2->data.string, flags, &err)) == NULL) abort_interp(muf_re_error(err)); text = DoNullInd(oper1->data.string); len = strlen(text); nosubs = re->re.re_nsub + 1; if ((matches = (regmatch_t *) malloc(sizeof(regmatch_t) * nosubs)) == NULL) abort_interp("Out of memory"); if ((err = regexec(&re->re, text, nosubs, matches, 0)) != 0) { if (err != REG_NOMATCH) { free(matches); abort_interp(muf_re_error(err)); } if (((nu_val = new_array_packed(0)) == NULL) || ((nu_idx = new_array_packed(0)) == NULL)) { free(matches); if (nu_val != NULL) array_free(nu_val); if (nu_idx != NULL) array_free(nu_idx); abort_interp("Out of memory"); } } else { if (((nu_val = new_array_packed(nosubs)) == NULL) || ((nu_idx = new_array_packed(nosubs)) == NULL)) { free(matches); if (nu_val != NULL) array_free(nu_val); if (nu_idx != NULL) array_free(nu_idx); abort_interp("Out of memory"); } for (i = 0; i < nosubs; i++) { regmatch_t *cm = &matches[i]; struct inst idx, val; stk_array *nu; if ((cm->rm_so >= 0) && (cm->rm_eo >= 0) && (cm->rm_so < len)) snprintf(buf, BUFFER_LEN, "%.*s", cm->rm_eo - cm->rm_so, &text[cm->rm_so]); else buf[0] = '\0'; idx.type = PROG_INTEGER; idx.data.number = i; val.type = PROG_STRING; val.data.string = alloc_prog_string(buf); array_setitem(&nu_val, &idx, &val); CLEAR(&idx); CLEAR(&val); if ((nu = new_array_packed(2)) == NULL) { free(matches); array_free(nu_val); array_free(nu_idx); abort_interp("Out of memory"); } idx.type = PROG_INTEGER; idx.data.number = 0; val.type = PROG_INTEGER; val.data.number = cm->rm_so + 1; array_setitem(&nu, &idx, &val); CLEAR(&idx); CLEAR(&val); idx.type = PROG_INTEGER; idx.data.number = 1; val.type = PROG_INTEGER; val.data.number = cm->rm_eo - cm->rm_so; array_setitem(&nu, &idx, &val); CLEAR(&idx); CLEAR(&val); idx.type = PROG_INTEGER; idx.data.number = i; val.type = PROG_ARRAY; val.data.array = nu; array_setitem(&nu_idx, &idx, &val); CLEAR(&idx); CLEAR(&val); } } free(matches); CLEAR(oper3); CLEAR(oper2); CLEAR(oper1); PushArrayRaw(nu_val); PushArrayRaw(nu_idx); }