FreeBSD Bugzilla – Attachment 150663 Details for
Bug 195929
usr.bin/sed -- constify, remove line-length limits
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
Properly process multi-line -e commands too
sed.patch (text/plain), 20.54 KB, created by
Mikhail T.
on 2014-12-17 02:04:17 UTC
(
hide
)
Description:
Properly process multi-line -e commands too
Filename:
MIME Type:
Creator:
Mikhail T.
Created:
2014-12-17 02:04:17 UTC
Size:
20.54 KB
patch
obsolete
>Index: Makefile >=================================================================== >--- Makefile (revision 275828) >+++ Makefile (working copy) >@@ -6,7 +6,7 @@ > PROG= sed > SRCS= compile.c main.c misc.c process.c > >-WARNS?= 2 >+WARNS?= 5 > > .if ${MK_TESTS} != "no" > SUBDIR+= tests >Index: compile.c >=================================================================== >--- compile.c (revision 275828) >+++ compile.c (working copy) >@@ -64,21 +64,21 @@ > int lh_ref; > } *labels[LHSZ]; > >-static char *compile_addr(char *, struct s_addr *); >-static char *compile_ccl(char **, char *); >-static char *compile_delimited(char *, char *, int); >-static char *compile_flags(char *, struct s_subst *); >-static regex_t *compile_re(char *, int); >-static char *compile_subst(char *, struct s_subst *); >-static char *compile_text(void); >-static char *compile_tr(char *, struct s_tr **); >+static const char *compile_addr(const char *, struct s_addr *); >+static char *compile_ccl(const char **, char *); >+static const char *compile_delimited(const char *, char *, int); >+static const char *compile_flags(const char *, struct s_subst *); >+static regex_t *compile_re(const char *, int); >+static const char *compile_subst(const char *, struct s_subst *); >+static char *compile_text(size_t *); >+static const char *compile_tr(const char *, struct s_tr **); > static struct s_command > **compile_stream(struct s_command **); >-static char *duptoeol(char *, const char *); >+static char *duptoeol(const char *, const char *, size_t *); > static void enterlabel(struct s_command *); > static struct s_command >- *findlabel(char *); >-static void fixuplabel(struct s_command *, struct s_command *); >+ *findlabel(const char *); >+static void fixuplabel(struct s_command *, const struct s_command *); > static void uselabel(void); > > /* >@@ -144,40 +144,44 @@ > err(1, "malloc"); > } > >-#define EATSPACE() do { \ >- if (p) \ >- while (*p && isspace((unsigned char)*p)) \ >- p++; \ >+#define EATSPACE() do { \ >+ while (*p && isspace((unsigned char)*p)) \ >+ p++; \ > } while (0) > >+#define EATSPACEN() do { \ >+ while (*p && *p != '\n' && isspace((unsigned char)*p)) \ >+ p++; \ >+ } while (0) >+ > static struct s_command ** > compile_stream(struct s_command **link) > { >- char *p; >- static char lbuf[_POSIX2_LINE_MAX + 1]; /* To save stack */ >+ const char *p; > struct s_command *cmd, *cmd2, *stack; > struct s_format *fp; > char re[_POSIX2_LINE_MAX + 1]; > int naddr; /* Number of addresses */ >+ int stackdepth = 0; > >- stack = 0; >+ stack = NULL; > for (;;) { >- if ((p = cu_fgets(lbuf, sizeof(lbuf), NULL)) == NULL) { >- if (stack != 0) >+ if ((p = cu_fgets(NULL)) == NULL) { >+ if (stack != NULL) > errx(1, "%lu: %s: unexpected EOF (pending }'s)", > linenum, fname); > return (link); > } > >-semicolon: EATSPACE(); >- if (p) { >- if (*p == '#' || *p == '\0') >- continue; >- else if (*p == ';') { >- p++; >- goto semicolon; >- } >+semicolon: EATSPACEN(); >+ switch (*p) { >+ case '#': case '\0': case '\n': >+ continue; /* to next command-unit */ >+ case ';': >+ p++; >+ goto semicolon; > } >+ > if ((*link = cmd = malloc(sizeof(struct s_command))) == NULL) > err(1, "malloc"); > link = &cmd->next; >@@ -208,7 +212,7 @@ > cmd->a1 = cmd->a2 = 0; > > nonsel: /* Now parse the command */ >- if (!*p) >+ if (*p == '\0' || *p == '\n') > errx(1, "%lu: %s: command expected", linenum, fname); > cmd->code = *p; > for (fp = cmd_fmts; fp->code; fp++) >@@ -215,7 +219,7 @@ > if (fp->code == *p) > break; > if (!fp->code) >- errx(1, "%lu: %s: invalid command code %c", linenum, fname, *p); >+ errx(1, "%lu: %s: invalid command code %c (%s)", linenum, fname, *p, p); > if (naddr > fp->naddr) > errx(1, > "%lu: %s: command %c expects up to %d address(es), found %d", >@@ -228,11 +232,11 @@ > goto nonsel; > case GROUP: /* { */ > p++; >- EATSPACE(); >+ EATSPACEN(); > cmd->next = stack; > stack = cmd; > link = &cmd->u.c; >- if (*p) >+ if (*p != '\0' && *p != '\n') > goto semicolon; > break; > case ENDGROUP: >@@ -241,7 +245,7 @@ > * group is really just a noop. > */ > cmd->nonsel = 1; >- if (stack == 0) >+ if (stack == NULL) > errx(1, "%lu: %s: unexpected }", linenum, fname); > cmd2 = stack; > stack = cmd2->next; >@@ -249,13 +253,13 @@ > /*FALLTHROUGH*/ > case EMPTY: /* d D g G h H l n N p P q x = \0 */ > p++; >- EATSPACE(); >+ EATSPACEN(); > if (*p == ';') { > p++; > link = &cmd->next; > goto semicolon; > } >- if (*p) >+ if (*p != '\0' && *p != '\n') > errx(1, "%lu: %s: extra characters at the end of %c command", > linenum, fname, cmd->code); > break; >@@ -266,12 +270,12 @@ > errx(1, > "%lu: %s: command %c expects \\ followed by text", linenum, fname, cmd->code); > p++; >- EATSPACE(); >- if (*p) >+ EATSPACEN(); >+ if (*p != '\n') > errx(1, >- "%lu: %s: extra characters after \\ at the end of %c command", >- linenum, fname, cmd->code); >- cmd->t = compile_text(); >+ "%lu: %s: extra characters (%c) after \\ at the end of %c command", >+ linenum, fname, *p, cmd->code); >+ cmd->t = compile_text(&cmd->tlen); > break; > case COMMENT: /* \0 # */ > break; >@@ -280,10 +284,10 @@ > EATSPACE(); > if (*p == '\0') > errx(1, "%lu: %s: filename expected", linenum, fname); >- cmd->t = duptoeol(p, "w command"); >+ cmd->t = duptoeol(p, "w command", &cmd->tlen); > if (aflag) > cmd->u.fd = -1; >- else if ((cmd->u.fd = open(p, >+ else if ((cmd->u.fd = open(cmd->t, > O_WRONLY|O_APPEND|O_CREAT|O_TRUNC, > DEFFILEMODE)) == -1) > err(1, "%s", p); >@@ -294,27 +298,27 @@ > if (*p == '\0') > errx(1, "%lu: %s: filename expected", linenum, fname); > else >- cmd->t = duptoeol(p, "read command"); >+ cmd->t = duptoeol(p, "read command", &cmd->tlen); > break; > case BRANCH: /* b t */ > p++; >- EATSPACE(); >- if (*p == '\0') >+ EATSPACEN(); >+ if (*p == '\0' || *p == '\n') > cmd->t = NULL; > else >- cmd->t = duptoeol(p, "branch"); >+ cmd->t = duptoeol(p, "branch", &cmd->tlen); > break; > case LABEL: /* : */ > p++; > EATSPACE(); >- cmd->t = duptoeol(p, "label"); >- if (strlen(p) == 0) >+ cmd->t = duptoeol(p, "label", &cmd->tlen); >+ if (cmd->t[0] == '\0') > errx(1, "%lu: %s: empty label", linenum, fname); > enterlabel(cmd); > break; > case SUBST: /* s */ > p++; >- if (*p == '\0' || *p == '\\') >+ if (*p == '\0' || *p == '\\' || *p == '\n') > errx(1, > "%lu: %s: substitute pattern can not be delimited by newline or backslash", > linenum, fname); >@@ -339,7 +343,6 @@ > cmd->u.s->re = NULL; > else > cmd->u.s->re = compile_re(re, cmd->u.s->icase); >- EATSPACE(); > if (*p == ';') { > p++; > link = &cmd->next; >@@ -372,8 +375,8 @@ > * in the case of a non-terminated string. The character array d is filled > * with the processed string. > */ >-static char * >-compile_delimited(char *p, char *d, int is_tr) >+static const char * >+compile_delimited(const char *p, char *d, int is_tr) > { > char c; > >@@ -416,10 +419,10 @@ > > /* compile_ccl: expand a POSIX character class */ > static char * >-compile_ccl(char **sp, char *t) >+compile_ccl(const char **sp, char *t) > { > int c, d; >- char *s = *sp; >+ const char *s = *sp; > > *t++ = *s++; > if (*s == '^') >@@ -442,7 +445,7 @@ > * Cflags are passed to regcomp. > */ > static regex_t * >-compile_re(char *re, int case_insensitive) >+compile_re(const char *re, int case_insensitive) > { > regex_t *rep; > int eval, flags; >@@ -466,14 +469,13 @@ > * point to a saved copy of it. Nsub is the number of parenthesized regular > * expressions. > */ >-static char * >-compile_subst(char *p, struct s_subst *s) >+static const char * >+compile_subst(const char *p, struct s_subst *s) > { >- static char lbuf[_POSIX2_LINE_MAX + 1]; > int asize, size; > u_char ref; > char c, *text, *op, *sp; >- int more = 1, sawesc = 0; >+ int more = 0, sawesc = 0; > > c = *p++; /* Terminator character */ > if (c == '\0') >@@ -487,7 +489,7 @@ > size = 0; > do { > op = sp = text + size; >- for (; *p; p++) { >+ for (; *p != '\0' && *p != '\n'; p++) { > if (*p == '\\' || sawesc) { > /* > * If this is a continuation from the last >@@ -509,7 +511,10 @@ > */ > sawesc = 1; > p--; >- continue; >+ break; >+ } else if (*p == '\n') { >+ *sp++ = '\n'; >+ break; > } else if (strchr("123456789", *p) != NULL) { > *sp++ = '\\'; > ref = *p - '0'; >@@ -522,9 +527,12 @@ > } else if (*p == '&' || *p == '\\') > *sp++ = '\\'; > } else if (*p == c) { >- if (*++p == '\0' && more) { >- if (cu_fgets(lbuf, sizeof(lbuf), &more)) >- p = lbuf; >+ if ((*++p == '\0' || *p == '\n') && more) { >+ const char *nextp; >+ >+ nextp = cu_fgets(&more); >+ if (nextp != NULL) >+ p = nextp; > } > *sp++ = '\0'; > size += sp - op; >@@ -532,6 +540,7 @@ > err(1, "realloc"); > return (p); > } else if (*p == '\n') { >+ break; > errx(1, > "%lu: %s: unescaped newline inside substitute pattern", linenum, fname); > /* NOTREACHED */ >@@ -544,7 +553,7 @@ > if ((text = realloc(text, asize)) == NULL) > err(1, "realloc"); > } >- } while (cu_fgets(p = lbuf, sizeof(lbuf), &more)); >+ } while ((p = cu_fgets(&more))); > errx(1, "%lu: %s: unterminated substitute in regular expression", > linenum, fname); > /* NOTREACHED */ >@@ -553,8 +562,8 @@ > /* > * Compile the flags of the s command > */ >-static char * >-compile_flags(char *p, struct s_subst *s) >+static const char * >+compile_flags(const char *p, struct s_subst *s) > { > int gn; /* True if we have seen g or n */ > unsigned long nval; >@@ -566,7 +575,7 @@ > s->wfd = -1; > s->icase = 0; > for (gn = 0;;) { >- EATSPACE(); /* EXTENSION */ >+ EATSPACEN(); /* EXTENSION */ > switch (*p) { > case 'g': > if (gn) >@@ -594,12 +603,12 @@ > "%lu: %s: more than one number or 'g' in substitute flags", linenum, fname); > gn = 1; > errno = 0; >- nval = strtol(p, &p, 10); >+ nval = strtol(p, &q, 10); > if (errno == ERANGE || nval > INT_MAX) > errx(1, > "%lu: %s: overflow in the 'N' substitute flag", linenum, fname); > s->n = nval; >- p--; >+ p = q - 1; > break; > case 'w': > p++; >@@ -637,8 +646,8 @@ > /* > * Compile a translation set of strings into a lookup table. > */ >-static char * >-compile_tr(char *p, struct s_tr **py) >+static const char * >+compile_tr(const char *p, struct s_tr **py) > { > struct s_tr *y; > int i; >@@ -730,24 +739,25 @@ > * Compile the text following an a or i command. > */ > static char * >-compile_text(void) >+compile_text(size_t *ptlen) > { > int asize, esc_nl, size; >- char *text, *p, *op, *s; >- char lbuf[_POSIX2_LINE_MAX + 1]; >+ char *text, *s; >+ const char *p, *op; > > asize = 2 * _POSIX2_LINE_MAX + 1; > if ((text = malloc(asize)) == NULL) > err(1, "malloc"); > size = 0; >- while (cu_fgets(lbuf, sizeof(lbuf), NULL)) { >+ while ((p = cu_fgets(NULL))) { > op = s = text + size; >- p = lbuf; > EATSPACE(); > for (esc_nl = 0; *p != '\0'; p++) { > if (*p == '\\' && p[1] != '\0' && *++p == '\n') > esc_nl = 1; > *s++ = *p; >+ if (*p == '\n') >+ break; > } > size += s - op; > if (!esc_nl) { >@@ -761,9 +771,10 @@ > } > } > text[size] = '\0'; >- if ((p = realloc(text, size + 1)) == NULL) >+ if ((text = realloc(text, size + 1)) == NULL) > err(1, "realloc"); >- return (p); >+ *ptlen = size; >+ return (text); > } > > /* >@@ -770,8 +781,8 @@ > * 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(char *p, struct s_addr *a) >+static const char * >+compile_addr(const char *p, struct s_addr *a) > { > char *end, re[_POSIX2_LINE_MAX + 1]; > int icase; >@@ -825,22 +836,25 @@ > * Return a copy of all the characters up to \n or \0. > */ > static char * >-duptoeol(char *s, const char *ctype) >+duptoeol(const char *s, const char *ctype, size_t *ptlen) > { > size_t len; > int ws; >- char *p, *start; >+ char *p; >+ const char *start; > > ws = 0; > for (start = s; *s != '\0' && *s != '\n'; ++s) > ws = isspace((unsigned char)*s); >- *s = '\0'; > if (ws) > warnx("%lu: %s: whitespace after %s", linenum, fname, ctype); >- len = s - start + 1; >- if ((p = malloc(len)) == NULL) >+ len = s - start; >+ if ((p = malloc(len + 1)) == NULL) > err(1, "malloc"); >- return (memmove(p, start, len)); >+ memmove(p, start, len); >+ p[len] = '\0'; >+ *ptlen = len; >+ return p; > } > > /* >@@ -851,7 +865,7 @@ > * TODO: Remove } nodes > */ > static void >-fixuplabel(struct s_command *cp, struct s_command *end) >+fixuplabel(struct s_command *cp, const struct s_command *end) > { > > for (; cp != end; cp = cp->next) >@@ -868,7 +882,7 @@ > break; > } > if ((cp->u.c = findlabel(cp->t)) == NULL) >- errx(1, "%lu: %s: undefined label '%s'", linenum, fname, cp->t); >+ errx(1, "%lu: %s: %c: undefined label '%s'", linenum, fname, cp->code, cp->t); > free(cp->t); > break; > case '{': >@@ -908,7 +922,7 @@ > * list cp. L is excluded from the search. Return NULL if not found. > */ > static struct s_command * >-findlabel(char *name) >+findlabel(const char *name) > { > struct labhash *lh; > u_char *p; >Index: defs.h >=================================================================== >--- defs.h (revision 275828) >+++ defs.h (working copy) >@@ -94,6 +94,7 @@ > struct s_addr *a1, *a2; /* Start and end address */ > u_long startline; /* Start line number or zero */ > char *t; /* Text for : a c i r w */ >+ size_t tlen; /* Length of the text */ > union { > struct s_command *c; /* Command(s) for b t { */ > struct s_subst *s; /* Substitute command */ >Index: extern.h >=================================================================== >--- extern.h (revision 275828) >+++ extern.h (working copy) >@@ -48,9 +48,9 @@ > void cfclose(struct s_command *, struct s_command *); > void compile(void); > void cspace(SPACE *, const char *, size_t, enum e_spflag); >-char *cu_fgets(char *, int, int *); >+const char *cu_fgets(int *); > int mf_fgets(SPACE *, enum e_spflag); > int lastline(void); > void process(void); > void resetstate(void); >-char *strregerror(int, regex_t *); >+const char *strregerror(int, const regex_t *); >Index: main.c >=================================================================== >--- main.c (revision 275828) >+++ main.c (working copy) >@@ -73,7 +73,7 @@ > struct s_compunit { > struct s_compunit *next; > enum e_cut {CU_FILE, CU_STRING} type; >- char *s; /* Pointer to string or fname */ >+ const char *s; /* Pointer to string or fname */ > }; > > /* >@@ -86,7 +86,7 @@ > * Linked list of files to be processed > */ > struct s_flist { >- char *fname; >+ const char *fname; > struct s_flist *next; > }; > >@@ -117,8 +117,8 @@ > static const char *inplace; /* Inplace edit file extension. */ > u_long linenum; > >-static void add_compunit(enum e_cut, char *); >-static void add_file(char *); >+static void add_compunit(enum e_cut, const char *); >+static void add_file(const char *); > static void usage(void); > > int >@@ -214,14 +209,16 @@ > * Like fgets, but go through the chain of compilation units chaining them > * together. Empty strings and files are ignored. > */ >-char * >-cu_fgets(char *buf, int n, int *more) >+const char * >+cu_fgets(int *more) > { > static enum {ST_EOF, ST_FILE, ST_STRING} state = ST_EOF; > static FILE *f; /* Current open file */ >- static char *s; /* Current pointer inside string */ >- static char string_ident[30]; >+ static const char *s; /* Current pointer inside string */ >+ static char string_ident[30], *lastresult; >+ static size_t lastsize; > char *p; >+ const char *start; > > again: > switch (state) { >@@ -251,14 +248,16 @@ > goto again; > } > case ST_FILE: >- if ((p = fgets(buf, n, f)) != NULL) { >+ p = lastresult; >+ if (getline(&p, &lastsize, f) != -1) { > linenum++; >- if (linenum == 1 && buf[0] == '#' && buf[1] == 'n') >+ if (linenum == 1 && p[0] == '#' && p[1] == 'n') > nflag = 1; > if (more != NULL) > *more = !feof(f); >- return (p); >- } >+ return (lastresult = p); >+ } else if (ferror(f)) >+ err(1, "%s", script->s); > script = script->next; > (void)fclose(f); > state = ST_EOF; >@@ -266,39 +265,26 @@ > case ST_STRING: > if (linenum == 0 && s[0] == '#' && s[1] == 'n') > nflag = 1; >- p = buf; >+ else if (s[0] == '\0') { >+ state = ST_EOF; >+ script = script->next; >+ goto again; >+ } >+ start = s; > for (;;) { >- if (n-- <= 1) { >- *p = '\0'; >- linenum++; >- if (more != NULL) >- *more = 1; >- return (buf); >- } > switch (*s) { > case '\0': > state = ST_EOF; >- if (s == script->s) { >- script = script->next; >- goto again; >- } else { >- script = script->next; >- *p = '\0'; >- linenum++; >- if (more != NULL) >- *more = 0; >- return (buf); >- } >+ script = script->next; >+ /* FALLTHROUGH */ > case '\n': >- *p++ = '\n'; >- *p = '\0'; > s++; > linenum++; > if (more != NULL) > *more = 0; >- return (buf); >+ return (start); > default: >- *p++ = *s++; >+ s++; > } > } > } >@@ -400,13 +386,15 @@ > sizeof(oldfname)); > len = strlcat(oldfname, inplace, > sizeof(oldfname)); >- if (len > sizeof(oldfname)) >+ if ((size_t)len > sizeof(oldfname)) > errx(1, "%s: name too long", fname); > } > len = snprintf(tmpfname, sizeof(tmpfname), > "%s/.!%ld!%s", dirname(fname), (long)getpid(), > basename(fname)); >- if (len >= sizeof(tmpfname)) >+ if (len < 0) >+ err(1, "snprintf"); >+ if ((size_t)len >= sizeof(tmpfname)) > errx(1, "%s: name too long", fname); > unlink(tmpfname); > if ((outfile = fopen(tmpfname, "w")) == NULL) >@@ -452,7 +440,7 @@ > * Add a compilation unit to the linked list > */ > static void >-add_compunit(enum e_cut type, char *s) >+add_compunit(enum e_cut type, const char *s) > { > struct s_compunit *cu; > >@@ -469,7 +457,7 @@ > * Add a file to the linked list > */ > static void >-add_file(char *s) >+add_file(const char *s) > { > struct s_flist *fp; > >Index: misc.c >=================================================================== >--- misc.c (revision 275828) >+++ misc.c (working copy) >@@ -55,8 +55,8 @@ > * because of the silly semantics of regerror (we can never know the size of > * the buffer). > */ >-char * >-strregerror(int errcode, regex_t *preg) >+const char * >+strregerror(int errcode, const regex_t *preg) > { > static char *oe; > size_t s; >Index: process.c >=================================================================== >--- process.c (revision 275828) >+++ process.c (working copy) >@@ -67,12 +67,12 @@ > #define hsl HS.len > > static __inline int applies(struct s_command *); >-static void do_tr(struct s_tr *); >+static void do_tr(const struct s_tr *); > static void flush_appends(void); >-static void lputs(char *, size_t); >-static __inline int regexec_e(regex_t *, const char *, int, int, size_t); >-static void regsub(SPACE *, char *, char *); >-static int substitute(struct s_command *); >+static void lputs(const char *, size_t); >+static __inline int regexec_e(const regex_t *, const char *, int, int, size_t); >+static void regsub(SPACE *, const char *, const char *); >+static int substitute(const struct s_command *); > > struct s_appends *appends; /* Array of pointers to strings to append. */ > static int appendx; /* Index into appends array. */ >@@ -81,7 +81,7 @@ > static int lastaddr; /* Set by applies if last address of a range. */ > static int sdone; /* If any substitutes since last line input. */ > /* Iov structure for 'w' commands. */ >-static regex_t *defpreg; >+static const regex_t *defpreg; > size_t maxnsub; > regmatch_t *match; > >@@ -119,7 +119,7 @@ > err(1, "realloc"); > appends[appendx].type = AP_STRING; > appends[appendx].s = cp->t; >- appends[appendx].len = strlen(cp->t); >+ appends[appendx].len = cp->tlen; > appendx++; > break; > case 'b': >@@ -209,7 +209,7 @@ > err(1, "realloc"); > appends[appendx].type = AP_FILE; > appends[appendx].s = cp->t; >- appends[appendx].len = strlen(cp->t); >+ appends[appendx].len = cp->tlen; > appendx++; > break; > case 's': >@@ -365,7 +365,7 @@ > * and then swap them. > */ > static int >-substitute(struct s_command *cp) >+substitute(const struct s_command *cp) > { > SPACE tspace; > regex_t *re; >@@ -476,7 +476,7 @@ > * Perform translation ('y' command) in the pattern space. > */ > static void >-do_tr(struct s_tr *y) >+do_tr(const struct s_tr *y) > { > SPACE tmp; > char c, *p; >@@ -565,7 +565,7 @@ > } > > static void >-lputs(char *s, size_t len) >+lputs(const char *s, size_t len) > { > static const char escapes[] = "\\\a\b\f\r\t\v"; > int c, col, width; >@@ -645,7 +645,7 @@ > } > > static __inline int >-regexec_e(regex_t *preg, const char *string, int eflags, int nomatch, >+regexec_e(const regex_t *preg, const char *string, int eflags, int nomatch, > size_t slen) > { > int eval; >@@ -677,7 +677,7 @@ > * Based on a routine by Henry Spencer > */ > static void >-regsub(SPACE *sp, char *string, char *src) >+regsub(SPACE *sp, const char *string, const char *src) > { > int len, no; > char c, *dst;
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 195929
:
150515
|
150516
|
150518
|
150536
|
150558
|
150663
|
152797
|
153006
|
171898
|
171900
|
172273
|
172402
|
172403
|
172409
|
172442
|
172615
|
172616
|
172618