static char * name_from_address(char *str, int n) { char *s, *p; int l; bool space = true; s = allocStr(str, -1); SKIP_BLANKS(s); if (*s == '<' && (p = strchr(s, '>'))) { *p++ = '\0'; SKIP_BLANKS(p); if (*p == '\0') /* <address> */ s++; else /* <address> name ? */ s = p; } else if ((p = strchr(s, '<'))) /* name <address> */ *p = '\0'; else if ((p = strchr(s, '('))) /* address (name) */ s = p; if (*s == '"' && (p = strchr(s + 1, '"'))) { /* "name" */ *p = '\0'; s++; } else if (*s == '(' && (p = strchr(s + 1, ')'))) { /* (name) */ *p = '\0'; s++; } for (p = s, l = 0; *p; p += get_mclen(p)) { if (IS_SPACE(*p)) { if (space) continue; space = true; } else space = false; l += get_mcwidth(p); if (l > n) break; } *p = '\0'; return s; }
int RegexMatch(Regex *re, char *str, int len, int firstp) { char *p, *ep; char *lpos; Regex *r; if (str == NULL) return 0; if (len < 0) len = strlen(str); re->position = NULL; ep = str + len; for (p = str; p <= ep; p++) { lpos = NULL; re->lposition = NULL; for (r = re; r != NULL; r = r->alt_regex) { switch (regmatch(r->re, p, ep, firstp && (p == str), &lpos)) { case 1: /* matched */ re->position = p; if (re->lposition == NULL || re->lposition < lpos) re->lposition = lpos; break; case -1: /* error */ re->position = NULL; return -1; } } if (re->lposition != NULL) { /* matched */ return 1; } p += get_mclen(p) - 1; } return 0; }
static int form_update_line(Line *line, char **str, int spos, int epos, int width, int newline, int password) { int c_len = 1, c_width = 1, w, i, len, pos; char *p, *buf; Lineprop c_type, effect, *prop; for (p = *str, w = 0, pos = 0; *p && w < width;) { c_type = get_mctype((unsigned char *)p); #ifdef USE_M17N c_len = get_mclen(p); c_width = get_mcwidth(p); #endif if (c_type == PC_CTRL) { if (newline && *p == '\n') break; if (*p != '\r') { w++; pos++; } } else if (password) { #ifdef USE_M17N if (w + c_width > width) break; #endif w += c_width; pos += c_width; #ifdef USE_M17N } else if (c_type & PC_UNKNOWN) { w++; pos++; } else { if (w + c_width > width) break; #endif w += c_width; pos += c_len; } p += c_len; } pos += width - w; len = line->len + pos + spos - epos; buf = New_N(char, len); prop = New_N(Lineprop, len); memmove((void *)buf, (void *)line->lineBuf, spos * sizeof(char)); memmove((void *)prop, (void *)line->propBuf, spos * sizeof(Lineprop)); effect = CharEffect(line->propBuf[spos]); for (p = *str, w = 0, pos = spos; *p && w < width;) { c_type = get_mctype((unsigned char *)p); #ifdef USE_M17N c_len = get_mclen(p); c_width = get_mcwidth(p); #endif if (c_type == PC_CTRL) { if (newline && *p == '\n') break; if (*p != '\r') { buf[pos] = password ? '*' : ' '; prop[pos] = effect | PC_ASCII; pos++; w++; } } else if (password) { #ifdef USE_M17N if (w + c_width > width) break; #endif for (i = 0; i < c_width; i++) { buf[pos] = '*'; prop[pos] = effect | PC_ASCII; pos++; w++; } #ifdef USE_M17N } else if (c_type & PC_UNKNOWN) { buf[pos] = ' '; prop[pos] = effect | PC_ASCII; pos++; w++; } else { if (w + c_width > width) break; #else } else { #endif buf[pos] = *p; prop[pos] = effect | c_type; pos++; #ifdef USE_M17N c_type = (c_type & ~PC_WCHAR1) | PC_WCHAR2; for (i = 1; i < c_len; i++) { buf[pos] = p[i]; prop[pos] = effect | c_type; pos++; } #endif w += c_width; } p += c_len; }
Str checkType(Str s, Lineprop **oprop, Linecolor **ocolor) { Lineprop mode; Lineprop effect = PE_NORMAL; Lineprop *prop; static Lineprop *prop_buffer = NULL; static int prop_size = 0; char *str = s->ptr, *endp = &s->ptr[s->length], *bs = NULL; #ifdef USE_ANSI_COLOR Lineprop ceffect = PE_NORMAL; Linecolor cmode = 0; int check_color = FALSE; Linecolor *color = NULL; static Linecolor *color_buffer = NULL; static int color_size = 0; char *es = NULL; #endif int do_copy = FALSE; int i; int plen = 0, clen; if (prop_size < s->length) { prop_size = (s->length > LINELEN) ? s->length : LINELEN; prop_buffer = New_Reuse(Lineprop, prop_buffer, prop_size); } prop = prop_buffer; if (ShowEffect) { bs = memchr(str, '\b', s->length); #ifdef USE_ANSI_COLOR if (ocolor) { es = memchr(str, ESC_CODE, s->length); if (es) { if (color_size < s->length) { color_size = (s->length > LINELEN) ? s->length : LINELEN; color_buffer = New_Reuse(Linecolor, color_buffer, color_size); } color = color_buffer; } } #endif if ((bs != NULL) #ifdef USE_ANSI_COLOR || (es != NULL) #endif ) { char *sp = str, *ep; s = Strnew_size(s->length); do_copy = TRUE; ep = bs ? (bs - 2) : endp; #ifdef USE_ANSI_COLOR if (es && ep > es - 2) ep = es - 2; #endif for (; str < ep && IS_ASCII(*str); str++) { *(prop++) = PE_NORMAL | (IS_CNTRL(*str) ? PC_CTRL : PC_ASCII); #ifdef USE_ANSI_COLOR if (color) *(color++) = 0; #endif } Strcat_charp_n(s, sp, (int)(str - sp)); } } if (!do_copy) { for (; str < endp && IS_ASCII(*str); str++) *(prop++) = PE_NORMAL | (IS_CNTRL(*str) ? PC_CTRL : PC_ASCII); } while (str < endp) { if (prop - prop_buffer >= prop_size) break; if (bs != NULL) { #ifdef USE_M17N if (str == bs - 2 && !strncmp(str, "__\b\b", 4)) { str += 4; effect = PE_UNDER; if (str < endp) bs = memchr(str, '\b', endp - str); continue; } else #endif if (str == bs - 1 && *str == '_') { str += 2; effect = PE_UNDER; if (str < endp) bs = memchr(str, '\b', endp - str); continue; } else if (str == bs) { if (*(str + 1) == '_') { if (s->length) { str += 2; #ifdef USE_M17N for (i = 1; i <= plen; i++) *(prop - i) |= PE_UNDER; #else *(prop - 1) |= PE_UNDER; #endif } else { str++; } } #ifdef USE_M17N else if (!strncmp(str + 1, "\b__", 3)) { if (s->length) { str += (plen == 1) ? 3 : 4; for (i = 1; i <= plen; i++) *(prop - i) |= PE_UNDER; } else { str += 2; } } else if (*(str + 1) == '\b') { if (s->length) { clen = get_mclen(str + 2); if (plen == clen && !strncmp(str - plen, str + 2, plen)) { for (i = 1; i <= plen; i++) *(prop - i) |= PE_BOLD; str += 2 + clen; } else { Strshrink(s, plen); prop -= plen; str += 2; } } else { str += 2; } } #endif else { if (s->length) { #ifdef USE_M17N clen = get_mclen(str + 1); if (plen == clen && !strncmp(str - plen, str + 1, plen)) { for (i = 1; i <= plen; i++) *(prop - i) |= PE_BOLD; str += 1 + clen; } else { Strshrink(s, plen); prop -= plen; str++; } #else if (*(str - 1) == *(str + 1)) { *(prop - 1) |= PE_BOLD; str += 2; } else { Strshrink(s, 1); prop--; str++; } #endif } else { str++; } } if (str < endp) bs = memchr(str, '\b', endp - str); continue; } #ifdef USE_ANSI_COLOR else if (str > bs) bs = memchr(str, '\b', endp - str); #endif } #ifdef USE_ANSI_COLOR if (es != NULL) { if (str == es) { int ok = parse_ansi_color(&str, &ceffect, &cmode); if (str < endp) es = memchr(str, ESC_CODE, endp - str); if (ok) { if (cmode) check_color = TRUE; continue; } } else if (str > es) es = memchr(str, ESC_CODE, endp - str); } #endif plen = get_mclen(str); mode = get_mctype(str) | effect; #ifdef USE_ANSI_COLOR if (color) { *(color++) = cmode; mode |= ceffect; } #endif *(prop++) = mode; #ifdef USE_M17N if (plen > 1) { mode = (mode & ~PC_WCHAR1) | PC_WCHAR2; for (i = 1; i < plen; i++) { *(prop++) = mode; #ifdef USE_ANSI_COLOR if (color) *(color++) = cmode; #endif } if (do_copy) Strcat_charp_n(s, (char *)str, plen); str += plen; } else #endif { if (do_copy) Strcat_char(s, (char)*str); str++; } effect = PE_NORMAL; } *oprop = prop_buffer; #ifdef USE_ANSI_COLOR if (ocolor) *ocolor = check_color ? color_buffer : NULL; #endif return s; }
static int regmatch_iter(struct MatchingContext1 *c, regexchar * re, char *str, char *end_p, int firstp) { switch (c->label) { case 1: goto label1; case 2: goto label2; case 3: goto label3; case 4: goto label4; case 5: goto label5; case 6: goto label6; case 7: goto label7; } if (RE_MODE(re) == RE_ENDMARK) return 0; c->re = re; c->firstp = firstp; c->str = str; c->end_p = end_p; c->sub_ctx = NULL; c->lastpos = NULL; while (RE_MODE(c->re) != RE_ENDMARK) { if (c->re->mode & (RE_ANYTIME | RE_OPT)) { if (c->re->mode & RE_ANYTIME) c->iter_limit = RE_ITER_LIMIT; else c->iter_limit = 1; c->n_any = -1; while (c->n_any < c->iter_limit) { if (c->str + c->n_any >= c->end_p) { return 0; } if (c->n_any >= 0) { if (RE_MODE(c->re) == RE_SUBREGEX) { c->ctx2 = GC_malloc(sizeof(struct MatchingContext2)); c->ctx2->label = 0; while (regmatch_sub_anytime(c->ctx2, c->re->p.sub, c->re + 1, c->str + c->n_any, c->end_p, c->iter_limit, c->firstp)) { c->n_any = c->ctx2->lastpos - c->str; c->lastpos = c->ctx2->lastpos; YIELD(1, c, 1); } return 0; } else { longchar k; k = set_longchar(c->str + c->n_any); if (regmatch1(c->re, &k)) { c->n_any += get_mclen(c->str + c->n_any); } else { return 0; } c->firstp = 0; } } else c->n_any++; if (RE_MODE(c->re + 1) == RE_ENDMARK) { c->lastpos = c->str + c->n_any; YIELD(1, c, 2); } else if (regmatch(c->re + 1, c->str + c->n_any, c->end_p, c->firstp, &c->lastpos) == 1) { YIELD(1, c, 3); } } return 0; } /* regexp other than pat*, pat+ and pat? */ switch (RE_MODE(c->re)) { case RE_BEGIN: if (!c->firstp) return 0; c->re++; break; case RE_END: if (c->str >= c->end_p) { c->lastpos = c->str; c->re++; YIELD(1, c, 4); } else { c->lastpos = NULL; return 0; } break; case RE_SUBREGEX: if (c->sub_ctx == NULL) { c->sub_ctx = GC_malloc(sizeof(struct MatchingContext1)); } c->sub_regex = c->re->p.sub; for (;;) { c->sub_ctx->label = 0; while (regmatch_iter(c->sub_ctx, c->sub_regex->re, c->str, c->end_p, c->firstp)) { if (c->sub_ctx->lastpos != c->str) c->firstp = 0; if (RE_MODE(c->re + 1) == RE_ENDMARK) { c->lastpos = c->sub_ctx->lastpos; YIELD(1, c, 5); } else if (regmatch(c->re + 1, c->sub_ctx->lastpos, c->end_p, c->firstp, &c->lastpos) == 1) { YIELD(1, c, 6); } } if (c->sub_regex->alt_regex == NULL) break; c->sub_regex = c->sub_regex->alt_regex; } return 0; default: { longchar k; k = set_longchar(c->str); c->str += get_mclen(c->str); if (!regmatch1(c->re, &k)) return 0; } c->re++; c->firstp = 0; } if (c->str > c->end_p) { return 0; } } c->lastpos = c->str; #ifdef REGEX_DEBUG if (verbose) printf("Succeed: %s %d\n", c->str, c->lastpos - c->str); #endif YIELD(1, c, 7); return 0; }
static Regex * newRegex0(char **ex, int igncase, Regex *regex, char **msg, int level) { char *p; longchar *r; regexchar *re; int m; longchar *st_ptr; if (regex == NULL) regex = (Regex *)GC_malloc(sizeof(Regex)); regex->alt_regex = NULL; re = regex->re; st_ptr = regex->storage; for (p = *ex; *p != '\0'; p++) { re->mode = 0; switch (*p) { case '.': re->p.pattern = NULL; RE_SET_MODE(re, RE_ANY); re++; break; case '$': re->p.pattern = NULL; RE_SET_MODE(re, RE_END); re++; break; case '^': re->p.pattern = NULL; RE_SET_MODE(re, RE_BEGIN); re++; break; case '+': if (re == regex->re || (RE_MODE(re - 1) != RE_ANY && (re - 1)->p.pattern == NULL)) { if (msg) *msg = "Invalid regular expression"; return NULL; } *re = *(re - 1); re->mode |= RE_ANYTIME; re++; break; case '*': if (re == regex->re || (RE_MODE(re - 1) != RE_ANY && (re - 1)->p.pattern == NULL)) { if (msg) *msg = "Invalid regular expression"; return NULL; } (re - 1)->mode |= RE_ANYTIME; break; case '?': if (re == regex->re || (RE_MODE(re - 1) != RE_ANY && (re - 1)->p.pattern == NULL)) { if (msg) *msg = "Invalid regular expression"; return NULL; } (re - 1)->mode |= RE_OPT; break; case '[': r = st_ptr; if (*++p == '^') { p++; m = RE_EXCEPT; } else m = RE_WHICH; if (*p == '-' || *p == ']') *(st_ptr++) = set_longchar(p); while (*p != ']') { if (*p == '\\') { p++; *(st_ptr++) = set_longchar(p); p += get_mclen(p); } else if (*p == '-' && *(p + 1) != ']') { (st_ptr++)->type = RE_WHICH_RANGE; p++; } else if (*p == '\0') { if (msg) *msg = "Missing ]"; return NULL; } else { *(st_ptr++) = set_longchar(p); p += get_mclen(p); } if (st_ptr >= ®ex->storage[STORAGE_MAX]) { if (msg) *msg = "Regular expression too long"; return NULL; } } (st_ptr++)->type = RE_TYPE_END; re->p.pattern = r; RE_SET_MODE(re, m); if (igncase) re->mode |= RE_IGNCASE; re++; break; case '|': RE_SET_MODE(re, RE_ENDMARK); re++; p++; regex->alt_regex = newRegex0(&p, igncase, NULL, msg, level); if (regex->alt_regex == NULL) return NULL; *ex = p; return regex; case '(': RE_SET_MODE(re, RE_SUBREGEX); p++; re->p.sub = newRegex0(&p, igncase, NULL, msg, level + 1); if (re->p.sub == NULL) return NULL; re++; break; case ')': if (level == 0) { if (msg) *msg = "Too many ')'"; return NULL; } RE_SET_MODE(re, RE_ENDMARK); re++; *ex = p; return regex; case '\\': p++; default: *(st_ptr) = set_longchar(p); p += get_mclen(p) - 1; re->p.pattern = st_ptr; st_ptr++; RE_SET_MODE(re, RE_NORMAL); if (igncase) re->mode |= RE_IGNCASE; re++; } if (st_ptr >= ®ex->storage[STORAGE_MAX] || re >= ®ex->re[REGEX_MAX]) { if (msg) *msg = "Regular expression too long"; return NULL; } } RE_SET_MODE(re, RE_ENDMARK); if (msg) *msg = NULL; *ex = p; return regex; }