From af324b1f72282ce4fa95546af0e865b46a10a457 Mon Sep 17 00:00:00 2001 From: Ondrej Oprala Date: Fri, 8 Nov 2013 17:13:06 +0100 Subject: hexdump: add the prefix 'hexdump-' to {conv,display,parse}.c Signed-off-by: Ondrej Oprala --- text-utils/Makemodule.am | 6 +- text-utils/conv.c | 111 ---------- text-utils/display.c | 385 --------------------------------- text-utils/hexdump-conv.c | 111 ++++++++++ text-utils/hexdump-display.c | 385 +++++++++++++++++++++++++++++++++ text-utils/hexdump-parse.c | 494 +++++++++++++++++++++++++++++++++++++++++++ text-utils/parse.c | 494 ------------------------------------------- 7 files changed, 993 insertions(+), 993 deletions(-) delete mode 100644 text-utils/conv.c delete mode 100644 text-utils/display.c create mode 100644 text-utils/hexdump-conv.c create mode 100644 text-utils/hexdump-display.c create mode 100644 text-utils/hexdump-parse.c delete mode 100644 text-utils/parse.c diff --git a/text-utils/Makemodule.am b/text-utils/Makemodule.am index 970b452e9..267a195ca 100644 --- a/text-utils/Makemodule.am +++ b/text-utils/Makemodule.am @@ -29,12 +29,12 @@ column_SOURCES = text-utils/column.c column_LDADD = $(LDADD) libcommon.la hexdump_SOURCES = \ - text-utils/conv.c \ - text-utils/display.c \ + text-utils/hexdump-conv.c \ + text-utils/hexdump-display.c \ text-utils/hexdump.c \ text-utils/hexdump.h \ text-utils/hexsyntax.c \ - text-utils/parse.c + text-utils/hexdump-parse.c hexdump_LDADD = $(LDADD) libcommon.la rev_SOURCES = text-utils/rev.c diff --git a/text-utils/conv.c b/text-utils/conv.c deleted file mode 100644 index e17acc4fe..000000000 --- a/text-utils/conv.c +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include "hexdump.h" -#include "xalloc.h" - -void -conv_c(PR *pr, u_char *p) -{ - char *buf = NULL; - char const *str; - - switch(*p) { - case '\0': - str = "\\0"; - goto strpr; - /* case '\a': */ - case '\007': - str = "\\a"; - goto strpr; - case '\b': - str = "\\b"; - goto strpr; - case '\f': - str = "\\f"; - goto strpr; - case '\n': - str = "\\n"; - goto strpr; - case '\r': - str = "\\r"; - goto strpr; - case '\t': - str = "\\t"; - goto strpr; - case '\v': - str = "\\v"; - goto strpr; - default: - break; - } - if (isprint(*p)) { - *pr->cchar = 'c'; - printf(pr->fmt, *p); - } else { - xasprintf(&buf, "%03o", *p); - str = buf; -strpr: *pr->cchar = 's'; - printf(pr->fmt, str); - } - free(buf); -} - -void -conv_u(PR *pr, u_char *p) -{ - static const char *list[] = { - "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", - "bs", "ht", "lf", "vt", "ff", "cr", "so", "si", - "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb", - "can", "em", "sub", "esc", "fs", "gs", "rs", "us", - }; - - /* od used nl, not lf */ - if (*p <= 0x1f) { - *pr->cchar = 's'; - printf(pr->fmt, list[*p]); - } else if (*p == 0x7f) { - *pr->cchar = 's'; - printf(pr->fmt, "del"); - } else if (isprint(*p)) { - *pr->cchar = 'c'; - printf(pr->fmt, *p); - } else { - *pr->cchar = 'x'; - printf(pr->fmt, *p); - } -} diff --git a/text-utils/display.c b/text-utils/display.c deleted file mode 100644 index b6b1f140d..000000000 --- a/text-utils/display.c +++ /dev/null @@ -1,385 +0,0 @@ -/* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include "hexdump.h" -#include "xalloc.h" -#include "c.h" -#include "nls.h" - -static void doskip(const char *, int); -static u_char *get(void); - -enum _vflag vflag = FIRST; - -static off_t address; /* address/offset in stream */ -static off_t eaddress; /* end address */ - -static inline void -print(PR *pr, unsigned char *bp) { - - switch(pr->flags) { - case F_ADDRESS: - printf(pr->fmt, address); - break; - case F_BPAD: - printf(pr->fmt, ""); - break; - case F_C: - conv_c(pr, bp); - break; - case F_CHAR: - printf(pr->fmt, *bp); - break; - case F_DBL: - { - double dval; - float fval; - switch(pr->bcnt) { - case 4: - memmove(&fval, bp, sizeof(fval)); - printf(pr->fmt, fval); - break; - case 8: - memmove(&dval, bp, sizeof(dval)); - printf(pr->fmt, dval); - break; - } - break; - } - case F_INT: - { - short sval; /* int16_t */ - int ival; /* int32_t */ - long long Lval; /* int64_t, int64_t */ - - switch(pr->bcnt) { - case 1: - printf(pr->fmt, *bp); - break; - case 2: - memmove(&sval, bp, sizeof(sval)); - printf(pr->fmt, sval); - break; - case 4: - memmove(&ival, bp, sizeof(ival)); - printf(pr->fmt, ival); - break; - case 8: - memmove(&Lval, bp, sizeof(Lval)); - printf(pr->fmt, Lval); - break; - } - break; - } - case F_P: - printf(pr->fmt, isprint(*bp) ? *bp : '.'); - break; - case F_STR: - printf(pr->fmt, (char *)bp); - break; - case F_TEXT: - printf("%s", pr->fmt); - break; - case F_U: - conv_u(pr, bp); - break; - case F_UINT: - { - unsigned short sval; /* u_int16_t */ - unsigned int ival; /* u_int32_t */ - unsigned long long Lval;/* u_int64_t, u_int64_t */ - - switch(pr->bcnt) { - case 1: - printf(pr->fmt, *bp); - break; - case 2: - memmove(&sval, bp, sizeof(sval)); - printf(pr->fmt, sval); - break; - case 4: - memmove(&ival, bp, sizeof(ival)); - printf(pr->fmt, ival); - break; - case 8: - memmove(&Lval, bp, sizeof(Lval)); - printf(pr->fmt, Lval); - break; - } - break; - } - } -} - -static void bpad(PR *pr) -{ - static const char *spec = " -0+#"; - char *p1, *p2; - - /* - * remove all conversion flags; '-' is the only one valid - * with %s, and it's not useful here. - */ - pr->flags = F_BPAD; - pr->cchar[0] = 's'; - pr->cchar[1] = 0; - - p1 = pr->fmt; - while (*p1 != '%') - ++p1; - - p2 = ++p1; - while (*p1 && strchr(spec, *p1)) - ++p1; - - while ((*p2++ = *p1++)) - ; -} - -void display(void) -{ - register struct list_head *fs; - register FS *fss; - register FU *fu; - register PR *pr; - register int cnt; - register unsigned char *bp; - off_t saveaddress; - unsigned char savech = 0, *savebp; - struct list_head *p, *q, *r; - - while ((bp = get()) != NULL) { - fs = &fshead; savebp = bp; saveaddress = address; - - list_for_each(p, fs) { - fss = list_entry(p, FS, fslist); - - list_for_each(q, &fss->fulist) { - fu = list_entry(q, FU, fulist); - - if (fu->flags&F_IGNORE) - break; - - cnt = fu->reps; - - while (cnt) { - list_for_each(r, &fu->prlist) { - pr = list_entry(r, PR, prlist); - - if (eaddress && address >= eaddress - && !(pr->flags&(F_TEXT|F_BPAD))) - bpad(pr); - - if (cnt == 1 && pr->nospace) { - savech = *pr->nospace; - *pr->nospace = '\0'; - print(pr, bp); - *pr->nospace = savech; - } else - print(pr, bp); - - address += pr->bcnt; - bp += pr->bcnt; - } - --cnt; - } - } - bp = savebp; - address = saveaddress; - } - } - if (endfu) { - /* - * if eaddress not set, error or file size was multiple of - * blocksize, and no partial block ever found. - */ - if (!eaddress) { - if (!address) - return; - eaddress = address; - } - list_for_each (p, &endfu->prlist) { - pr = list_entry(p, PR, prlist); - switch(pr->flags) { - case F_ADDRESS: - printf(pr->fmt, eaddress); - break; - case F_TEXT: - printf("%s", pr->fmt); - break; - } - } - } -} - -static char **_argv; - -static u_char * -get(void) -{ - static int ateof = 1; - static u_char *curp, *savp; - ssize_t n, need, nread; - u_char *tmpp; - - if (!curp) { - curp = xcalloc(1, blocksize); - savp = xcalloc(1, blocksize); - } else { - tmpp = curp; - curp = savp; - savp = tmpp; - address += blocksize; - } - need = blocksize, nread = 0; - while (TRUE) { - /* - * if read the right number of bytes, or at EOF for one file, - * and no other files are available, zero-pad the rest of the - * block and set the end flag. - */ - if (!length || (ateof && !next(NULL))) { - if (need == blocksize) - goto retnul; - if (!need && vflag != ALL && - !memcmp(curp, savp, nread)) { - if (vflag != DUP) - printf("*\n"); - goto retnul; - } - if (need > 0) - memset((char *)curp + nread, 0, need); - eaddress = address + nread; - return(curp); - } - if (fileno(stdin) == -1) { - warnx(_("all input file arguments failed")); - goto retnul; - } - n = fread((char *)curp + nread, sizeof(unsigned char), - length == -1 ? need : min(length, need), stdin); - if (!n) { - if (ferror(stdin)) - warn("%s", _argv[-1]); - ateof = 1; - continue; - } - ateof = 0; - if (length != -1) - length -= n; - if (!(need -= n)) { - if (vflag == ALL || vflag == FIRST || - memcmp(curp, savp, blocksize)) { - if (vflag == DUP || vflag == FIRST) - vflag = WAIT; - return(curp); - } - if (vflag == WAIT) - printf("*\n"); - vflag = DUP; - address += blocksize; - need = blocksize; - nread = 0; - } - else - nread += n; - } -retnul: - free (curp); - free (savp); - return NULL; -} - -int next(char **argv) -{ - static int done; - int statok; - - if (argv) { - _argv = argv; - return(1); - } - while (TRUE) { - if (*_argv) { - if (!(freopen(*_argv, "r", stdin))) { - warn("%s", *_argv); - exitval = EXIT_FAILURE; - ++_argv; - continue; - } - statok = done = 1; - } else { - if (done++) - return(0); - statok = 0; - } - if (skip) - doskip(statok ? *_argv : "stdin", statok); - if (*_argv) - ++_argv; - if (!skip) - return(1); - } - /* NOTREACHED */ -} - -static void -doskip(const char *fname, int statok) -{ - struct stat sbuf; - - if (statok) { - if (fstat(fileno(stdin), &sbuf)) - err(EXIT_FAILURE, "%s", fname); - if (S_ISREG(sbuf.st_mode) && skip > sbuf.st_size) { - /* If size valid and skip >= size */ - skip -= sbuf.st_size; - address += sbuf.st_size; - return; - } - } - /* sbuf may be undefined here - do not test it */ - if (fseek(stdin, skip, SEEK_SET)) - err(EXIT_FAILURE, "%s", fname); - address += skip; - skip = 0; -} diff --git a/text-utils/hexdump-conv.c b/text-utils/hexdump-conv.c new file mode 100644 index 000000000..e17acc4fe --- /dev/null +++ b/text-utils/hexdump-conv.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include "hexdump.h" +#include "xalloc.h" + +void +conv_c(PR *pr, u_char *p) +{ + char *buf = NULL; + char const *str; + + switch(*p) { + case '\0': + str = "\\0"; + goto strpr; + /* case '\a': */ + case '\007': + str = "\\a"; + goto strpr; + case '\b': + str = "\\b"; + goto strpr; + case '\f': + str = "\\f"; + goto strpr; + case '\n': + str = "\\n"; + goto strpr; + case '\r': + str = "\\r"; + goto strpr; + case '\t': + str = "\\t"; + goto strpr; + case '\v': + str = "\\v"; + goto strpr; + default: + break; + } + if (isprint(*p)) { + *pr->cchar = 'c'; + printf(pr->fmt, *p); + } else { + xasprintf(&buf, "%03o", *p); + str = buf; +strpr: *pr->cchar = 's'; + printf(pr->fmt, str); + } + free(buf); +} + +void +conv_u(PR *pr, u_char *p) +{ + static const char *list[] = { + "nul", "soh", "stx", "etx", "eot", "enq", "ack", "bel", + "bs", "ht", "lf", "vt", "ff", "cr", "so", "si", + "dle", "dcl", "dc2", "dc3", "dc4", "nak", "syn", "etb", + "can", "em", "sub", "esc", "fs", "gs", "rs", "us", + }; + + /* od used nl, not lf */ + if (*p <= 0x1f) { + *pr->cchar = 's'; + printf(pr->fmt, list[*p]); + } else if (*p == 0x7f) { + *pr->cchar = 's'; + printf(pr->fmt, "del"); + } else if (isprint(*p)) { + *pr->cchar = 'c'; + printf(pr->fmt, *p); + } else { + *pr->cchar = 'x'; + printf(pr->fmt, *p); + } +} diff --git a/text-utils/hexdump-display.c b/text-utils/hexdump-display.c new file mode 100644 index 000000000..b6b1f140d --- /dev/null +++ b/text-utils/hexdump-display.c @@ -0,0 +1,385 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hexdump.h" +#include "xalloc.h" +#include "c.h" +#include "nls.h" + +static void doskip(const char *, int); +static u_char *get(void); + +enum _vflag vflag = FIRST; + +static off_t address; /* address/offset in stream */ +static off_t eaddress; /* end address */ + +static inline void +print(PR *pr, unsigned char *bp) { + + switch(pr->flags) { + case F_ADDRESS: + printf(pr->fmt, address); + break; + case F_BPAD: + printf(pr->fmt, ""); + break; + case F_C: + conv_c(pr, bp); + break; + case F_CHAR: + printf(pr->fmt, *bp); + break; + case F_DBL: + { + double dval; + float fval; + switch(pr->bcnt) { + case 4: + memmove(&fval, bp, sizeof(fval)); + printf(pr->fmt, fval); + break; + case 8: + memmove(&dval, bp, sizeof(dval)); + printf(pr->fmt, dval); + break; + } + break; + } + case F_INT: + { + short sval; /* int16_t */ + int ival; /* int32_t */ + long long Lval; /* int64_t, int64_t */ + + switch(pr->bcnt) { + case 1: + printf(pr->fmt, *bp); + break; + case 2: + memmove(&sval, bp, sizeof(sval)); + printf(pr->fmt, sval); + break; + case 4: + memmove(&ival, bp, sizeof(ival)); + printf(pr->fmt, ival); + break; + case 8: + memmove(&Lval, bp, sizeof(Lval)); + printf(pr->fmt, Lval); + break; + } + break; + } + case F_P: + printf(pr->fmt, isprint(*bp) ? *bp : '.'); + break; + case F_STR: + printf(pr->fmt, (char *)bp); + break; + case F_TEXT: + printf("%s", pr->fmt); + break; + case F_U: + conv_u(pr, bp); + break; + case F_UINT: + { + unsigned short sval; /* u_int16_t */ + unsigned int ival; /* u_int32_t */ + unsigned long long Lval;/* u_int64_t, u_int64_t */ + + switch(pr->bcnt) { + case 1: + printf(pr->fmt, *bp); + break; + case 2: + memmove(&sval, bp, sizeof(sval)); + printf(pr->fmt, sval); + break; + case 4: + memmove(&ival, bp, sizeof(ival)); + printf(pr->fmt, ival); + break; + case 8: + memmove(&Lval, bp, sizeof(Lval)); + printf(pr->fmt, Lval); + break; + } + break; + } + } +} + +static void bpad(PR *pr) +{ + static const char *spec = " -0+#"; + char *p1, *p2; + + /* + * remove all conversion flags; '-' is the only one valid + * with %s, and it's not useful here. + */ + pr->flags = F_BPAD; + pr->cchar[0] = 's'; + pr->cchar[1] = 0; + + p1 = pr->fmt; + while (*p1 != '%') + ++p1; + + p2 = ++p1; + while (*p1 && strchr(spec, *p1)) + ++p1; + + while ((*p2++ = *p1++)) + ; +} + +void display(void) +{ + register struct list_head *fs; + register FS *fss; + register FU *fu; + register PR *pr; + register int cnt; + register unsigned char *bp; + off_t saveaddress; + unsigned char savech = 0, *savebp; + struct list_head *p, *q, *r; + + while ((bp = get()) != NULL) { + fs = &fshead; savebp = bp; saveaddress = address; + + list_for_each(p, fs) { + fss = list_entry(p, FS, fslist); + + list_for_each(q, &fss->fulist) { + fu = list_entry(q, FU, fulist); + + if (fu->flags&F_IGNORE) + break; + + cnt = fu->reps; + + while (cnt) { + list_for_each(r, &fu->prlist) { + pr = list_entry(r, PR, prlist); + + if (eaddress && address >= eaddress + && !(pr->flags&(F_TEXT|F_BPAD))) + bpad(pr); + + if (cnt == 1 && pr->nospace) { + savech = *pr->nospace; + *pr->nospace = '\0'; + print(pr, bp); + *pr->nospace = savech; + } else + print(pr, bp); + + address += pr->bcnt; + bp += pr->bcnt; + } + --cnt; + } + } + bp = savebp; + address = saveaddress; + } + } + if (endfu) { + /* + * if eaddress not set, error or file size was multiple of + * blocksize, and no partial block ever found. + */ + if (!eaddress) { + if (!address) + return; + eaddress = address; + } + list_for_each (p, &endfu->prlist) { + pr = list_entry(p, PR, prlist); + switch(pr->flags) { + case F_ADDRESS: + printf(pr->fmt, eaddress); + break; + case F_TEXT: + printf("%s", pr->fmt); + break; + } + } + } +} + +static char **_argv; + +static u_char * +get(void) +{ + static int ateof = 1; + static u_char *curp, *savp; + ssize_t n, need, nread; + u_char *tmpp; + + if (!curp) { + curp = xcalloc(1, blocksize); + savp = xcalloc(1, blocksize); + } else { + tmpp = curp; + curp = savp; + savp = tmpp; + address += blocksize; + } + need = blocksize, nread = 0; + while (TRUE) { + /* + * if read the right number of bytes, or at EOF for one file, + * and no other files are available, zero-pad the rest of the + * block and set the end flag. + */ + if (!length || (ateof && !next(NULL))) { + if (need == blocksize) + goto retnul; + if (!need && vflag != ALL && + !memcmp(curp, savp, nread)) { + if (vflag != DUP) + printf("*\n"); + goto retnul; + } + if (need > 0) + memset((char *)curp + nread, 0, need); + eaddress = address + nread; + return(curp); + } + if (fileno(stdin) == -1) { + warnx(_("all input file arguments failed")); + goto retnul; + } + n = fread((char *)curp + nread, sizeof(unsigned char), + length == -1 ? need : min(length, need), stdin); + if (!n) { + if (ferror(stdin)) + warn("%s", _argv[-1]); + ateof = 1; + continue; + } + ateof = 0; + if (length != -1) + length -= n; + if (!(need -= n)) { + if (vflag == ALL || vflag == FIRST || + memcmp(curp, savp, blocksize)) { + if (vflag == DUP || vflag == FIRST) + vflag = WAIT; + return(curp); + } + if (vflag == WAIT) + printf("*\n"); + vflag = DUP; + address += blocksize; + need = blocksize; + nread = 0; + } + else + nread += n; + } +retnul: + free (curp); + free (savp); + return NULL; +} + +int next(char **argv) +{ + static int done; + int statok; + + if (argv) { + _argv = argv; + return(1); + } + while (TRUE) { + if (*_argv) { + if (!(freopen(*_argv, "r", stdin))) { + warn("%s", *_argv); + exitval = EXIT_FAILURE; + ++_argv; + continue; + } + statok = done = 1; + } else { + if (done++) + return(0); + statok = 0; + } + if (skip) + doskip(statok ? *_argv : "stdin", statok); + if (*_argv) + ++_argv; + if (!skip) + return(1); + } + /* NOTREACHED */ +} + +static void +doskip(const char *fname, int statok) +{ + struct stat sbuf; + + if (statok) { + if (fstat(fileno(stdin), &sbuf)) + err(EXIT_FAILURE, "%s", fname); + if (S_ISREG(sbuf.st_mode) && skip > sbuf.st_size) { + /* If size valid and skip >= size */ + skip -= sbuf.st_size; + address += sbuf.st_size; + return; + } + } + /* sbuf may be undefined here - do not test it */ + if (fseek(stdin, skip, SEEK_SET)) + err(EXIT_FAILURE, "%s", fname); + address += skip; + skip = 0; +} diff --git a/text-utils/hexdump-parse.c b/text-utils/hexdump-parse.c new file mode 100644 index 000000000..37d2a4c86 --- /dev/null +++ b/text-utils/hexdump-parse.c @@ -0,0 +1,494 @@ +/* + * Copyright (c) 1989 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + + /* 1999-02-22 Arkadiusz Miśkiewicz + * - added Native Language Support + */ + +#include +#include +#include +#include +#include +#include +#include "hexdump.h" +#include "nls.h" +#include "xalloc.h" +#include "strutils.h" + +static void escape(char *p1); +static void badcnt(const char *s); +static void badsfmt(void); +static void badfmt(const char *fmt); +static void badconv(const char *ch); + +#define first_letter(s,f) strchr(f, *(s)) + +FU *endfu; /* format at end-of-data */ + +void addfile(char *name) +{ + char *fmt, *buf = NULL; + FILE *fp; + size_t n; + + if ((fp = fopen(name, "r")) == NULL) + err(EXIT_FAILURE, _("can't read %s"), name); + + while (getline(&buf, &n, fp) != -1) { + fmt = buf; + + while (*fmt && isspace(*fmt)) + ++fmt; + if (!*fmt || *fmt == '#') + continue; + + add(fmt); + } + + free(buf); + fclose(fp); +} + +void add(const char *fmt) +{ + const char *p, *savep; + FS *tfs; + FU *tfu; + + /* Start new linked list of format units. */ + tfs = xcalloc(1, sizeof(FS)); + INIT_LIST_HEAD(&tfs->fslist); + INIT_LIST_HEAD(&tfs->fulist); + list_add_tail(&tfs->fslist, &fshead); + + /* Take the format string and break it up into format units. */ + p = fmt; + while (TRUE) { + /* Skip leading white space. */ + if (!*(p = skip_space(p))) + break; + + /* Allocate a new format unit and link it in. */ + tfu = xcalloc(1, sizeof(FU)); + tfu->reps = 1; + + INIT_LIST_HEAD(&tfu->fulist); + INIT_LIST_HEAD(&tfu->prlist); + list_add_tail(&tfu->fulist, &tfs->fulist); + + /* If leading digit, repetition count. */ + if (isdigit(*p)) { + savep = p; + while (isdigit(*p) && ++p) + ; + if (!isspace(*p) && *p != '/') + badfmt(fmt); + /* may overwrite either white space or slash */ + tfu->reps = atoi(savep); + tfu->flags = F_SETREP; + /* skip trailing white space */ + p = skip_space(++p); + } + + /* Skip slash and trailing white space. */ + if (*p == '/') + p = skip_space(p); + + /* byte count */ + if (isdigit(*p)) { + savep = p; + while (isdigit(*p) && ++p) + ; + if (!isspace(*p)) + badfmt(fmt); + tfu->bcnt = atoi(savep); + /* skip trailing white space */ + p = skip_space(++p); + } + + /* format */ + if (*p != '"') + badfmt(fmt); + savep = ++p; + while (*p != '"') { + if (!*p++) + badfmt(fmt); + } + tfu->fmt = xmalloc(p - savep + 1); + xstrncpy(tfu->fmt, savep, p - savep + 1); + escape(tfu->fmt); + ++p; + } +} + +static const char *spec = ".#-+ 0123456789"; + +int block_size(FS *fs) +{ + FU *fu; + int bcnt, prec, cursize = 0; + char *fmt; + struct list_head *p; + + /* figure out the data block size needed for each format unit */ + list_for_each (p, &fs->fulist) { + fu = list_entry(p, FU, fulist); + if (fu->bcnt) { + cursize += fu->bcnt * fu->reps; + continue; + } + bcnt = prec = 0; + fmt = fu->fmt; + while (*fmt) { + if (*fmt != '%') { + ++fmt; + continue; + } + /* + * skip any special chars -- save precision in + * case it's a %s format. + */ + while (strchr(spec + 1, *++fmt)) + ; + if (*fmt == '.' && isdigit(*++fmt)) { + prec = atoi(fmt); + while (isdigit(*++fmt)) + ; + } + if (first_letter(fmt, "diouxX")) + bcnt += 4; + else if (first_letter(fmt, "efgEG")) + bcnt += 8; + else if (*fmt == 's') + bcnt += prec; + else if (*fmt == 'c' || (*fmt == '_' && first_letter(++fmt, "cpu"))) + ++bcnt; + ++fmt; + } + cursize += bcnt * fu->reps; + } + return(cursize); +} + +void rewrite(FS *fs) +{ + enum { NOTOKAY, USEBCNT, USEPREC } sokay; + PR *pr; + FU *fu; + struct list_head *p, *q; + char *p1, *p2, *fmtp; + char savech, cs[3]; + int nconv, prec = 0; + + list_for_each (p, &fs->fulist) { + fu = list_entry(p, FU, fulist); + /* + * Break each format unit into print units; each + * conversion character gets its own. + */ + nconv = 0; + fmtp = fu->fmt; + while (*fmtp) { + pr = xcalloc(1, sizeof(PR)); + INIT_LIST_HEAD(&pr->prlist); + list_add_tail(&pr->prlist, &fu->prlist); + + /* Skip preceding text and up to the next % sign. */ + p1 = fmtp; + while (*p1 && *p1 != '%') + ++p1; + + /* Only text in the string. */ + if (!*p1) { + pr->fmt = xstrdup(fmtp); + pr->flags = F_TEXT; + break; + } + + /* + * Get precision for %s -- if have a byte count, don't + * need it. + */ + if (fu->bcnt) { + sokay = USEBCNT; + /* skip to conversion character */ + while (++p1 && strchr(spec, *p1)) + ; + } else { + /* skip any special chars, field width */ + while (strchr(spec + 1, *++p1)) + ; + if (*p1 == '.' && isdigit(*++p1)) { + sokay = USEPREC; + prec = atoi(p1); + while (isdigit(*++p1)) + ; + } else + sokay = NOTOKAY; + } + + p2 = p1 + 1; /* Set end pointer. */ + cs[0] = *p1; /* Set conversion string. */ + cs[1] = 0; + + /* + * Figure out the byte count for each conversion; + * rewrite the format as necessary, set up blank- + * padding for end of data. + */ + if (*cs == 'c') { + pr->flags = F_CHAR; + switch(fu->bcnt) { + case 0: + case 1: + pr->bcnt = 1; + break; + default: + p1[1] = '\0'; + badcnt(p1); + } + } else if (first_letter(cs, "di")) { + pr->flags = F_INT; + goto isint; + } else if (first_letter(cs, "ouxX")) { + pr->flags = F_UINT; +isint: cs[2] = '\0'; + cs[1] = cs[0]; + cs[0] = 'q'; + switch(fu->bcnt) { + case 0: + pr->bcnt = 4; + break; + case 1: + case 2: + case 4: + case 8: + pr->bcnt = fu->bcnt; + break; + default: + p1[1] = '\0'; + badcnt(p1); + } + } else if (first_letter(cs, "efgEG")) { + pr->flags = F_DBL; + switch(fu->bcnt) { + case 0: + pr->bcnt = 8; + break; + case 4: + case 8: + pr->bcnt = fu->bcnt; + break; + default: + p1[1] = '\0'; + badcnt(p1); + } + } else if(*cs == 's') { + pr->flags = F_STR; + switch(sokay) { + case NOTOKAY: + badsfmt(); + case USEBCNT: + pr->bcnt = fu->bcnt; + break; + case USEPREC: + pr->bcnt = prec; + break; + } + } else if (*cs == '_') { + ++p2; + switch(p1[1]) { + case 'A': + endfu = fu; + fu->flags |= F_IGNORE; + /* FALLTHROUGH */ + case 'a': + pr->flags = F_ADDRESS; + ++p2; + if (first_letter(p1 + 2, "dox")) { + cs[0] = 'q'; + cs[1] = p1[2]; + cs[2] = '\0'; + } else { + p1[3] = '\0'; + badconv(p1); + } + break; + case 'c': + pr->flags = F_C; + /* cs[0] = 'c'; set in conv_c */ + goto isint2; + case 'p': + pr->flags = F_P; + cs[0] = 'c'; + goto isint2; + case 'u': + pr->flags = F_U; + /* cs[0] = 'c'; set in conv_u */ + isint2: switch(fu->bcnt) { + case 0: + case 1: + pr->bcnt = 1; + break; + default: + p1[2] = '\0'; + badcnt(p1); + } + break; + default: + p1[2] = '\0'; + badconv(p1); + } + } else { + p1[1] = '\0'; + badconv(p1); + } + + /* + * Copy to PR format string, set conversion character + * pointer, update original. + */ + savech = *p2; + p1[0] = '\0'; + pr->fmt = xmalloc(strlen(fmtp) + strlen(cs) + 1); + strcpy(pr->fmt, fmtp); + strcat(pr->fmt, cs); + *p2 = savech; + pr->cchar = pr->fmt + (p1 - fmtp); + fmtp = p2; + + /* Only one conversion character if byte count */ + if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++) + errx(EXIT_FAILURE, + _("byte count with multiple conversion characters")); + } + /* + * If format unit byte count not specified, figure it out + * so can adjust rep count later. + */ + if (!fu->bcnt) + list_for_each(q, &fu->prlist) + fu->bcnt += (list_entry(q, PR, prlist))->bcnt; + } + /* + * If the format string interprets any data at all, and it's + * not the same as the blocksize, and its last format unit + * interprets any data at all, and has no iteration count, + * repeat it as necessary. + * + * If rep count is greater than 1, no trailing whitespace + * gets output from the last iteration of the format unit. + */ + list_for_each (p, &fs->fulist) { + fu = list_entry(p, FU, fulist); + + if (list_entry_is_last(&fu->fulist, &fs->fulist) && + fs->bcnt < blocksize && + !(fu->flags&F_SETREP) && fu->bcnt) + fu->reps += (blocksize - fs->bcnt) / fu->bcnt; + if (fu->reps > 1) { + if (!list_empty(&fu->prlist)) { + pr = list_last_entry(&fu->prlist, PR, prlist); + for (p1 = pr->fmt, p2 = NULL; *p1; ++p1) + p2 = isspace(*p1) ? p1 : NULL; + if (p2) + pr->nospace = p2; + } + } + } +} + + +static void escape(char *p1) +{ + char *p2; + + /* alphabetic escape sequences have to be done in place */ + p2 = p1; + while (TRUE) { + if (!*p1) { + *p2 = *p1; + break; + } + if (*p1 == '\\') + switch(*++p1) { + case 'a': + /* *p2 = '\a'; */ + *p2 = '\007'; + break; + case 'b': + *p2 = '\b'; + break; + case 'f': + *p2 = '\f'; + break; + case 'n': + *p2 = '\n'; + break; + case 'r': + *p2 = '\r'; + break; + case 't': + *p2 = '\t'; + break; + case 'v': + *p2 = '\v'; + break; + default: + *p2 = *p1; + break; + } + ++p1; ++p2; + } +} + +static void badcnt(const char *s) +{ + errx(EXIT_FAILURE, _("bad byte count for conversion character %s"), s); +} + +static void badsfmt(void) +{ + errx(EXIT_FAILURE, _("%%s requires a precision or a byte count")); +} + +static void badfmt(const char *fmt) +{ + errx(EXIT_FAILURE, _("bad format {%s}"), fmt); +} + +static void badconv(const char *ch) +{ + errx(EXIT_FAILURE, _("bad conversion character %%%s"), ch); +} diff --git a/text-utils/parse.c b/text-utils/parse.c deleted file mode 100644 index 37d2a4c86..000000000 --- a/text-utils/parse.c +++ /dev/null @@ -1,494 +0,0 @@ -/* - * Copyright (c) 1989 The Regents of the University of California. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - - /* 1999-02-22 Arkadiusz Miśkiewicz - * - added Native Language Support - */ - -#include -#include -#include -#include -#include -#include -#include "hexdump.h" -#include "nls.h" -#include "xalloc.h" -#include "strutils.h" - -static void escape(char *p1); -static void badcnt(const char *s); -static void badsfmt(void); -static void badfmt(const char *fmt); -static void badconv(const char *ch); - -#define first_letter(s,f) strchr(f, *(s)) - -FU *endfu; /* format at end-of-data */ - -void addfile(char *name) -{ - char *fmt, *buf = NULL; - FILE *fp; - size_t n; - - if ((fp = fopen(name, "r")) == NULL) - err(EXIT_FAILURE, _("can't read %s"), name); - - while (getline(&buf, &n, fp) != -1) { - fmt = buf; - - while (*fmt && isspace(*fmt)) - ++fmt; - if (!*fmt || *fmt == '#') - continue; - - add(fmt); - } - - free(buf); - fclose(fp); -} - -void add(const char *fmt) -{ - const char *p, *savep; - FS *tfs; - FU *tfu; - - /* Start new linked list of format units. */ - tfs = xcalloc(1, sizeof(FS)); - INIT_LIST_HEAD(&tfs->fslist); - INIT_LIST_HEAD(&tfs->fulist); - list_add_tail(&tfs->fslist, &fshead); - - /* Take the format string and break it up into format units. */ - p = fmt; - while (TRUE) { - /* Skip leading white space. */ - if (!*(p = skip_space(p))) - break; - - /* Allocate a new format unit and link it in. */ - tfu = xcalloc(1, sizeof(FU)); - tfu->reps = 1; - - INIT_LIST_HEAD(&tfu->fulist); - INIT_LIST_HEAD(&tfu->prlist); - list_add_tail(&tfu->fulist, &tfs->fulist); - - /* If leading digit, repetition count. */ - if (isdigit(*p)) { - savep = p; - while (isdigit(*p) && ++p) - ; - if (!isspace(*p) && *p != '/') - badfmt(fmt); - /* may overwrite either white space or slash */ - tfu->reps = atoi(savep); - tfu->flags = F_SETREP; - /* skip trailing white space */ - p = skip_space(++p); - } - - /* Skip slash and trailing white space. */ - if (*p == '/') - p = skip_space(p); - - /* byte count */ - if (isdigit(*p)) { - savep = p; - while (isdigit(*p) && ++p) - ; - if (!isspace(*p)) - badfmt(fmt); - tfu->bcnt = atoi(savep); - /* skip trailing white space */ - p = skip_space(++p); - } - - /* format */ - if (*p != '"') - badfmt(fmt); - savep = ++p; - while (*p != '"') { - if (!*p++) - badfmt(fmt); - } - tfu->fmt = xmalloc(p - savep + 1); - xstrncpy(tfu->fmt, savep, p - savep + 1); - escape(tfu->fmt); - ++p; - } -} - -static const char *spec = ".#-+ 0123456789"; - -int block_size(FS *fs) -{ - FU *fu; - int bcnt, prec, cursize = 0; - char *fmt; - struct list_head *p; - - /* figure out the data block size needed for each format unit */ - list_for_each (p, &fs->fulist) { - fu = list_entry(p, FU, fulist); - if (fu->bcnt) { - cursize += fu->bcnt * fu->reps; - continue; - } - bcnt = prec = 0; - fmt = fu->fmt; - while (*fmt) { - if (*fmt != '%') { - ++fmt; - continue; - } - /* - * skip any special chars -- save precision in - * case it's a %s format. - */ - while (strchr(spec + 1, *++fmt)) - ; - if (*fmt == '.' && isdigit(*++fmt)) { - prec = atoi(fmt); - while (isdigit(*++fmt)) - ; - } - if (first_letter(fmt, "diouxX")) - bcnt += 4; - else if (first_letter(fmt, "efgEG")) - bcnt += 8; - else if (*fmt == 's') - bcnt += prec; - else if (*fmt == 'c' || (*fmt == '_' && first_letter(++fmt, "cpu"))) - ++bcnt; - ++fmt; - } - cursize += bcnt * fu->reps; - } - return(cursize); -} - -void rewrite(FS *fs) -{ - enum { NOTOKAY, USEBCNT, USEPREC } sokay; - PR *pr; - FU *fu; - struct list_head *p, *q; - char *p1, *p2, *fmtp; - char savech, cs[3]; - int nconv, prec = 0; - - list_for_each (p, &fs->fulist) { - fu = list_entry(p, FU, fulist); - /* - * Break each format unit into print units; each - * conversion character gets its own. - */ - nconv = 0; - fmtp = fu->fmt; - while (*fmtp) { - pr = xcalloc(1, sizeof(PR)); - INIT_LIST_HEAD(&pr->prlist); - list_add_tail(&pr->prlist, &fu->prlist); - - /* Skip preceding text and up to the next % sign. */ - p1 = fmtp; - while (*p1 && *p1 != '%') - ++p1; - - /* Only text in the string. */ - if (!*p1) { - pr->fmt = xstrdup(fmtp); - pr->flags = F_TEXT; - break; - } - - /* - * Get precision for %s -- if have a byte count, don't - * need it. - */ - if (fu->bcnt) { - sokay = USEBCNT; - /* skip to conversion character */ - while (++p1 && strchr(spec, *p1)) - ; - } else { - /* skip any special chars, field width */ - while (strchr(spec + 1, *++p1)) - ; - if (*p1 == '.' && isdigit(*++p1)) { - sokay = USEPREC; - prec = atoi(p1); - while (isdigit(*++p1)) - ; - } else - sokay = NOTOKAY; - } - - p2 = p1 + 1; /* Set end pointer. */ - cs[0] = *p1; /* Set conversion string. */ - cs[1] = 0; - - /* - * Figure out the byte count for each conversion; - * rewrite the format as necessary, set up blank- - * padding for end of data. - */ - if (*cs == 'c') { - pr->flags = F_CHAR; - switch(fu->bcnt) { - case 0: - case 1: - pr->bcnt = 1; - break; - default: - p1[1] = '\0'; - badcnt(p1); - } - } else if (first_letter(cs, "di")) { - pr->flags = F_INT; - goto isint; - } else if (first_letter(cs, "ouxX")) { - pr->flags = F_UINT; -isint: cs[2] = '\0'; - cs[1] = cs[0]; - cs[0] = 'q'; - switch(fu->bcnt) { - case 0: - pr->bcnt = 4; - break; - case 1: - case 2: - case 4: - case 8: - pr->bcnt = fu->bcnt; - break; - default: - p1[1] = '\0'; - badcnt(p1); - } - } else if (first_letter(cs, "efgEG")) { - pr->flags = F_DBL; - switch(fu->bcnt) { - case 0: - pr->bcnt = 8; - break; - case 4: - case 8: - pr->bcnt = fu->bcnt; - break; - default: - p1[1] = '\0'; - badcnt(p1); - } - } else if(*cs == 's') { - pr->flags = F_STR; - switch(sokay) { - case NOTOKAY: - badsfmt(); - case USEBCNT: - pr->bcnt = fu->bcnt; - break; - case USEPREC: - pr->bcnt = prec; - break; - } - } else if (*cs == '_') { - ++p2; - switch(p1[1]) { - case 'A': - endfu = fu; - fu->flags |= F_IGNORE; - /* FALLTHROUGH */ - case 'a': - pr->flags = F_ADDRESS; - ++p2; - if (first_letter(p1 + 2, "dox")) { - cs[0] = 'q'; - cs[1] = p1[2]; - cs[2] = '\0'; - } else { - p1[3] = '\0'; - badconv(p1); - } - break; - case 'c': - pr->flags = F_C; - /* cs[0] = 'c'; set in conv_c */ - goto isint2; - case 'p': - pr->flags = F_P; - cs[0] = 'c'; - goto isint2; - case 'u': - pr->flags = F_U; - /* cs[0] = 'c'; set in conv_u */ - isint2: switch(fu->bcnt) { - case 0: - case 1: - pr->bcnt = 1; - break; - default: - p1[2] = '\0'; - badcnt(p1); - } - break; - default: - p1[2] = '\0'; - badconv(p1); - } - } else { - p1[1] = '\0'; - badconv(p1); - } - - /* - * Copy to PR format string, set conversion character - * pointer, update original. - */ - savech = *p2; - p1[0] = '\0'; - pr->fmt = xmalloc(strlen(fmtp) + strlen(cs) + 1); - strcpy(pr->fmt, fmtp); - strcat(pr->fmt, cs); - *p2 = savech; - pr->cchar = pr->fmt + (p1 - fmtp); - fmtp = p2; - - /* Only one conversion character if byte count */ - if (!(pr->flags&F_ADDRESS) && fu->bcnt && nconv++) - errx(EXIT_FAILURE, - _("byte count with multiple conversion characters")); - } - /* - * If format unit byte count not specified, figure it out - * so can adjust rep count later. - */ - if (!fu->bcnt) - list_for_each(q, &fu->prlist) - fu->bcnt += (list_entry(q, PR, prlist))->bcnt; - } - /* - * If the format string interprets any data at all, and it's - * not the same as the blocksize, and its last format unit - * interprets any data at all, and has no iteration count, - * repeat it as necessary. - * - * If rep count is greater than 1, no trailing whitespace - * gets output from the last iteration of the format unit. - */ - list_for_each (p, &fs->fulist) { - fu = list_entry(p, FU, fulist); - - if (list_entry_is_last(&fu->fulist, &fs->fulist) && - fs->bcnt < blocksize && - !(fu->flags&F_SETREP) && fu->bcnt) - fu->reps += (blocksize - fs->bcnt) / fu->bcnt; - if (fu->reps > 1) { - if (!list_empty(&fu->prlist)) { - pr = list_last_entry(&fu->prlist, PR, prlist); - for (p1 = pr->fmt, p2 = NULL; *p1; ++p1) - p2 = isspace(*p1) ? p1 : NULL; - if (p2) - pr->nospace = p2; - } - } - } -} - - -static void escape(char *p1) -{ - char *p2; - - /* alphabetic escape sequences have to be done in place */ - p2 = p1; - while (TRUE) { - if (!*p1) { - *p2 = *p1; - break; - } - if (*p1 == '\\') - switch(*++p1) { - case 'a': - /* *p2 = '\a'; */ - *p2 = '\007'; - break; - case 'b': - *p2 = '\b'; - break; - case 'f': - *p2 = '\f'; - break; - case 'n': - *p2 = '\n'; - break; - case 'r': - *p2 = '\r'; - break; - case 't': - *p2 = '\t'; - break; - case 'v': - *p2 = '\v'; - break; - default: - *p2 = *p1; - break; - } - ++p1; ++p2; - } -} - -static void badcnt(const char *s) -{ - errx(EXIT_FAILURE, _("bad byte count for conversion character %s"), s); -} - -static void badsfmt(void) -{ - errx(EXIT_FAILURE, _("%%s requires a precision or a byte count")); -} - -static void badfmt(const char *fmt) -{ - errx(EXIT_FAILURE, _("bad format {%s}"), fmt); -} - -static void badconv(const char *ch) -{ - errx(EXIT_FAILURE, _("bad conversion character %%%s"), ch); -} -- cgit v1.2.3-55-g7522