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