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