diff options
Diffstat (limited to 'sed/compile.c')
-rw-r--r-- | sed/compile.c | 1475 |
1 files changed, 728 insertions, 747 deletions
diff --git a/sed/compile.c b/sed/compile.c index 513fac5..7a28e56 100644 --- a/sed/compile.c +++ b/sed/compile.c @@ -1,6 +1,5 @@ /* GNU SED, a batch stream editor. - Copyright (C) 1989,90,91,92,93,94,95,98,99,2002,2003,2004,2005,2006,2008,2010 - Free Software Foundation, Inc. + Copyright (C) 1989-2016 Free Software Foundation, Inc. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -33,7 +32,7 @@ /* let's not confuse text editors that have only dumb bracket-matching... */ #define OPEN_BRACKET '[' #define CLOSE_BRACKET ']' -#define OPEN_BRACE '{' +/* #define OPEN_BRACE '{' */ #define CLOSE_BRACE '}' struct prog_info { @@ -78,11 +77,11 @@ struct special_files { FILE **pfp; }; -FILE *my_stdin, *my_stdout, *my_stderr; -struct special_files special_files[] = { - { { "/dev/stdin", false, NULL, NULL }, &my_stdin }, - { { "/dev/stdout", false, NULL, NULL }, &my_stdout }, - { { "/dev/stderr", false, NULL, NULL }, &my_stderr }, +static FILE *my_stdin, *my_stdout, *my_stderr; +static struct special_files special_files[] = { + { { (char *) "/dev/stdin", false, NULL, NULL }, &my_stdin }, + { { (char *) "/dev/stdout", false, NULL, NULL }, &my_stdout }, + { { (char *) "/dev/stderr", false, NULL, NULL }, &my_stderr }, { { NULL, false, NULL, NULL }, NULL } }; @@ -138,44 +137,67 @@ static const char errors[] = "expected newer version of sed\0" "invalid usage of line address 0\0" "unknown command: `%c'\0" - "incomplete command"; + "incomplete command\0" + "\":\" lacks a label\0" + "recursive escaping after \\c not allowed\0" + "e/r/w commands disabled in sandbox mode"; #define BAD_BANG (errors) #define BAD_COMMA (BAD_BANG + sizeof(N_("multiple `!'s"))) #define BAD_STEP (BAD_COMMA + sizeof(N_("unexpected `,'"))) -#define EXCESS_OPEN_BRACE (BAD_STEP + sizeof(N_("invalid usage of +N or ~N as first address"))) +#define EXCESS_OPEN_BRACE (BAD_STEP \ + + sizeof(N_("invalid usage of +N or ~N as first address"))) #define EXCESS_CLOSE_BRACE (EXCESS_OPEN_BRACE + sizeof(N_("unmatched `{'"))) #define EXCESS_JUNK (EXCESS_CLOSE_BRACE + sizeof(N_("unexpected `}'"))) -#define EXPECTED_SLASH (EXCESS_JUNK + sizeof(N_("extra characters after command"))) -#define NO_CLOSE_BRACE_ADDR (EXPECTED_SLASH + sizeof(N_("expected \\ after `a', `c' or `i'"))) -#define NO_COLON_ADDR (NO_CLOSE_BRACE_ADDR + sizeof(N_("`}' doesn't want any addresses"))) -#define NO_SHARP_ADDR (NO_COLON_ADDR + sizeof(N_(": doesn't want any addresses"))) -#define NO_COMMAND (NO_SHARP_ADDR + sizeof(N_("comments don't accept any addresses"))) +#define EXPECTED_SLASH (EXCESS_JUNK \ + + sizeof(N_("extra characters after command"))) +#define NO_CLOSE_BRACE_ADDR (EXPECTED_SLASH \ + + sizeof(N_("expected \\ after `a', `c' or `i'"))) +#define NO_COLON_ADDR (NO_CLOSE_BRACE_ADDR \ + + sizeof(N_("`}' doesn't want any addresses"))) +#define NO_SHARP_ADDR (NO_COLON_ADDR \ + + sizeof(N_(": doesn't want any addresses"))) +#define NO_COMMAND (NO_SHARP_ADDR \ + + sizeof(N_("comments don't accept any addresses"))) #define ONE_ADDR (NO_COMMAND + sizeof(N_("missing command"))) #define UNTERM_ADDR_RE (ONE_ADDR + sizeof(N_("command only uses one address"))) #define UNTERM_S_CMD (UNTERM_ADDR_RE + sizeof(N_("unterminated address regex"))) #define UNTERM_Y_CMD (UNTERM_S_CMD + sizeof(N_("unterminated `s' command"))) #define UNKNOWN_S_OPT (UNTERM_Y_CMD + sizeof(N_("unterminated `y' command"))) #define EXCESS_P_OPT (UNKNOWN_S_OPT + sizeof(N_("unknown option to `s'"))) -#define EXCESS_G_OPT (EXCESS_P_OPT + sizeof(N_("multiple `p' options to `s' command"))) -#define EXCESS_N_OPT (EXCESS_G_OPT + sizeof(N_("multiple `g' options to `s' command"))) -#define ZERO_N_OPT (EXCESS_N_OPT + sizeof(N_("multiple number options to `s' command"))) -#define Y_CMD_LEN (ZERO_N_OPT + sizeof(N_("number option to `s' command may not be zero"))) -#define BAD_DELIM (Y_CMD_LEN + sizeof(N_("strings for `y' command are different lengths"))) -#define ANCIENT_VERSION (BAD_DELIM + sizeof(N_("delimiter character is not a single-byte character"))) -#define INVALID_LINE_0 (ANCIENT_VERSION + sizeof(N_("expected newer version of sed"))) -#define UNKNOWN_CMD (INVALID_LINE_0 + sizeof(N_("invalid usage of line address 0"))) +#define EXCESS_G_OPT (EXCESS_P_OPT \ + + sizeof(N_("multiple `p' options to `s' command"))) +#define EXCESS_N_OPT (EXCESS_G_OPT \ + + sizeof(N_("multiple `g' options to `s' command"))) +#define ZERO_N_OPT (EXCESS_N_OPT \ + + sizeof(N_("multiple number options to `s' command"))) +#define Y_CMD_LEN (ZERO_N_OPT \ + + sizeof(N_("number option to `s' command may not be zero"))) +#define BAD_DELIM (Y_CMD_LEN \ + + sizeof(N_("strings for `y' command are different lengths"))) +#define ANCIENT_VERSION (BAD_DELIM \ + + sizeof(N_("delimiter character is not a single-byte character"))) +#define INVALID_LINE_0 (ANCIENT_VERSION \ + + sizeof(N_("expected newer version of sed"))) +#define UNKNOWN_CMD (INVALID_LINE_0 \ + + sizeof(N_("invalid usage of line address 0"))) #define INCOMPLETE_CMD (UNKNOWN_CMD + sizeof(N_("unknown command: `%c'"))) -#define END_ERRORS (INCOMPLETE_CMD + sizeof(N_("incomplete command"))) +#define COLON_LACKS_LABEL (INCOMPLETE_CMD \ + + sizeof(N_("incomplete command"))) +#define RECURSIVE_ESCAPE_C (COLON_LACKS_LABEL \ + + sizeof(N_("\":\" lacks a label"))) +#define DISALLOWED_CMD (RECURSIVE_ESCAPE_C \ + + sizeof(N_("recursive escaping after \\c not allowed"))) +/* #define END_ERRORS (DISALLOWED_CMD \ + + sizeof(N_( "e/r/w commands disabled in sandbox mode"))) */ static struct output *file_read = NULL; static struct output *file_write = NULL; /* Complain about an unknown command and exit. */ -void -bad_command(ch) - char ch; +static void +bad_command(char ch) { const char *msg = _(UNKNOWN_CMD); char *unknown_cmd = xmalloc(strlen(msg)); @@ -185,40 +207,38 @@ bad_command(ch) /* Complain about a programming error and exit. */ void -bad_prog(why) - const char *why; +bad_prog(const char *why) { if (cur_input.name) fprintf(stderr, _("%s: file %s line %lu: %s\n"), - myname, cur_input.name, (unsigned long)cur_input.line, why); + myname, cur_input.name, (unsigned long)cur_input.line, why); else fprintf(stderr, _("%s: -e expression #%lu, char %lu: %s\n"), - myname, - (unsigned long)cur_input.string_expr_count, - (unsigned long)(prog.cur-prog.base), - why); - exit(EXIT_FAILURE); + myname, + (unsigned long)cur_input.string_expr_count, + (unsigned long)(prog.cur-prog.base), + why); + exit(EXIT_BAD_USAGE); } /* Read the next character from the program. Return EOF if there isn't anything to read. Keep cur_input.line up to date, so error messages can be meaningful. */ -static int inchar (void); static int -inchar() +inchar(void) { int ch = EOF; if (prog.cur) { if (prog.cur < prog.end) - ch = *prog.cur++; + ch = *prog.cur++; } else if (prog.file) { if (!feof(prog.file)) - ch = getc(prog.file); + ch = getc(prog.file); } if (ch == '\n') ++cur_input.line; @@ -226,10 +246,8 @@ inchar() } /* unget `ch' so the next call to inchar will return it. */ -static void savchar (int ch); static void -savchar(ch) - int ch; +savchar(int ch) { if (ch == EOF) return; @@ -238,17 +256,16 @@ savchar(ch) if (prog.cur) { if (prog.cur <= prog.base || *--prog.cur != ch) - panic("Called savchar() with unexpected pushback (%x)", - (unsigned char)ch); + panic("Called savchar() with unexpected pushback (%x)", + (unsigned char)ch); } else ungetc(ch, prog.file); } /* Read the next non-blank character from the program. */ -static int in_nonblank (void); static int -in_nonblank() +in_nonblank(void) { int ch; do @@ -258,10 +275,8 @@ in_nonblank() } /* Read an integer value from the program. */ -static countT in_integer (int ch); static countT -in_integer(ch) - int ch; +in_integer (int ch) { countT num = 0; @@ -274,23 +289,15 @@ in_integer(ch) return num; } -static int add_then_next (struct buffer *b, int ch); static int -add_then_next(b, ch) - struct buffer *b; - int ch; +add_then_next(struct buffer *b, int ch) { add1_buffer(b, ch); return inchar(); } -static char * convert_number (char *, char *, const char *, int); static char * -convert_number(result, buf, bufend, base) - char *result; - char *buf; - const char *bufend; - int base; +convert_number(char *result, char *buf, const char *bufend, int base) { int n = 0; int max = 1; @@ -300,26 +307,26 @@ convert_number(result, buf, bufend, base) { int d = -1; switch (*p) - { - case '0': d = 0x0; break; - case '1': d = 0x1; break; - case '2': d = 0x2; break; - case '3': d = 0x3; break; - case '4': d = 0x4; break; - case '5': d = 0x5; break; - case '6': d = 0x6; break; - case '7': d = 0x7; break; - case '8': d = 0x8; break; - case '9': d = 0x9; break; - case 'A': case 'a': d = 0xa; break; - case 'B': case 'b': d = 0xb; break; - case 'C': case 'c': d = 0xc; break; - case 'D': case 'd': d = 0xd; break; - case 'E': case 'e': d = 0xe; break; - case 'F': case 'f': d = 0xf; break; - } + { + case '0': d = 0x0; break; + case '1': d = 0x1; break; + case '2': d = 0x2; break; + case '3': d = 0x3; break; + case '4': d = 0x4; break; + case '5': d = 0x5; break; + case '6': d = 0x6; break; + case '7': d = 0x7; break; + case '8': d = 0x8; break; + case '9': d = 0x9; break; + case 'A': case 'a': d = 0xa; break; + case 'B': case 'b': d = 0xb; break; + case 'C': case 'c': d = 0xc; break; + case 'D': case 'd': d = 0xd; break; + case 'E': case 'e': d = 0xe; break; + case 'F': case 'f': d = 0xf; break; + } if (d < 0 || base <= d) - break; + break; n = n * base + d; } if (p == buf+1) @@ -331,24 +338,26 @@ convert_number(result, buf, bufend, base) /* Read in a filename for a `r', `w', or `s///w' command. */ -static struct buffer *read_filename (void); static struct buffer * -read_filename() +read_filename(void) { struct buffer *b; int ch; + if (sandbox) + bad_prog(_(DISALLOWED_CMD)); + b = init_buffer(); ch = in_nonblank(); while (ch != EOF && ch != '\n') { #if 0 /*XXX ZZZ 1998-09-12 kpp: added, then had second thoughts*/ if (posixicity == POSIXLY_EXTENDED) - if (ch == ';' || ch == '#') - { - savchar(ch); - break; - } + if (ch == ';' || ch == '#') + { + savchar(ch); + break; + } #endif ch = add_then_next(b, ch); } @@ -356,12 +365,8 @@ read_filename() return b; } -static struct output *get_openfile (struct output **file_ptrs, const char *mode, int fail); static struct output * -get_openfile(file_ptrs, mode, fail) - struct output **file_ptrs; - const char *mode; - int fail; +get_openfile (struct output **file_ptrs, const char *mode, int fail) { struct buffer *b; char *file_name; @@ -377,16 +382,16 @@ get_openfile(file_ptrs, mode, fail) { /* Check whether it is a special file (stdin, stdout or stderr) */ struct special_files *special = special_files; - + /* std* sometimes are not constants, so they cannot be used in the initializer for special_files */ my_stdin = stdin; my_stdout = stdout; my_stderr = stderr; for (special = special_files; special->outf.name; special++) if (strcmp(special->outf.name, file_name) == 0) { - special->outf.fp = *special->pfp; - free_buffer (b); - return &special->outf; + special->outf.fp = *special->pfp; + free_buffer (b); + return &special->outf; } } @@ -404,10 +409,8 @@ get_openfile(file_ptrs, mode, fail) } -static struct sed_cmd *next_cmd_entry (struct vector **vectorp); static struct sed_cmd * -next_cmd_entry(vectorp) - struct vector **vectorp; +next_cmd_entry (struct vector **vectorp) { struct sed_cmd *cmd; struct vector *v; @@ -430,79 +433,75 @@ next_cmd_entry(vectorp) return cmd; } -static int snarf_char_class (struct buffer *b, mbstate_t *cur_stat); static int -snarf_char_class(b, cur_stat) - struct buffer *b; - mbstate_t *cur_stat; +snarf_char_class (struct buffer *b, mbstate_t *cur_stat) { int ch; int state = 0; - int delim; - bool pending_mb = 0; - + int delim IF_LINT ( = 0) ; + ch = inchar(); if (ch == '^') ch = add_then_next(b, ch); if (ch == CLOSE_BRACKET) ch = add_then_next(b, ch); - + /* States are: - 0 outside a collation element, character class or collation class - 1 after the bracket - 2 after the opening ./:/= - 3 after the closing ./:/= */ + 0 outside a collation element, character class or collation class + 1 after the bracket + 2 after the opening ./:/= + 3 after the closing ./:/= */ for (;; ch = add_then_next (b, ch)) { - pending_mb = BRLEN (ch, cur_stat) != 1; + const int mb_char = IS_MB_CHAR (ch, cur_stat); switch (ch) - { - case EOF: - case '\n': - return ch; - - case '.': - case ':': - case '=': - if (pending_mb) - continue; - - if (state == 1) - { - delim = ch; - state = 2; - } - else if (state == 2 && ch == delim) - state = 3; - else - break; - - continue; - - case OPEN_BRACKET: - if (pending_mb) - continue; - - if (state == 0) - state = 1; - continue; - - case CLOSE_BRACKET: - if (pending_mb) - continue; - - if (state == 0 || state == 1) - return ch; - else if (state == 3) - state = 0; - - break; - - default: - break; - } + { + case EOF: + case '\n': + return ch; + + case '.': + case ':': + case '=': + if (mb_char) + continue; + + if (state == 1) + { + delim = ch; + state = 2; + } + else if (state == 2 && ch == delim) + state = 3; + else + break; + + continue; + + case OPEN_BRACKET: + if (mb_char) + continue; + + if (state == 0) + state = 1; + continue; + + case CLOSE_BRACKET: + if (mb_char) + continue; + + if (state == 0 || state == 1) + return ch; + else if (state == 3) + state = 0; + + break; + + default: + break; + } /* Getting a character different from .=: whilst in state 1 goes back to state 0, getting a character different from ] @@ -511,52 +510,48 @@ snarf_char_class(b, cur_stat) } } -static struct buffer *match_slash (int slash, int regex); static struct buffer * -match_slash(slash, regex) - int slash; - int regex; +match_slash (int slash, int regex) { struct buffer *b; int ch; - mbstate_t cur_stat; - - memset (&cur_stat, 0, sizeof (mbstate_t)); + mbstate_t cur_stat = { 0, }; /* We allow only 1 byte characters for a slash. */ - if (BRLEN (slash, &cur_stat) == -2) + if (IS_MB_CHAR (slash, &cur_stat)) bad_prog (BAD_DELIM); - memset (&cur_stat, 0, sizeof (mbstate_t)); + memset (&cur_stat, 0, sizeof cur_stat); b = init_buffer(); while ((ch = inchar()) != EOF && ch != '\n') { - bool pending_mb = !MBSINIT (&cur_stat); - if (BRLEN (ch, &cur_stat) == 1 && !pending_mb) - { - if (ch == slash) - return b; - else if (ch == '\\') - { - ch = inchar(); - if (ch == EOF) - break; + const int mb_char = IS_MB_CHAR (ch, &cur_stat); + + if (!mb_char) + { + if (ch == slash) + return b; + else if (ch == '\\') + { + ch = inchar(); + if (ch == EOF) + break; #ifndef REG_PERL - else if (ch == 'n' && regex) - ch = '\n'; + else if (ch == 'n' && regex) + ch = '\n'; #endif - else if (ch != '\n' && (ch != slash || (!regex && ch == '&'))) - add1_buffer(b, '\\'); - } + else if (ch != '\n' && (ch != slash || (!regex && ch == '&'))) + add1_buffer(b, '\\'); + } else if (ch == OPEN_BRACKET && regex) - { - add1_buffer(b, ch); - ch = snarf_char_class(b, &cur_stat); - if (ch != CLOSE_BRACKET) - break; - } - } + { + add1_buffer(b, ch); + ch = snarf_char_class(b, &cur_stat); + if (ch != CLOSE_BRACKET) + break; + } + } add1_buffer(b, ch); } @@ -567,10 +562,8 @@ match_slash(slash, regex) return NULL; } -static int mark_subst_opts (struct subst *cmd); static int -mark_subst_opts(cmd) - struct subst *cmd; +mark_subst_opts (struct subst *cmd) { int flags = 0; int ch; @@ -586,90 +579,91 @@ mark_subst_opts(cmd) { case 'i': /* GNU extension */ case 'I': /* GNU extension */ - if (posixicity == POSIXLY_BASIC) - bad_prog(_(UNKNOWN_S_OPT)); - flags |= REG_ICASE; - break; + if (posixicity == POSIXLY_BASIC) + bad_prog(_(UNKNOWN_S_OPT)); + flags |= REG_ICASE; + break; #ifdef REG_PERL case 's': /* GNU extension */ case 'S': /* GNU extension */ - if (posixicity == POSIXLY_BASIC) - bad_prog(_(UNKNOWN_S_OPT)); - if (extended_regexp_flags & REG_PERL) - flags |= REG_DOTALL; - break; + if (posixicity == POSIXLY_BASIC) + bad_prog(_(UNKNOWN_S_OPT)); + if (extended_regexp_flags & REG_PERL) + flags |= REG_DOTALL; + break; case 'x': /* GNU extension */ case 'X': /* GNU extension */ - if (posixicity == POSIXLY_BASIC) - bad_prog(_(UNKNOWN_S_OPT)); - if (extended_regexp_flags & REG_PERL) - flags |= REG_EXTENDED; - break; + if (posixicity == POSIXLY_BASIC) + bad_prog(_(UNKNOWN_S_OPT)); + if (extended_regexp_flags & REG_PERL) + flags |= REG_EXTENDED; + break; #endif case 'm': /* GNU extension */ case 'M': /* GNU extension */ - if (posixicity == POSIXLY_BASIC) - bad_prog(_(UNKNOWN_S_OPT)); - flags |= REG_NEWLINE; - break; + if (posixicity == POSIXLY_BASIC) + bad_prog(_(UNKNOWN_S_OPT)); + flags |= REG_NEWLINE; + break; case 'e': - cmd->eval = true; - break; + if (posixicity == POSIXLY_BASIC) + bad_prog(_(UNKNOWN_S_OPT)); + cmd->eval = true; + break; case 'p': - if (cmd->print) - bad_prog(_(EXCESS_P_OPT)); - cmd->print |= (1 << cmd->eval); /* 1=before eval, 2=after */ - break; + if (cmd->print) + bad_prog(_(EXCESS_P_OPT)); + cmd->print |= (1 << cmd->eval); /* 1=before eval, 2=after */ + break; case 'g': - if (cmd->global) - bad_prog(_(EXCESS_G_OPT)); - cmd->global = true; - break; + if (cmd->global) + bad_prog(_(EXCESS_G_OPT)); + cmd->global = true; + break; case 'w': - cmd->outf = get_openfile(&file_write, write_mode, true); - return flags; + cmd->outf = get_openfile(&file_write, write_mode, true); + return flags; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': - if (cmd->numb) - bad_prog(_(EXCESS_N_OPT)); - cmd->numb = in_integer(ch); - if (!cmd->numb) - bad_prog(_(ZERO_N_OPT)); - break; + if (cmd->numb) + bad_prog(_(EXCESS_N_OPT)); + cmd->numb = in_integer(ch); + if (!cmd->numb) + bad_prog(_(ZERO_N_OPT)); + break; case CLOSE_BRACE: case '#': - savchar(ch); - /* Fall Through */ + savchar(ch); + /* Fall Through */ case EOF: case '\n': case ';': - return flags; + return flags; case '\r': - if (inchar() == '\n') - return flags; - /* FALLTHROUGH */ + if (inchar() == '\n') + return flags; + /* FALLTHROUGH */ default: - bad_prog(_(UNKNOWN_S_OPT)); - /*NOTREACHED*/ + bad_prog(_(UNKNOWN_S_OPT)); + /*NOTREACHED*/ } } /* read in a label for a `:', `b', or `t' command */ -static char *read_label (void); static char * -read_label() +read_label (void) { struct buffer *b; int ch; @@ -679,7 +673,7 @@ read_label() ch = in_nonblank(); while (ch != EOF && ch != '\n' - && !ISBLANK(ch) && ch != ';' && ch != CLOSE_BRACE && ch != '#') + && !ISBLANK(ch) && ch != ';' && ch != CLOSE_BRACE && ch != '#') ch = add_then_next (b, ch); savchar(ch); @@ -693,14 +687,9 @@ read_label() command so that the jump to/from the label can be backpatched after compilation is complete, or a reference created by a `{' to be backpatched when the corresponding `}' is found. */ -static struct sed_label *setup_label - (struct sed_label *, countT, char *, const struct error_info *); static struct sed_label * -setup_label(list, idx, name, err_info) - struct sed_label *list; - countT idx; - char *name; - const struct error_info *err_info; +setup_label(struct sed_label *list, countT idx, char *name, + const struct error_info *err_info) { struct sed_label *ret = OB_MALLOC(&obs, 1, struct sed_label); ret->v_index = idx; @@ -711,10 +700,8 @@ setup_label(list, idx, name, err_info) return ret; } -static struct sed_label *release_label (struct sed_label *list_head); static struct sed_label * -release_label(list_head) - struct sed_label *list_head; +release_label (struct sed_label *list_head) { struct sed_label *ret; @@ -745,12 +732,8 @@ new_replacement(char *text, size_t length, enum replacement_types type) return r; } -static void setup_replacement (struct subst *, const char *, size_t); static void -setup_replacement(sub, text, length) - struct subst *sub; - const char *text; - size_t length; +setup_replacement (struct subst *sub, const char *text, size_t length) { char *base; char *p; @@ -769,77 +752,77 @@ setup_replacement(sub, text, length) for (p=base; p<text_end; ++p) { if (*p == '\\') - { - /* Preceding the backslash may be some literal text: */ - tail = tail->next = - new_replacement(base, (size_t)(p - base), repl_type); - - repl_type = save_type; - - /* Skip the backslash and look for a numeric back-reference, - or a case-munging escape if not in POSIX mode: */ - ++p; - if (p == text_end) - ++tail->prefix_length; - - else if (posixicity == POSIXLY_BASIC && !ISDIGIT (*p)) - { - p[-1] = *p; - ++tail->prefix_length; - } - - else - switch (*p) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - tail->subst_id = *p - '0'; - if (sub->max_id < tail->subst_id) - sub->max_id = tail->subst_id; - break; - - case 'L': - repl_type = REPL_LOWERCASE; - save_type = REPL_LOWERCASE; - break; - - case 'U': - repl_type = REPL_UPPERCASE; - save_type = REPL_UPPERCASE; - break; - - case 'E': - repl_type = REPL_ASIS; - save_type = REPL_ASIS; - break; - - case 'l': - save_type = repl_type; - repl_type |= REPL_LOWERCASE_FIRST; - break; - - case 'u': - save_type = repl_type; - repl_type |= REPL_UPPERCASE_FIRST; - break; - - default: - p[-1] = *p; - ++tail->prefix_length; - } - - base = p + 1; - } + { + /* Preceding the backslash may be some literal text: */ + tail = tail->next = + new_replacement(base, (size_t)(p - base), repl_type); + + repl_type = save_type; + + /* Skip the backslash and look for a numeric back-reference, + or a case-munging escape if not in POSIX mode: */ + ++p; + if (p == text_end) + ++tail->prefix_length; + + else if (posixicity == POSIXLY_BASIC && !ISDIGIT (*p)) + { + p[-1] = *p; + ++tail->prefix_length; + } + + else + switch (*p) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + tail->subst_id = *p - '0'; + if (sub->max_id < tail->subst_id) + sub->max_id = tail->subst_id; + break; + + case 'L': + repl_type = REPL_LOWERCASE; + save_type = REPL_LOWERCASE; + break; + + case 'U': + repl_type = REPL_UPPERCASE; + save_type = REPL_UPPERCASE; + break; + + case 'E': + repl_type = REPL_ASIS; + save_type = REPL_ASIS; + break; + + case 'l': + save_type = repl_type; + repl_type |= REPL_LOWERCASE_FIRST; + break; + + case 'u': + save_type = repl_type; + repl_type |= REPL_UPPERCASE_FIRST; + break; + + default: + p[-1] = *p; + ++tail->prefix_length; + } + + base = p + 1; + } else if (*p == '&') - { - /* Preceding the ampersand may be some literal text: */ - tail = tail->next = - new_replacement(base, (size_t)(p - base), repl_type); - - repl_type = save_type; - tail->subst_id = 0; - base = p + 1; - } + { + /* Preceding the ampersand may be some literal text: */ + tail = tail->next = + new_replacement(base, (size_t)(p - base), repl_type); + + repl_type = save_type; + tail->subst_id = 0; + base = p + 1; + } } /* There may be some trailing literal text: */ if (base < text_end) @@ -850,11 +833,8 @@ setup_replacement(sub, text, length) sub->replacement = root.next; } -static void read_text (struct text_buf *buf, int leadin_ch); static void -read_text(buf, leadin_ch) - struct text_buf *buf; - int leadin_ch; +read_text (struct text_buf *buf, int leadin_ch) { int ch; @@ -862,7 +842,7 @@ read_text(buf, leadin_ch) if (buf) { if (pending_text) - free_buffer(pending_text); + free_buffer(pending_text); pending_text = init_buffer(); buf->text = NULL; buf->text_length = 0; @@ -880,17 +860,17 @@ read_text(buf, leadin_ch) while (ch != EOF && ch != '\n') { if (ch == '\\') - { - ch = inchar(); - if (ch != EOF) - add1_buffer (pending_text, '\\'); - } + { + ch = inchar(); + if (ch != EOF) + add1_buffer (pending_text, '\\'); + } if (ch == EOF) - { - add1_buffer (pending_text, '\n'); - return; - } + { + add1_buffer (pending_text, '\n'); + return; + } ch = add_then_next (pending_text, ch); } @@ -899,7 +879,7 @@ read_text(buf, leadin_ch) if (!buf) buf = old_text_buf; buf->text_length = normalize_text (get_buffer (pending_text), - size_buffer (pending_text), TEXT_BUFFER); + size_buffer (pending_text), TEXT_BUFFER); buf->text = MEMDUP(get_buffer(pending_text), buf->text_length, char); free_buffer(pending_text); pending_text = NULL; @@ -910,11 +890,8 @@ read_text(buf, leadin_ch) return non-zero and store the resulting address in `*addr'. If the input doesn't look like an address read nothing and return zero. */ -static bool compile_address (struct addr *addr, int ch); static bool -compile_address(addr, ch) - struct addr *addr; - int ch; +compile_address (struct addr *addr, int ch) { addr->addr_type = ADDR_IS_NULL; addr->addr_step = 0; @@ -927,45 +904,45 @@ compile_address(addr, ch) struct buffer *b; addr->addr_type = ADDR_IS_REGEX; if (ch == '\\') - ch = inchar(); + ch = inchar(); if ( !(b = match_slash(ch, true)) ) - bad_prog(_(UNTERM_ADDR_RE)); + bad_prog(_(UNTERM_ADDR_RE)); for(;;) - { - ch = in_nonblank(); - if (posixicity == POSIXLY_BASIC) - goto posix_address_modifier; + { + ch = in_nonblank(); + if (posixicity == POSIXLY_BASIC) + goto posix_address_modifier; switch(ch) - { - case 'I': /* GNU extension */ - flags |= REG_ICASE; - break; + { + case 'I': /* GNU extension */ + flags |= REG_ICASE; + break; #ifdef REG_PERL - case 'S': /* GNU extension */ - if (extended_regexp_flags & REG_PERL) - flags |= REG_DOTALL; - break; - - case 'X': /* GNU extension */ - if (extended_regexp_flags & REG_PERL) - flags |= REG_EXTENDED; - break; + case 'S': /* GNU extension */ + if (extended_regexp_flags & REG_PERL) + flags |= REG_DOTALL; + break; + + case 'X': /* GNU extension */ + if (extended_regexp_flags & REG_PERL) + flags |= REG_EXTENDED; + break; #endif - case 'M': /* GNU extension */ - flags |= REG_NEWLINE; - break; - - default: - posix_address_modifier: - savchar (ch); - addr->addr_regex = compile_regex (b, flags, 0); - free_buffer(b); - return true; - } - } + case 'M': /* GNU extension */ + flags |= REG_NEWLINE; + break; + + default: + posix_address_modifier: + savchar (ch); + addr->addr_regex = compile_regex (b, flags, 0); + free_buffer(b); + return true; + } + } } else if (ISDIGIT(ch)) { @@ -973,28 +950,28 @@ compile_address(addr, ch) addr->addr_type = ADDR_IS_NUM; ch = in_nonblank(); if (ch != '~' || posixicity == POSIXLY_BASIC) - { - savchar(ch); - } + { + savchar(ch); + } else - { - countT step = in_integer(in_nonblank()); - if (step > 0) - { - addr->addr_step = step; - addr->addr_type = ADDR_IS_NUM_MOD; - } - } + { + countT step = in_integer(in_nonblank()); + if (step > 0) + { + addr->addr_step = step; + addr->addr_type = ADDR_IS_NUM_MOD; + } + } } else if ((ch == '+' || ch == '~') && posixicity != POSIXLY_BASIC) { addr->addr_step = in_integer(in_nonblank()); if (addr->addr_step==0) - ; /* default to ADDR_IS_NULL; forces matching to stop on next line */ + ; /* default to ADDR_IS_NULL; forces matching to stop on next line */ else if (ch == '+') - addr->addr_type = ADDR_IS_STEP; + addr->addr_type = ADDR_IS_STEP; else - addr->addr_type = ADDR_IS_STEP_MOD; + addr->addr_type = ADDR_IS_STEP_MOD; } else if (ch == '$') { @@ -1008,10 +985,8 @@ compile_address(addr, ch) /* Read a program (or a subprogram within `{' `}' pairs) in and store the compiled form in `*vector'. Return a pointer to the new vector. */ -static struct vector *compile_program (struct vector *); static struct vector * -compile_program(vector) - struct vector *vector; +compile_program(struct vector *vector) { struct sed_cmd *cur_cmd; struct buffer *b; @@ -1034,176 +1009,185 @@ compile_program(vector) struct addr a; while ((ch=inchar()) == ';' || ISSPACE(ch)) - ; + ; if (ch == EOF) - break; + break; cur_cmd = next_cmd_entry(&vector); if (compile_address(&a, ch)) - { - if (a.addr_type == ADDR_IS_STEP - || a.addr_type == ADDR_IS_STEP_MOD) - bad_prog(_(BAD_STEP)); - - cur_cmd->a1 = MEMDUP(&a, 1, struct addr); - ch = in_nonblank(); - if (ch == ',') - { - if (!compile_address(&a, in_nonblank())) - bad_prog(_(BAD_COMMA)); - - cur_cmd->a2 = MEMDUP(&a, 1, struct addr); - ch = in_nonblank(); - } - - if ((cur_cmd->a1->addr_type == ADDR_IS_NUM - && cur_cmd->a1->addr_number == 0) - && ((!cur_cmd->a2 || cur_cmd->a2->addr_type != ADDR_IS_REGEX) - || posixicity == POSIXLY_BASIC)) - bad_prog(_(INVALID_LINE_0)); - } + { + if (a.addr_type == ADDR_IS_STEP + || a.addr_type == ADDR_IS_STEP_MOD) + bad_prog(_(BAD_STEP)); + + cur_cmd->a1 = MEMDUP(&a, 1, struct addr); + ch = in_nonblank(); + if (ch == ',') + { + if (!compile_address(&a, in_nonblank())) + bad_prog(_(BAD_COMMA)); + + cur_cmd->a2 = MEMDUP(&a, 1, struct addr); + ch = in_nonblank(); + } + + if ((cur_cmd->a1->addr_type == ADDR_IS_NUM + && cur_cmd->a1->addr_number == 0) + && ((!cur_cmd->a2 || cur_cmd->a2->addr_type != ADDR_IS_REGEX) + || posixicity == POSIXLY_BASIC)) + bad_prog(_(INVALID_LINE_0)); + } if (ch == '!') - { - cur_cmd->addr_bang = true; - ch = in_nonblank(); - if (ch == '!') - bad_prog(_(BAD_BANG)); - } + { + cur_cmd->addr_bang = true; + ch = in_nonblank(); + if (ch == '!') + bad_prog(_(BAD_BANG)); + } /* Do not accept extended commands in --posix mode. Also, - a few commands only accept one address in that mode. */ + a few commands only accept one address in that mode. */ if (posixicity == POSIXLY_BASIC) switch (ch) { case 'e': case 'F': case 'v': case 'z': case 'L': case 'Q': case 'T': case 'R': case 'W': bad_command(ch); + /* FALLTHROUGH */ - case 'a': case 'i': case 'l': - case '=': case 'r': - if (cur_cmd->a2) - bad_prog(_(ONE_ADDR)); - } + case 'a': case 'i': case 'l': + case '=': case 'r': + if (cur_cmd->a2) + bad_prog(_(ONE_ADDR)); + } cur_cmd->cmd = ch; switch (ch) - { - case '#': - if (cur_cmd->a1) - bad_prog(_(NO_SHARP_ADDR)); - ch = inchar(); - if (ch=='n' && first_script && cur_input.line < 2) - if ( (prog.base && prog.cur==2+prog.base) - || (prog.file && !prog.base && 2==ftell(prog.file))) - no_default_output = true; - while (ch != EOF && ch != '\n') - ch = inchar(); - continue; /* restart the for (;;) loop */ - - case 'v': - /* This is an extension. Programs needing GNU sed might start - * with a `v' command so that other seds will stop. - * We compare the version and ignore POSIXLY_CORRECT. - */ - { - char *version = read_label (); - char *compared_version; - compared_version = (*version == '\0') ? "4.0" : version; - if (strverscmp (compared_version, SED_FEATURE_VERSION) > 0) - bad_prog(_(ANCIENT_VERSION)); - - free (version); - posixicity = POSIXLY_EXTENDED; - } - continue; - - case '{': - blocks = setup_label(blocks, vector->v_length, NULL, &cur_input); - cur_cmd->addr_bang = !cur_cmd->addr_bang; - break; - - case '}': - if (!blocks) - bad_prog(_(EXCESS_CLOSE_BRACE)); - if (cur_cmd->a1) - bad_prog(_(NO_CLOSE_BRACE_ADDR)); - ch = in_nonblank(); - if (ch == CLOSE_BRACE || ch == '#') - savchar(ch); - else if (ch != EOF && ch != '\n' && ch != ';') - bad_prog(_(EXCESS_JUNK)); - - vector->v[blocks->v_index].x.jump_index = vector->v_length; - blocks = release_label(blocks); /* done with this entry */ - break; - - case 'e': - ch = in_nonblank(); - if (ch == EOF || ch == '\n') - { - cur_cmd->x.cmd_txt.text_length = 0; - break; - } - else - goto read_text_to_slash; - - case 'a': - case 'i': - case 'c': - ch = in_nonblank(); - - read_text_to_slash: - if (ch == EOF) - bad_prog(_(EXPECTED_SLASH)); - - if (ch == '\\') - ch = inchar(); - else - { - if (posixicity == POSIXLY_BASIC) - bad_prog(_(EXPECTED_SLASH)); - savchar(ch); - ch = '\n'; - } - - read_text(&cur_cmd->x.cmd_txt, ch); - break; - - case ':': - if (cur_cmd->a1) - bad_prog(_(NO_COLON_ADDR)); - labels = setup_label(labels, vector->v_length, read_label(), NULL); - break; - - case 'T': - case 'b': - case 't': - jumps = setup_label(jumps, vector->v_length, read_label(), NULL); - break; - - case 'Q': - case 'q': - if (cur_cmd->a2) - bad_prog(_(ONE_ADDR)); - /* Fall through */ - - case 'L': - case 'l': - ch = in_nonblank(); - if (ISDIGIT(ch) && posixicity != POSIXLY_BASIC) - { - cur_cmd->x.int_arg = in_integer(ch); - ch = in_nonblank(); - } - else - cur_cmd->x.int_arg = -1; - - if (ch == CLOSE_BRACE || ch == '#') - savchar(ch); - else if (ch != EOF && ch != '\n' && ch != ';') - bad_prog(_(EXCESS_JUNK)); - - break; + { + case '#': + if (cur_cmd->a1) + bad_prog(_(NO_SHARP_ADDR)); + ch = inchar(); + if (ch=='n' && first_script && cur_input.line < 2) + if ( (prog.base && prog.cur==2+prog.base) + || (prog.file && !prog.base && 2==ftell(prog.file))) + no_default_output = true; + while (ch != EOF && ch != '\n') + ch = inchar(); + continue; /* restart the for (;;) loop */ + + case 'v': + /* This is an extension. Programs needing GNU sed might start + * with a `v' command so that other seds will stop. + * We compare the version and ignore POSIXLY_CORRECT. + */ + { + char *version = read_label (); + char const *compared_version; + compared_version = (*version == '\0') ? "4.0" : version; + if (strverscmp (compared_version, PACKAGE_VERSION) > 0) + bad_prog(_(ANCIENT_VERSION)); + + free (version); + posixicity = POSIXLY_EXTENDED; + } + continue; + + case '{': + blocks = setup_label(blocks, vector->v_length, NULL, &cur_input); + cur_cmd->addr_bang = !cur_cmd->addr_bang; + break; + + case '}': + if (!blocks) + bad_prog(_(EXCESS_CLOSE_BRACE)); + if (cur_cmd->a1) + bad_prog(_(NO_CLOSE_BRACE_ADDR)); + ch = in_nonblank(); + if (ch == CLOSE_BRACE || ch == '#') + savchar(ch); + else if (ch != EOF && ch != '\n' && ch != ';') + bad_prog(_(EXCESS_JUNK)); + + vector->v[blocks->v_index].x.jump_index = vector->v_length; + blocks = release_label(blocks); /* done with this entry */ + break; + + case 'e': + if (sandbox) + bad_prog(_(DISALLOWED_CMD)); + + ch = in_nonblank(); + if (ch == EOF || ch == '\n') + { + cur_cmd->x.cmd_txt.text_length = 0; + break; + } + else + goto read_text_to_slash; + + case 'a': + case 'i': + case 'c': + ch = in_nonblank(); + + read_text_to_slash: + if (ch == EOF) + bad_prog(_(EXPECTED_SLASH)); + + if (ch == '\\') + ch = inchar(); + else + { + if (posixicity == POSIXLY_BASIC) + bad_prog(_(EXPECTED_SLASH)); + savchar(ch); + ch = '\n'; + } + + read_text(&cur_cmd->x.cmd_txt, ch); + break; + + case ':': + if (cur_cmd->a1) + bad_prog(_(NO_COLON_ADDR)); + { + char *label = read_label (); + if (!*label) + bad_prog(_(COLON_LACKS_LABEL)); + labels = setup_label(labels, vector->v_length, label, NULL); + } + break; + + case 'T': + case 'b': + case 't': + jumps = setup_label(jumps, vector->v_length, read_label(), NULL); + break; + + case 'Q': + case 'q': + if (cur_cmd->a2) + bad_prog(_(ONE_ADDR)); + /* Fall through */ + + case 'L': + case 'l': + ch = in_nonblank(); + if (ISDIGIT(ch) && posixicity != POSIXLY_BASIC) + { + cur_cmd->x.int_arg = in_integer(ch); + ch = in_nonblank(); + } + else + cur_cmd->x.int_arg = -1; + + if (ch == CLOSE_BRACE || ch == '#') + savchar(ch); + else if (ch != EOF && ch != '\n' && ch != ';') + bad_prog(_(EXCESS_JUNK)); + + break; case '=': case 'd': @@ -1212,92 +1196,94 @@ compile_program(vector) case 'g': case 'G': case 'h': - case 'H': - case 'n': - case 'N': - case 'p': - case 'P': - case 'z': - case 'x': - ch = in_nonblank(); - if (ch == CLOSE_BRACE || ch == '#') - savchar(ch); - else if (ch != EOF && ch != '\n' && ch != ';') - bad_prog(_(EXCESS_JUNK)); - break; - - case 'r': - b = read_filename(); - cur_cmd->x.fname = ck_strdup(get_buffer(b)); - free_buffer(b); - break; + case 'H': + case 'n': + case 'N': + case 'p': + case 'P': + case 'z': + case 'x': + ch = in_nonblank(); + if (ch == CLOSE_BRACE || ch == '#') + savchar(ch); + else if (ch != EOF && ch != '\n' && ch != ';') + bad_prog(_(EXCESS_JUNK)); + break; + + case 'r': + b = read_filename(); + cur_cmd->x.fname = ck_strdup(get_buffer(b)); + free_buffer(b); + break; case 'R': - cur_cmd->x.fp = get_openfile(&file_read, read_mode, false)->fp; - break; + cur_cmd->x.fp = get_openfile(&file_read, read_mode, false)->fp; + break; case 'W': - case 'w': - cur_cmd->x.outf = get_openfile(&file_write, write_mode, true); - break; - - case 's': - { - struct buffer *b2; - int flags; - int slash; - - slash = inchar(); - if ( !(b = match_slash(slash, true)) ) - bad_prog(_(UNTERM_S_CMD)); - if ( !(b2 = match_slash(slash, false)) ) - bad_prog(_(UNTERM_S_CMD)); - - cur_cmd->x.cmd_subst = OB_MALLOC(&obs, 1, struct subst); - setup_replacement(cur_cmd->x.cmd_subst, - get_buffer(b2), size_buffer(b2)); - free_buffer(b2); - - flags = mark_subst_opts(cur_cmd->x.cmd_subst); - cur_cmd->x.cmd_subst->regx = - compile_regex(b, flags, cur_cmd->x.cmd_subst->max_id + 1); - free_buffer(b); - } - break; - - case 'y': - { - size_t len, dest_len; - int slash; - struct buffer *b2; + case 'w': + cur_cmd->x.outf = get_openfile(&file_write, write_mode, true); + break; + + case 's': + { + struct buffer *b2; + int flags; + int slash; + + slash = inchar(); + if ( !(b = match_slash(slash, true)) ) + bad_prog(_(UNTERM_S_CMD)); + if ( !(b2 = match_slash(slash, false)) ) + bad_prog(_(UNTERM_S_CMD)); + + cur_cmd->x.cmd_subst = OB_MALLOC(&obs, 1, struct subst); + setup_replacement(cur_cmd->x.cmd_subst, + get_buffer(b2), size_buffer(b2)); + free_buffer(b2); + + flags = mark_subst_opts(cur_cmd->x.cmd_subst); + cur_cmd->x.cmd_subst->regx = + compile_regex(b, flags, cur_cmd->x.cmd_subst->max_id + 1); + free_buffer(b); + + if (cur_cmd->x.cmd_subst->eval && sandbox) + bad_prog(_(DISALLOWED_CMD)); + } + break; + + case 'y': + { + size_t len, dest_len; + int slash; + struct buffer *b2; char *src_buf, *dest_buf; - - slash = inchar(); - if ( !(b = match_slash(slash, false)) ) - bad_prog(_(UNTERM_Y_CMD)); + + slash = inchar(); + if ( !(b = match_slash(slash, false)) ) + bad_prog(_(UNTERM_Y_CMD)); src_buf = get_buffer(b); - len = normalize_text(src_buf, size_buffer (b), TEXT_BUFFER); + len = normalize_text(src_buf, size_buffer (b), TEXT_BUFFER); if ( !(b2 = match_slash(slash, false)) ) - bad_prog(_(UNTERM_Y_CMD)); + bad_prog(_(UNTERM_Y_CMD)); dest_buf = get_buffer(b2); - dest_len = normalize_text(dest_buf, size_buffer (b2), TEXT_BUFFER); + dest_len = normalize_text(dest_buf, size_buffer (b2), TEXT_BUFFER); if (mb_cur_max > 1) - { - int i, j, idx, src_char_num; + { + size_t i, j, idx, src_char_num; size_t *src_lens = MALLOC(len, size_t); char **trans_pairs; size_t mbclen; - mbstate_t cur_stat; + mbstate_t cur_stat = { 0, }; /* Enumerate how many character the source buffer has. */ - memset(&cur_stat, 0, sizeof(mbstate_t)); for (i = 0, j = 0; i < len;) { mbclen = MBRLEN (src_buf + i, len - i, &cur_stat); /* An invalid sequence, or a truncated multibyte character. - We treat it as a singlebyte character. */ + We treat it as a single-byte character. */ if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) mbclen = 1; @@ -1306,7 +1292,7 @@ compile_program(vector) } src_char_num = j; - memset(&cur_stat, 0, sizeof(mbstate_t)); + memset(&cur_stat, 0, sizeof cur_stat); idx = 0; /* trans_pairs = {src(0), dest(0), src(1), dest(1), ..., NULL} @@ -1322,21 +1308,21 @@ compile_program(vector) /* Set the i-th source character. */ trans_pairs[2 * i] = MALLOC(src_lens[i] + 1, char); - strncpy(trans_pairs[2 * i], src_buf, src_lens[i]); + memcpy(trans_pairs[2 * i], src_buf, src_lens[i]); trans_pairs[2 * i][src_lens[i]] = '\0'; src_buf += src_lens[i]; /* Forward to next character. */ /* Fetch the i-th destination character. */ mbclen = MBRLEN (dest_buf + idx, dest_len - idx, &cur_stat); /* An invalid sequence, or a truncated multibyte character. - We treat it as a singlebyte character. */ + We treat it as a single-byte character. */ if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) mbclen = 1; /* Set the i-th destination character. */ trans_pairs[2 * i + 1] = MALLOC(mbclen + 1, char); - strncpy(trans_pairs[2 * i + 1], dest_buf + idx, mbclen); + memcpy(trans_pairs[2 * i + 1], dest_buf + idx, mbclen); trans_pairs[2 * i + 1][mbclen] = '\0'; idx += mbclen; /* Forward to next character. */ } @@ -1346,38 +1332,38 @@ compile_program(vector) } else { - unsigned char *translate = - OB_MALLOC(&obs, YMAP_LENGTH, unsigned char); + unsigned char *translate = + OB_MALLOC(&obs, YMAP_LENGTH, unsigned char); unsigned char *ustring = (unsigned char *)src_buf; - if (len != dest_len) + if (len != dest_len) bad_prog(_(Y_CMD_LEN)); - for (len = 0; len < YMAP_LENGTH; len++) - translate[len] = len; + for (len = 0; len < YMAP_LENGTH; len++) + translate[len] = len; while (dest_len--) translate[*ustring++] = (unsigned char)*dest_buf++; - cur_cmd->x.translate = translate; - } + cur_cmd->x.translate = translate; + } if ((ch = in_nonblank()) != EOF && ch != '\n' && ch != ';') bad_prog(_(EXCESS_JUNK)); free_buffer(b); free_buffer(b2); - } - break; + } + break; - case EOF: - bad_prog(_(NO_COMMAND)); - /*NOTREACHED*/ + case EOF: + bad_prog(_(NO_COMMAND)); + /*NOTREACHED*/ - default: - bad_command (ch); - /*NOTREACHED*/ - } + default: + bad_command (ch); + /*NOTREACHED*/ + } /* this is buried down here so that "continue" statements will miss it */ ++vector->v_length; @@ -1390,10 +1376,7 @@ compile_program(vector) /* deal with \X escapes */ size_t -normalize_text(buf, len, buftype) - char *buf; - size_t len; - enum text_types buftype; +normalize_text(char *buf, size_t len, enum text_types buftype) { const char *bufend = buf + len; char *p = buf; @@ -1410,84 +1393,83 @@ normalize_text(buf, len, buftype) int bracket_state = 0; int mbclen; - mbstate_t cur_stat; - memset(&cur_stat, 0, sizeof(mbstate_t)); + mbstate_t cur_stat = { 0, }; while (p < bufend) { mbclen = MBRLEN (p, bufend - p, &cur_stat); if (mbclen != 1) - { + { /* An invalid sequence, or a truncated multibyte character. - We treat it as a singlebyte character. */ + We treat it as a single-byte character. */ if (mbclen == (size_t) -1 || mbclen == (size_t) -2 || mbclen == 0) mbclen = 1; memmove (q, p, mbclen); q += mbclen; p += mbclen; - continue; - } + continue; + } if (*p == '\\' && p+1 < bufend && bracket_state == 0) - switch (*++p) - { + switch (*++p) + { #if defined __STDC__ && __STDC__-0 - case 'a': *q++ = '\a'; p++; continue; + case 'a': *q++ = '\a'; p++; continue; #else /* Not STDC; we'll just assume ASCII */ - case 'a': *q++ = '\007'; p++; continue; + case 'a': *q++ = '\007'; p++; continue; #endif - /* case 'b': *q++ = '\b'; p++; continue; --- conflicts with \b RE */ - case 'f': *q++ = '\f'; p++; continue; - case '\n': /*fall through */ - case 'n': *q++ = '\n'; p++; continue; - case 'r': *q++ = '\r'; p++; continue; - case 't': *q++ = '\t'; p++; continue; - case 'v': *q++ = '\v'; p++; continue; - - case 'd': /* decimal byte */ + /* case 'b': *q++ = '\b'; p++; continue; --- conflicts with \b RE */ + case 'f': *q++ = '\f'; p++; continue; + case '\n': /*fall through */ + case 'n': *q++ = '\n'; p++; continue; + case 'r': *q++ = '\r'; p++; continue; + case 't': *q++ = '\t'; p++; continue; + case 'v': *q++ = '\v'; p++; continue; + + case 'd': /* decimal byte */ base = 10; goto convert; - case 'x': /* hexadecimal byte */ + case 'x': /* hexadecimal byte */ base = 16; goto convert; #ifdef REG_PERL - case '0': case '1': case '2': case '3': - case '4': case '5': case '6': case '7': - if ((extended_regexp_flags & REG_PERL) - && p+1 < bufend - && p[1] >= '0' && p[1] <= '9') - { + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + if ((extended_regexp_flags & REG_PERL) + && p+1 < bufend + && p[1] >= '0' && p[1] <= '9') + { base = 8; goto convert; - } - else - { - /* we just pass the \ up one level for interpretation */ - if (buftype != TEXT_BUFFER) - *q++ = '\\'; - } - - continue; - - case 'o': /* octal byte */ - if (!(extended_regexp_flags & REG_PERL)) - { + } + else + { + /* we just pass the \ up one level for interpretation */ + if (buftype != TEXT_BUFFER) + *q++ = '\\'; + } + + continue; + + case 'o': /* octal byte */ + if (!(extended_regexp_flags & REG_PERL)) + { base = 8; goto convert; - } - else - { - /* we just pass the \ up one level for interpretation */ - if (buftype != TEXT_BUFFER) - *q++ = '\\'; - } - - continue; + } + else + { + /* we just pass the \ up one level for interpretation */ + if (buftype != TEXT_BUFFER) + *q++ = '\\'; + } + + continue; #else - case 'o': /* octal byte */ + case 'o': /* octal byte */ base = 8; #endif convert: @@ -1499,27 +1481,33 @@ convert: *q++ = ch; continue; - case 'c': - if (++p < bufend) - { - *q++ = toupper((unsigned char) *p) ^ 0x40; - p++; - continue; - } - else - { - /* we just pass the \ up one level for interpretation */ - if (buftype != TEXT_BUFFER) - *q++ = '\\'; - continue; - } - - default: - /* we just pass the \ up one level for interpretation */ - if (buftype != TEXT_BUFFER) - *q++ = '\\'; - break; - } + case 'c': + if (++p < bufend) + { + *q++ = toupper((unsigned char) *p) ^ 0x40; + if (*p == '\\') + { + p++; + if (*p != '\\') + bad_prog(RECURSIVE_ESCAPE_C); + } + p++; + continue; + } + else + { + /* we just pass the \ up one level for interpretation */ + if (buftype != TEXT_BUFFER) + *q++ = '\\'; + continue; + } + + default: + /* we just pass the \ up one level for interpretation */ + if (buftype != TEXT_BUFFER) + *q++ = '\\'; + break; + } else if (buftype == TEXT_REGEX && posixicity != POSIXLY_EXTENDED) switch (*p) { @@ -1527,17 +1515,17 @@ convert: if (!bracket_state) bracket_state = -1; break; - - case ':': - case '.': - case '=': + + case ':': + case '.': + case '=': if (bracket_state == -1 && p[-1] == '[') bracket_state = *p; break; case ']': if (bracket_state == 0) - ; + ; else if (bracket_state == -1) bracket_state = 0; else if (p[-2] != bracket_state && p[-1] == bracket_state) @@ -1554,10 +1542,7 @@ convert: /* `str' is a string (from the command line) that contains a sed command. Compile the command, and add it to the end of `cur_program'. */ struct vector * -compile_string(cur_program, str, len) - struct vector *cur_program; - char *str; - size_t len; +compile_string(struct vector *cur_program, char *str, size_t len) { static countT string_expr_count = 0; struct vector *ret; @@ -1584,9 +1569,7 @@ compile_string(cur_program, str, len) Read them in and add them to the end of `cur_program'. */ struct vector * -compile_file(cur_program, cmdfile) - struct vector *cur_program; - const char *cmdfile; +compile_file(struct vector *cur_program, const char *cmdfile) { struct vector *ret; @@ -1617,8 +1600,7 @@ compile_file(cur_program, cmdfile) In particular: this backpatches the jump targets. Any cleanup which can be done after these checks is done here also. */ void -check_final_program(program) - struct vector *program; +check_final_program(struct vector *program) { struct sed_label *go; struct sed_label *lbl; @@ -1637,7 +1619,7 @@ check_final_program(program) old_text_buf->text_length = size_buffer(pending_text); if (old_text_buf->text_length) old_text_buf->text = MEMDUP(get_buffer(pending_text), - old_text_buf->text_length, char); + old_text_buf->text_length, char); free_buffer(pending_text); pending_text = NULL; } @@ -1645,18 +1627,18 @@ check_final_program(program) for (go = jumps; go; go = release_label(go)) { for (lbl = labels; lbl; lbl = lbl->next) - if (strcmp(lbl->name, go->name) == 0) - break; + if (strcmp(lbl->name, go->name) == 0) + break; if (lbl) - { - program->v[go->v_index].x.jump_index = lbl->v_index; - } + { + program->v[go->v_index].x.jump_index = lbl->v_index; + } else - { - if (*go->name) - panic(_("can't find label for jump to `%s'"), go->name); - program->v[go->v_index].x.jump_index = program->v_length; - } + { + if (*go->name) + panic(_("can't find label for jump to `%s'"), go->name); + program->v[go->v_index].x.jump_index = program->v_length; + } } jumps = NULL; @@ -1670,23 +1652,23 @@ check_final_program(program) for (p=file_read; p; p=p->link) if (p->name) - { - free(p->name); - p->name = NULL; - } + { + free(p->name); + p->name = NULL; + } for (p=file_write; p; p=p->link) if (p->name) - { - free(p->name); - p->name = NULL; - } + { + free(p->name); + p->name = NULL; + } } } /* Rewind all resources which were allocated in this module. */ void -rewind_read_files() +rewind_read_files(void) { struct output *p; @@ -1697,8 +1679,7 @@ rewind_read_files() /* Release all resources which were allocated in this module. */ void -finish_program(program) - struct vector *program; +finish_program(void) { /* close all files... */ { @@ -1706,23 +1687,23 @@ finish_program(program) for (p=file_read; p; p=q) { - if (p->fp) - ck_fclose(p->fp); - q = p->link; + if (p->fp) + ck_fclose(p->fp); + q = p->link; #if 0 - /* We use obstacks. */ - free(p); + /* We use obstacks. */ + free(p); #endif } for (p=file_write; p; p=q) { - if (p->fp) - ck_fclose(p->fp); - q = p->link; + if (p->fp) + ck_fclose(p->fp); + q = p->link; #if 0 - /* We use obstacks. */ - free(p); + /* We use obstacks. */ + free(p); #endif } file_read = file_write = NULL; |