libbb: get rid of statics in dump.c; code shrinks a lot too
[platform/upstream/busybox.git] / coreutils / od.c
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
26 static void
27 odoffset(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
135 static 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
151 static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxv";
152
153 static 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
160 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
161 int 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  */