static const char * next_s(const char *s) { /* find next position in s, ignoring braces and ignoring TeX control sequences and any space that follows them */ for (++s; (*s != '\0'); ) { switch (*s) { case '\\': /* TeX control sequence */ ++s; /* look at next character */ if (Isalpha((int)*s)) /* \<one-or-more-letters> */ { while (Isalpha((int)*s)) ++s; } else /* \<non-letter> */ ++s; while (Isspace((int)*s)) /* advance over trailing whitespace */ ++s; /* since TeX does too */ break; case '{': case '}': ++s; break; case BIBTEX_HIDDEN_DELIMITER: /* ignore delimited inline comment */ for (++s; (*s != '\0'); ++s) { if (*s == BIBTEX_HIDDEN_DELIMITER) { ++s; break; } } break; default: return (s); } /* end switch */ } /* end for */ return (s); }
YESorNO match_pattern(const char *s, const char *pattern) { const char *org_s; const char *org_pattern; org_s = s; org_pattern = pattern; s = next_s(s-1); for ( ; (*pattern != '\0'); ++pattern) { switch(*pattern) { case 'a': /* single letter */ if (!Isalpha((int)*s)) RETURN_MATCH_FAILURE("single letter"); s = next_s(s); break; case 'A': /* one or more letters */ if (!Isalpha((int)*s)) RETURN_MATCH_FAILURE("one or more letters"); while (Isalpha((int)*s)) s = next_s(s); break; case 'd': if (!Isdigit((int)*s)) /* single digit */ RETURN_MATCH_FAILURE("single digit"); s = next_s(s); break; case 'D': /* one or more digits */ if (!Isdigit((int)*s)) RETURN_MATCH_FAILURE("one or more digits"); while (Isdigit((int)*s)) s = next_s(s); break; case 'r': /* single roman numeral */ if (!is_roman((int)*s)) RETURN_MATCH_FAILURE("single roman numeral"); s = next_s(s); break; case 'R': /* one or more roman numerals */ if (!is_roman((int)*s)) RETURN_MATCH_FAILURE("one or more roman numerals"); while (is_roman((int)*s)) s = next_s(s); break; case 'w': /* one word (letters and digits) */ if (!Isalnum((int)*s)) RETURN_MATCH_FAILURE("one word (letters and digits)"); while (Isalnum((int)*s)) s = next_s(s); break; case 'W': /* one or more space-separated words */ if (!Isalnum((int)*s)) RETURN_MATCH_FAILURE("one or more space-separated words"); while (Isalnum((int)*s)) /* parse first word */ s = next_s(s); for (;;) { if (!Isspace((int)*s)) break; while (Isspace((int)*s)) /* parse separators */ s = next_s(s); while (Isalnum((int)*s)) /* parse another word */ s = next_s(s); } break; case 'X': /* one or more special-separated words */ if (!Isalnum((int)*s)) RETURN_MATCH_FAILURE("one or more special-separated words"); while (Isalnum((int)*s)) /* parse first word */ s = next_s(s); for (;;) { if (!is_special(*s)) break; while (is_special(*s)) /* parse separators */ s = next_s(s); while (Isalnum((int)*s)) /* parse another word */ s = next_s(s); } break; case ' ': /* one or more whitespace characters */ if (!Isspace((int)*s)) RETURN_MATCH_FAILURE("one or more whitespace characters"); while (Isspace((int)*s)) s = next_s(s); break; case '.': /* exactly one special character */ if (!is_special(*s)) RETURN_MATCH_FAILURE("exactly one special character"); s = next_s(s); /* [07-Mar-1999] bug fix: missing before bibclean 2.12 */ break; case ':': /* one or more special characters */ if (!is_special(*s)) RETURN_MATCH_FAILURE("one or more special characters"); while (is_special(*s)) s = next_s(s); break; case '\\': /* literal next character */ pattern++; /* fall through to exact match test */ /*@fallthrough@*/ /*FALLTHROUGH*/ default: /* anything else: exact match */ if (*pattern != *s) RETURN_MATCH_FAILURE("anything else: exact match"); s = next_s(s); } /* end switch */ } /* end for (; ;) */ if (*s == '\0') return (YES); else RETURN_MATCH_FAILURE("end of string"); }
eChar parseescape(const Char **ptr) { const Char *p; Char c; p = *ptr; if ((p[1] & CHAR) == 0) { xprintf(CGETS(9, 8, "Something must follow: %c\n"), (char)*p); return CHAR_ERR; } if ((*p & CHAR) == '\\') { p++; switch (*p & CHAR) { case 'a': c = CTL_ESC('\007'); /* Bell */ break; case 'b': c = CTL_ESC('\010'); /* Backspace */ break; case 'e': c = CTL_ESC('\033'); /* Escape */ break; case 'f': c = CTL_ESC('\014'); /* Form Feed */ break; case 'n': c = CTL_ESC('\012'); /* New Line */ break; case 'r': c = CTL_ESC('\015'); /* Carriage Return */ break; case 't': c = CTL_ESC('\011'); /* Horizontal Tab */ break; case 'v': c = CTL_ESC('\013'); /* Vertical Tab */ break; case '\\': c = '\\'; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': { int cnt, val; Char ch; for (cnt = 0, val = 0; cnt < 3; cnt++) { ch = *p++ & CHAR; if (ch < '0' || ch > '7') { p--; break; } val = (val << 3) | (ch - '0'); } if ((val & ~0xff) != 0) { xprintf("%s", CGETS(9, 9, "Octal constant does not fit in a char.\n")); return 0; } #ifndef IS_ASCII if (CTL_ESC(val) != val && adrof(STRwarnebcdic)) xprintf(/*CGETS(9, 9, no NLS-String yet!*/ "Warning: Octal constant \\%3.3o is interpreted as EBCDIC value.\n", val/*)*/); #endif c = (Char) val; --p; } break; default: c = *p; break; } } else if ((*p & CHAR) == '^' && (Isalpha(p[1] & CHAR) || strchr("@^_?\\|[{]}", p[1] & CHAR))) { p++; #ifdef IS_ASCII c = ((*p & CHAR) == '?') ? CTL_ESC('\177') : ((*p & CHAR) & 0237); #else c = ((*p & CHAR) == '?') ? CTL_ESC('\177') : _toebcdic[_toascii[*p & CHAR] & 0237]; if (adrof(STRwarnebcdic)) xprintf(/*CGETS(9, 9, no NLS-String yet!*/ "Warning: Control character ^%c may be interpreted differently in EBCDIC.\n", *p & CHAR /*)*/); #endif } else c = *p; *ptr = p; return (c); }