📄 compile.c
字号:
*repp = xmalloc(sizeof(regex_t)); if (p && (eval = regcomp(*repp, re, 0)) != 0) err(COMPILE, "RE error: %s", strregerror(eval, *repp)); if (maxnsub < (*repp)->re_nsub) maxnsub = (*repp)->re_nsub; return (p);}/* * Compile the substitution string of a regular expression and set res to * point to a saved copy of it. Nsub is the number of parenthesized regular * expressions. */static char *compile_subst(p, s) char *p; struct s_subst *s;{ static char lbuf[_POSIX2_LINE_MAX + 1]; int asize, ref, size; char c, *text, *op, *sp; c = *p++; /* Terminator character */ if (c == '\0') return (NULL); s->maxbref = 0; s->linenum = linenum; asize = 2 * _POSIX2_LINE_MAX + 1; text = xmalloc(asize); size = 0; do { op = sp = text + size; for (; *p; p++) { if (*p == '\\') { p++; if (strchr("123456789", *p) != NULL) { *sp++ = '\\'; ref = *p - '0'; if (s->re != NULL && ref > s->re->re_nsub) err(COMPILE,"\\%c not defined in the RE", *p); if (s->maxbref < ref) s->maxbref = ref; } else if (*p == '&' || *p == '\\') *sp++ = '\\'; } else if (*p == c) { p++; *sp++ = '\0'; size += sp - op; s->new = xrealloc(text, size); return (p); } else if (*p == '\n') { err(COMPILE,"unescaped newline inside substitute pattern"); /* NOTREACHED */ } *sp++ = *p; } size += sp - op; if (asize - size < _POSIX2_LINE_MAX + 1) { asize *= 2; text = xmalloc(asize); } } while (cu_fgets(p = lbuf, sizeof(lbuf))); err(COMPILE, "unterminated substitute in regular expression"); /* NOTREACHED */}/* * Compile the flags of the s command */static char *compile_flags(p, s) char *p; struct s_subst *s;{ int gn; /* True if we have seen g or n */ char wfile[_POSIX2_LINE_MAX + 1], *q; s->n = 1; /* Default */ s->p = 0; s->wfile = NULL; s->wfd = -1; for (gn = 0;;) { EATSPACE(); /* EXTENSION */ switch (*p) { case 'g': if (gn) err(COMPILE,"more than one number or 'g' in substitute flags"); gn = 1; s->n = 0; break; case '\0': case '\n': case ';': return (p); case 'p': s->p = 1; break; case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': if (gn) err(COMPILE,"more than one number or 'g' in substitute flags"); gn = 1; /* XXX Check for overflow */ s->n = (int)strtol(p, &p, 10); break; case 'w': p++;#ifdef HISTORIC_PRACTICE if (*p != ' ') { err(WARNING, "space missing before w wfile"); return (p); }#endif EATSPACE(); q = wfile; while (*p) { if (*p == '\n') break; *q++ = *p++; } *q = '\0'; if (q == wfile) err(COMPILE, "no wfile specified"); s->wfile = strdup(wfile); if (!aflag && (s->wfd = open(wfile, O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, DEFFILEMODE)) == -1) err(FATAL, "%s: %s\n", wfile, strerror(errno)); return (p); default: err(COMPILE, "bad flag in substitute command: '%c'", *p); break; } p++; }}/* * Compile a translation set of strings into a lookup table. */static char *compile_tr(p, transtab) char *p; char **transtab;{ int i; char *lt, *op, *np; char old[_POSIX2_LINE_MAX + 1]; char new[_POSIX2_LINE_MAX + 1]; if (*p == '\0' || *p == '\\') err(COMPILE,"transform pattern can not be delimited by newline or backslash"); p = compile_delimited(p, old); if (p == NULL) { err(COMPILE, "unterminated transform source string"); return (NULL); } p = compile_delimited(--p, new); if (p == NULL) { err(COMPILE, "unterminated transform target string"); return (NULL); } EATSPACE(); if (strlen(new) != strlen(old)) { err(COMPILE, "transform strings are not the same length"); return (NULL); } /* We assume characters are 8 bits */ lt = xmalloc(UCHAR_MAX); for (i = 0; i <= UCHAR_MAX; i++) lt[i] = (char)i; for (op = old, np = new; *op; op++, np++) lt[(u_char)*op] = *np; *transtab = lt; return (p);}/* * Compile the text following an a or i command. */static char *compile_text(){ int asize, size; char *text, *p, *op, *s; char lbuf[_POSIX2_LINE_MAX + 1]; asize = 2 * _POSIX2_LINE_MAX + 1; text = xmalloc(asize); size = 0; while (cu_fgets(lbuf, sizeof(lbuf))) { op = s = text + size; p = lbuf; EATSPACE(); for (; *p; p++) { if (*p == '\\') p++; *s++ = *p; } size += s - op; if (p[-2] != '\\') { *s = '\0'; break; } if (asize - size < _POSIX2_LINE_MAX + 1) { asize *= 2; text = xmalloc(asize); } } return (xrealloc(text, size + 1));}/* * Get an address and return a pointer to the first character after * it. Fill the structure pointed to according to the address. */static char *compile_addr(p, a) char *p; struct s_addr *a;{ char *end; switch (*p) { case '\\': /* Context address */ ++p; /* FALLTHROUGH */ case '/': /* Context address */ p = compile_re(p, &a->u.r); if (p == NULL) err(COMPILE, "unterminated regular expression"); a->type = AT_RE; return (p); case '$': /* Last line */ a->type = AT_LAST; return (p + 1); /* Line number */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': a->type = AT_LINE; a->u.l = strtol(p, &end, 10); return (end); default: err(COMPILE, "expected context address"); return (NULL); }}/* * duptoeol -- * Return a copy of all the characters up to \n or \0. */static char *duptoeol(s, ctype) register char *s; char *ctype;{ size_t len; int ws; char *start; ws = 0; for (start = s; *s != '\0' && *s != '\n'; ++s) ws = isspace(*s); *s = '\0'; if (ws) err(WARNING, "whitespace after %s", ctype); len = s - start + 1; return (memmove(xmalloc(len), start, len));}/* * Convert goto label names to addresses, and count a and r commands, in * the given subset of the script. Free the memory used by labels in b * and t commands (but not by :). * * TODO: Remove } nodes */static voidfixuplabel(cp, end) struct s_command *cp, *end;{ for (; cp != end; cp = cp->next) switch (cp->code) { case 'a': case 'r': appendnum++; break; case 'b': case 't': /* Resolve branch target. */ if (cp->t == NULL) { cp->u.c = NULL; break; } if ((cp->u.c = findlabel(cp->t)) == NULL) err(COMPILE2, "undefined label '%s'", cp->t); free(cp->t); break; case '{': /* Do interior commands. */ fixuplabel(cp->u.c, cp->next); break; }}/* * Associate the given command label for later lookup. */static voidenterlabel(cp) struct s_command *cp;{ register struct labhash **lhp, *lh; register u_char *p; register u_int h, c; for (h = 0, p = (u_char *)cp->t; (c = *p) != 0; p++) h = (h << 5) + h + c; lhp = &labels[h & LHMASK]; for (lh = *lhp; lh != NULL; lh = lh->lh_next) if (lh->lh_hash == h && strcmp(cp->t, lh->lh_cmd->t) == 0) err(COMPILE2, "duplicate label '%s'", cp->t); lh = xmalloc(sizeof *lh); lh->lh_next = *lhp; lh->lh_hash = h; lh->lh_cmd = cp; lh->lh_ref = 0; *lhp = lh;}/* * Find the label contained in the command l in the command linked * list cp. L is excluded from the search. Return NULL if not found. */static struct s_command *findlabel(name) char *name;{ register struct labhash *lh; register u_char *p; register u_int h, c; for (h = 0, p = (u_char *)name; (c = *p) != 0; p++) h = (h << 5) + h + c; for (lh = labels[h & LHMASK]; lh != NULL; lh = lh->lh_next) { if (lh->lh_hash == h && strcmp(name, lh->lh_cmd->t) == 0) { lh->lh_ref = 1; return (lh->lh_cmd); } } return (NULL);}/* * Warn about any unused labels. As a side effect, release the label hash * table space. */static voiduselabel(){ register struct labhash *lh, *next; register int i; for (i = 0; i < LHSZ; i++) { for (lh = labels[i]; lh != NULL; lh = next) { next = lh->lh_next; if (!lh->lh_ref) err(WARNING, "unused label '%s'", lh->lh_cmd->t); free(lh); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -