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