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