Initial public busybox upstream commit
[busybox4maemo] / 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 #include <getopt.h>
21
22 #include "dump.h"
23
24 #define isdecdigit(c) isdigit(c)
25 #define ishexdigit(c) (isxdigit)(c)
26
27 static void
28 odoffset(int argc, char ***argvp)
29 {
30         char *num, *p;
31         int base;
32         char *end;
33
34         /*
35          * The offset syntax of od(1) was genuinely bizarre.  First, if
36          * it started with a plus it had to be an offset.  Otherwise, if
37          * there were at least two arguments, a number or lower-case 'x'
38          * followed by a number makes it an offset.  By default it was
39          * octal; if it started with 'x' or '0x' it was hex.  If it ended
40          * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
41          * multiplied the number by 512 or 1024 byte units.  There was
42          * no way to assign a block count to a hex offset.
43          *
44          * We assumes it's a file if the offset is bad.
45          */
46         p = **argvp;
47
48         if (!p) {
49                 /* hey someone is probably piping to us ... */
50                 return;
51         }
52
53         if ((*p != '+')
54                 && (argc < 2
55                         || (!isdecdigit(p[0])
56                                 && ((p[0] != 'x') || !ishexdigit(p[1])))))
57                 return;
58
59         base = 0;
60         /*
61          * bb_dump_skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
62          * set base.
63          */
64         if (p[0] == '+')
65                 ++p;
66         if (p[0] == 'x' && ishexdigit(p[1])) {
67                 ++p;
68                 base = 16;
69         } else if (p[0] == '0' && p[1] == 'x') {
70                 p += 2;
71                 base = 16;
72         }
73
74         /* bb_dump_skip over the number */
75         if (base == 16)
76                 for (num = p; ishexdigit(*p); ++p);
77         else
78                 for (num = p; isdecdigit(*p); ++p);
79
80         /* check for no number */
81         if (num == p)
82                 return;
83
84         /* if terminates with a '.', base is decimal */
85         if (*p == '.') {
86                 if (base)
87                         return;
88                 base = 10;
89         }
90
91         bb_dump_skip = strtol(num, &end, base ? base : 8);
92
93         /* if end isn't the same as p, we got a non-octal digit */
94         if (end != p)
95                 bb_dump_skip = 0;
96         else {
97                 if (*p) {
98                         if (*p == 'b') {
99                                 bb_dump_skip *= 512;
100                                 ++p;
101                         } else if (*p == 'B') {
102                                 bb_dump_skip *= 1024;
103                                 ++p;
104                         }
105                 }
106                 if (*p)
107                         bb_dump_skip = 0;
108                 else {
109                         ++*argvp;
110                         /*
111                          * If the offset uses a non-octal base, the base of
112                          * the offset is changed as well.  This isn't pretty,
113                          * but it's easy.
114                          */
115 #define TYPE_OFFSET     7
116                         {
117                                 char x_or_d;
118                                 if (base == 16) {
119                                         x_or_d = 'x';
120                                         goto DO_X_OR_D;
121                                 }
122                                 if (base == 10) {
123                                         x_or_d = 'd';
124                                 DO_X_OR_D:
125                                         bb_dump_fshead->nextfu->fmt[TYPE_OFFSET]
126                                                 = bb_dump_fshead->nextfs->nextfu->fmt[TYPE_OFFSET]
127                                                 = x_or_d;
128                                 }
129                         }
130                 }
131         }
132 }
133
134 static const char *const add_strings[] = {
135         "16/1 \"%3_u \" \"\\n\"",                               /* a */
136         "8/2 \" %06o \" \"\\n\"",                               /* B, o */
137         "16/1 \"%03o \" \"\\n\"",                               /* b */
138         "16/1 \"%3_c \" \"\\n\"",                               /* c */
139         "8/2 \"  %05u \" \"\\n\"",                              /* d */
140         "4/4 \"     %010u \" \"\\n\"",                  /* D */
141         "2/8 \"          %21.14e \" \"\\n\"",   /* e (undocumented in od), F */
142         "4/4 \" %14.7e \" \"\\n\"",                             /* f */
143         "4/4 \"       %08x \" \"\\n\"",                 /* H, X */
144         "8/2 \"   %04x \" \"\\n\"",                             /* h, x */
145         "4/4 \"    %11d \" \"\\n\"",                    /* I, L, l */
146         "8/2 \" %6d \" \"\\n\"",                                /* i */
147         "4/4 \"    %011o \" \"\\n\"",                   /* O */
148 };
149
150 static const char od_opts[] ALIGN1 = "aBbcDdeFfHhIiLlOoXxv";
151
152 static const char od_o2si[] ALIGN1 = {
153         0, 1, 2, 3, 5,
154         4, 6, 6, 7, 8,
155         9, 0xa, 0xb, 0xa, 0xa,
156         0xb, 1, 8, 9,
157 };
158
159 int od_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
160 int od_main(int argc, char **argv)
161 {
162         int ch;
163         int first = 1;
164         char *p;
165         bb_dump_vflag = FIRST;
166         bb_dump_length = -1;
167
168         while ((ch = getopt(argc, argv, od_opts)) > 0) {
169                 if (ch == 'v') {
170                         bb_dump_vflag = ALL;
171                 } else if (((p = strchr(od_opts, ch)) != NULL) && (*p != '\0')) {
172                         if (first) {
173                                 first = 0;
174                                 bb_dump_add("\"%07.7_Ao\n\"");
175                                 bb_dump_add("\"%07.7_ao  \"");
176                         } else {
177                                 bb_dump_add("\"         \"");
178                         }
179                         bb_dump_add(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 (!bb_dump_fshead) {
185                 bb_dump_add("\"%07.7_Ao\n\"");
186                 bb_dump_add("\"%07.7_ao  \" 8/2 \"%06o \" \"\\n\"");
187         }
188
189         argc -= optind;
190         argv += optind;
191
192         odoffset(argc, &argv);
193
194         return bb_dump_dump(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  */