busybox/coreutils/od.c
<<
>>
Prefs
   1/* vi: set sw=4 ts=4: */
   2/*
   3 * od implementation for busybox
   4 * Based on code from util-linux v 2.11l
   5 *
   6 * Copyright (c) 1990
   7 *      The Regents of the University of California.  All rights reserved.
   8 *
   9 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
  10 *
  11 * Original copyright notice is retained at the end of this file.
  12 */
  13
  14
  15#include "libbb.h"
  16#if ENABLE_DESKTOP
  17/* This one provides -t (busybox's own build script needs it) */
  18#include "od_bloaty.c"
  19#else
  20
  21#include "dump.h"
  22
  23#define isdecdigit(c) isdigit(c)
  24#define ishexdigit(c) (isxdigit)(c)
  25
  26static void
  27odoffset(dumper_t *dumper, int argc, char ***argvp)
  28{
  29        char *num, *p;
  30        int base;
  31        char *end;
  32
  33        /*
  34         * The offset syntax of od(1) was genuinely bizarre.  First, if
  35         * it started with a plus it had to be an offset.  Otherwise, if
  36         * there were at least two arguments, a number or lower-case 'x'
  37         * followed by a number makes it an offset.  By default it was
  38         * octal; if it started with 'x' or '0x' it was hex.  If it ended
  39         * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
  40         * multiplied the number by 512 or 1024 byte units.  There was
  41         * no way to assign a block count to a hex offset.
  42         *
  43         * We assumes it's a file if the offset is bad.
  44         */
  45        p = **argvp;
  46
  47        if (!p) {
  48                /* hey someone is probably piping to us ... */
  49                return;
  50        }
  51
  52        if ((*p != '+')
  53                && (argc < 2
  54                        || (!isdecdigit(p[0])
  55                                && ((p[0] != 'x') || !ishexdigit(p[1])))))
  56                return;
  57
  58        base = 0;
  59        /*
  60         * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
  61         * set base.
  62         */
  63        if (p[0] == '+')
  64                ++p;
  65        if (p[0] == 'x' && ishexdigit(p[1])) {
  66                ++p;
  67                base = 16;
  68        } else if (p[0] == '0' && p[1] == 'x') {
  69                p += 2;
  70                base = 16;
  71        }
  72
  73        /* skip over the number */
  74        if (base == 16)
  75                for (num = p; ishexdigit(*p); ++p)
  76                        continue;
  77        else
  78                for (num = p; isdecdigit(*p); ++p)
  79                        continue;
  80
  81        /* check for no number */
  82        if (num == p)
  83                return;
  84
  85        /* if terminates with a '.', base is decimal */
  86        if (*p == '.') {
  87                if (base)
  88                        return;
  89                base = 10;
  90        }
  91
  92        dumper->dump_skip = strtol(num, &end, base ? base : 8);
  93
  94        /* if end isn't the same as p, we got a non-octal digit */
  95        if (end != p)
  96                dumper->dump_skip = 0;
  97        else {
  98                if (*p) {
  99                        if (*p == 'b') {
 100                                dumper->dump_skip *= 512;
 101                                ++p;
 102                        } else if (*p == 'B') {
 103                                dumper->dump_skip *= 1024;
 104                                ++p;
 105                        }
 106                }
 107                if (*p)
 108                        dumper->dump_skip = 0;
 109                else {
 110                        ++*argvp;
 111                        /*
 112                         * If the offset uses a non-octal base, the base of
 113                         * the offset is changed as well.  This isn't pretty,
 114                         * but it's easy.
 115                         */
 116#define TYPE_OFFSET     7
 117                        {
 118                                char x_or_d;
 119                                if (base == 16) {
 120                                        x_or_d = 'x';
 121                                        goto DO_X_OR_D;
 122                                }
 123                                if (base == 10) {
 124                                        x_or_d = 'd';
 125 DO_X_OR_D:
 126                                        dumper->fshead->nextfu->fmt[TYPE_OFFSET]
 127                                                = dumper->fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
 128                                                = x_or_d;
 129                                }
 130                        }
 131                }
 132        }
 133}
 134
 135static const char *const add_strings[] = {
 136        "16/1 \"%3_u \" \"\\n\"",                               /* a */
 137        "8/2 \" %06o \" \"\\n\"",                               /* B, o */
 138        "16/1 \"%03o \" \"\\n\"",                               /* b */
 139        "16/1 \"%3_c \" \"\\n\"",                               /* c */
 140        "8/2 \"  %05u \" \"\\n\"",                              /* d */
 141        "4/4 \"     %010u \" \"\\n\"",                  /* D */
 142        "2/8 \"          %21.14e \" \"\\n\"",   /* e (undocumented in od), F */
 143        "4/4 \" %14.7e \" \"\\n\"",                             /* f */
 144        "4/4 \"       %08x \" \"\\n\"",                 /* H, X */
 145        "8/2 \"   %04x \" \"\\n\"",                             /* h, x */
 146        "4/4 \"    %11d \" \"\\n\"",                    /* I, L, l */
 147        "8/2 \" %6d \" \"\\n\"",                                /* i */
 148        "4/4 \"    %011o \" \"\\n\"",                   /* O */
 149};
 150
 151static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxv";
 152
 153static const char od_o2si[] ALIGN1 = {
 154        0, 1, 2, 3, 5,
 155        4, 6, 6, 7, 8,
 156        9, 0xa, 0xb, 0xa, 0xa,
 157        0xb, 1, 8, 9,
 158};
 159
 160int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 161int od_main(int argc, char **argv)
 162{
 163        int ch;
 164        int first = 1;
 165        char *p;
 166        dumper_t *dumper = alloc_dumper();
 167
 168        while ((ch = getopt(argc, argv, od_opts)) > 0) {
 169                if (ch == 'v') {
 170                        dumper->dump_vflag = ALL;
 171                } else if (((p = strchr(od_opts, ch)) != NULL) && (*p != '\0')) {
 172                        if (first) {
 173                                first = 0;
 174                                bb_dump_add(dumper, "\"%07.7_Ao\n\"");
 175                                bb_dump_add(dumper, "\"%07.7_ao  \"");
 176                        } else {
 177                                bb_dump_add(dumper, "\"         \"");
 178                        }
 179                        bb_dump_add(dumper, add_strings[(int)od_o2si[(p - od_opts)]]);
 180                } else {        /* P, p, s, w, or other unhandled */
 181                        bb_show_usage();
 182                }
 183        }
 184        if (!dumper->fshead) {
 185                bb_dump_add(dumper, "\"%07.7_Ao\n\"");
 186                bb_dump_add(dumper, "\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
 187        }
 188
 189        argc -= optind;
 190        argv += optind;
 191
 192        odoffset(dumper, argc, &argv);
 193
 194        return bb_dump_dump(dumper, argv);
 195}
 196#endif /* ENABLE_DESKTOP */
 197
 198/*-
 199 * Copyright (c) 1990 The Regents of the University of California.
 200 * All rights reserved.
 201 *
 202 * Redistribution and use in source and binary forms, with or without
 203 * modification, are permitted provided that the following conditions
 204 * are met:
 205 * 1. Redistributions of source code must retain the above copyright
 206 *    notice, this list of conditions and the following disclaimer.
 207 * 2. Redistributions in binary form must reproduce the above copyright
 208 *    notice, this list of conditions and the following disclaimer in the
 209 *    documentation and/or other materials provided with the distribution.
 210 * 3. Neither the name of the University nor the names of its contributors
 211 *    may be used to endorse or promote products derived from this software
 212 *    without specific prior written permission.
 213 *
 214 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
 215 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 216 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 217 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
 218 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 219 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 220 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 221 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 222 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
 223 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
 224 * SUCH DAMAGE.
 225 */
 226