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