source: rtems/cpukit/libmisc/shell/hexdump-odsyntax.c @ 9a77af8

4.104.115
Last change on this file since 9a77af8 was 9a77af8, checked in by Ralf Corsepius <ralf.corsepius@…>, on Mar 26, 2010 at 5:18:43 PM

Add HAVE_CONFIG_H support to let files receive configure defines.

  • Property mode set to 100644
File size: 10.7 KB
Line 
1/*-
2 * Copyright (c) 1990, 1993
3 *      The Regents of the University of California.  All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 *    notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 *    notice, this list of conditions and the following disclaimer in the
12 *    documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 *    must display the following acknowledgement:
15 *      This product includes software developed by the University of
16 *      California, Berkeley and its contributors.
17 * 4. Neither the name of the University nor the names of its contributors
18 *    may be used to endorse or promote products derived from this software
19 *    without specific prior written permission.
20 *
21 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
32 */
33
34#ifdef HAVE_CONFIG_H
35#include "config.h"
36#endif
37
38#ifndef lint
39#if 0
40static char sccsid[] = "@(#)odsyntax.c  8.2 (Berkeley) 5/4/95";
41#endif /* not lint */
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: src/usr.bin/hexdump/odsyntax.c,v 1.17 2004/07/22 13:14:42 johan Exp $");
44#endif
45
46#include <sys/types.h>
47
48#include <ctype.h>
49#include <err.h>
50#include <errno.h>
51#include <float.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56
57#include "hexdump.h"
58
59#define __need_getopt_newlib
60#include <getopt.h>
61
62#define PADDING "         "
63
64#if RTEMS_REMOVED
65int odmode;
66#endif
67
68static void odadd(rtems_shell_hexdump_globals*, const char *);
69static void odformat(rtems_shell_hexdump_globals*, const char *);
70static const char *odformatfp(rtems_shell_hexdump_globals*, char, const char *);
71static const char *odformatint(rtems_shell_hexdump_globals*, char, const char *);
72static void odoffset(rtems_shell_hexdump_globals*, int, char ***);
73static void odusage(rtems_shell_hexdump_globals*);
74
75void
76oldsyntax(rtems_shell_hexdump_globals* globals, int argc, char ***argvp)
77{
78        static char empty[] = "", padding[] = PADDING;
79        int ch;
80        char **argv, *end;
81
82  struct getopt_data getopt_reent;
83  memset(&getopt_reent, 0, sizeof(getopt_data));
84
85        /* Add initial (default) address format. -A may change it later. */
86#define TYPE_OFFSET     7
87        add(globals, "\"%07.7_Ao\n\"");
88        add(globals, "\"%07.7_ao  \"");
89
90        odmode = 1;
91        argv = *argvp;
92        while ((ch = getopt_r(argc, argv, "A:aBbcDdeFfHhIij:LlN:Oost:vXx", &getopt_reent)) != -1)
93                switch (ch) {
94                case 'A':
95                        switch (*optarg) {
96                        case 'd': case 'o': case 'x':
97                                fshead->nextfu->fmt[TYPE_OFFSET] = *optarg;
98                                fshead->nextfs->nextfu->fmt[TYPE_OFFSET] =
99                                    *optarg;
100                                break;
101                        case 'n':
102                                fshead->nextfu->fmt = empty;
103                                fshead->nextfs->nextfu->fmt = padding;
104                                break;
105                        default:
106                                errx(exit_jump, 1, "%s: invalid address base", optarg);
107                        }
108                        break;
109                case 'a':
110                        odformat(globals, "a");
111                        break;
112                case 'B':
113                case 'o':
114                        odformat(globals, "o2");
115                        break;
116                case 'b':
117                        odformat(globals, "o1");
118                        break;
119                case 'c':
120                        odformat(globals, "c");
121                        break;
122                case 'd':
123                        odformat(globals, "u2");
124                        break;
125                case 'D':
126                        odformat(globals, "u4");
127                        break;
128                case 'e':               /* undocumented in od */
129                case 'F':
130                        odformat(globals, "fD");
131                        break;
132                case 'f':
133                        odformat(globals, "fF");
134                        break;
135                case 'H':
136                case 'X':
137                        odformat(globals, "x4");
138                        break;
139                case 'h':
140                case 'x':
141                        odformat(globals, "x2");
142                        break;
143                case 'I':
144                case 'L':
145                case 'l':
146                        odformat(globals, "dL");
147                        break;
148                case 'i':
149                        odformat(globals, "dI");
150                        break;
151                case 'j':
152                        errno = 0;
153                        skip = strtoll(optarg, &end, 0);
154                        if (*end == 'b')
155                                skip *= 512;
156                        else if (*end == 'k')
157                                skip *= 1024;
158                        else if (*end == 'm')
159                                skip *= 1048576L;
160                        if (errno != 0 || skip < 0 || strlen(end) > 1)
161                                errx(exit_jump, 1, "%s: invalid skip amount", optarg);
162                        break;
163                case 'N':
164                        if ((length = atoi(optarg)) <= 0)
165                                errx(exit_jump, 1, "%s: invalid length", optarg);
166                        break;
167                case 'O':
168                        odformat(globals, "o4");
169                        break;
170                case 's':
171                        odformat(globals, "d2");
172                        break;
173                case 't':
174                        odformat(globals, optarg);
175                        break;
176                case 'v':
177                        vflag = ALL;
178                        break;
179                case '?':
180                default:
181                        odusage(globals);
182                }
183
184        if (fshead->nextfs->nextfs == NULL)
185                odformat(globals, "oS");
186
187        argc -= getopt_reent.optind;
188        *argvp += getopt_reent.optind;
189
190        if (argc)
191                odoffset(globals, argc, argvp);
192}
193
194static void
195odusage(rtems_shell_hexdump_globals* globals)
196{
197
198        fprintf(stderr,
199"usage: od [-aBbcDdeFfHhIiLlOosvXx] [-A base] [-j skip] [-N length] [-t type]\n");
200        fprintf(stderr,
201"          [[+]offset[.][Bb]] [file ...]\n");
202        exit(1);
203}
204
205static void
206odoffset(rtems_shell_hexdump_globals* globals, int argc, char ***argvp)
207{
208        char *p, *num, *end;
209        int base;
210
211        /*
212         * The offset syntax of od(1) was genuinely bizarre.  First, if
213         * it started with a plus it had to be an offset.  Otherwise, if
214         * there were at least two arguments, a number or lower-case 'x'
215         * followed by a number makes it an offset.  By default it was
216         * octal; if it started with 'x' or '0x' it was hex.  If it ended
217         * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
218         * multiplied the number by 512 or 1024 byte units.  There was
219         * no way to assign a block count to a hex offset.
220         *
221         * We assume it's a file if the offset is bad.
222         */
223        p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
224
225        if (*p != '+' && (argc < 2 ||
226            (!isdigit((unsigned char)p[0]) && (p[0] != 'x' || !isxdigit((unsigned char)p[1])))))
227                return;
228
229        base = 0;
230        /*
231         * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
232         * set base.
233         */
234        if (p[0] == '+')
235                ++p;
236        if (p[0] == 'x' && isxdigit((unsigned char)p[1])) {
237                ++p;
238                base = 16;
239        } else if (p[0] == '0' && p[1] == 'x') {
240                p += 2;
241                base = 16;
242        }
243
244        /* skip over the number */
245        if (base == 16)
246                for (num = p; isxdigit((unsigned char)*p); ++p);
247        else
248                for (num = p; isdigit((unsigned char)*p); ++p);
249
250        /* check for no number */
251        if (num == p)
252                return;
253
254        /* if terminates with a '.', base is decimal */
255        if (*p == '.') {
256                if (base)
257                        return;
258                base = 10;
259        }
260
261        skip = strtoll(num, &end, base ? base : 8);
262
263        /* if end isn't the same as p, we got a non-octal digit */
264        if (end != p) {
265                skip = 0;
266                return;
267        }
268
269        if (*p) {
270                if (*p == 'B') {
271                        skip *= 1024;
272                        ++p;
273                } else if (*p == 'b') {
274                        skip *= 512;
275                        ++p;
276                }
277        }
278
279        if (*p) {
280                skip = 0;
281                return;
282        }
283
284        /*
285         * If the offset uses a non-octal base, the base of the offset
286         * is changed as well.  This isn't pretty, but it's easy.
287         */
288        if (base == 16) {
289                fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
290                fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
291        } else if (base == 10) {
292                fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
293                fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
294        }
295
296        /* Terminate file list. */
297        (*argvp)[1] = NULL;
298}
299
300static void
301odformat(rtems_shell_hexdump_globals* globals, const char *fmt)
302{
303        char fchar;
304
305        while (*fmt != '\0') {
306                switch ((fchar = *fmt++)) {
307                case 'a':
308                        odadd(globals, "16/1 \"%3_u \" \"\\n\"");
309                        break;
310                case 'c':
311                        odadd(globals, "16/1 \"%3_c \" \"\\n\"");
312                        break;
313                case 'o': case 'u': case 'd': case 'x':
314                        fmt = odformatint(globals, fchar, fmt);
315                        break;
316                case 'f':
317                        fmt = odformatfp(globals, fchar, fmt);
318                        break;
319                default:
320                        errx(exit_jump, 1, "%c: unrecognised format character", fchar);
321                }
322        }
323}
324#define __unused
325
326static const char *
327odformatfp(rtems_shell_hexdump_globals* globals, char fchar __unused, const char *fmt)
328{
329        size_t isize;
330        int digits;
331        char *end, *hdfmt;
332
333        isize = sizeof(double);
334        switch (*fmt) {
335        case 'F':
336                isize = sizeof(float);
337                fmt++;
338                break;
339        case 'D':
340                isize = sizeof(double);
341                fmt++;
342                break;
343        case 'L':
344                isize = sizeof(long double);
345                fmt++;
346                break;
347        default:
348                if (isdigit((unsigned char)*fmt)) {
349                        errno = 0;
350                        isize = (size_t)strtoul(fmt, &end, 10);
351                        if (errno != 0 || isize == 0)
352                                errx(exit_jump, 1, "%s: invalid size", fmt);
353                        fmt = (const char *)end;
354                }
355        }
356        if (isize == sizeof(float) ) {
357                digits = FLT_DIG;
358        } else if (isize == sizeof(double)) {
359                digits = DBL_DIG;
360        } else if (isize == sizeof(long double)) {
361                digits = LDBL_DIG;
362        } else {
363                errx(exit_jump, 1, "unsupported floating point size %zu",
364                        isize);
365        }
366
367        asprintf(&hdfmt, "%lu/%lu \" %%%d.%de \" \"\\n\"",
368            16UL / (u_long)isize, (u_long)isize, digits + 8, digits);
369        if (hdfmt == NULL)
370                err(exit_jump, 1, NULL);
371        odadd(globals, hdfmt);
372        free(hdfmt);
373
374        return (fmt);
375}
376
377static const char *
378odformatint(rtems_shell_hexdump_globals* globals, char fchar, const char *fmt)
379{
380        unsigned long long n;
381        size_t isize;
382        int digits;
383        char *end, *hdfmt;
384
385        isize = sizeof(int);
386        switch (*fmt) {
387        case 'C':
388                isize = sizeof(char);
389                fmt++;
390                break;
391        case 'I':
392                isize = sizeof(int);
393                fmt++;
394                break;
395        case 'L':
396                isize = sizeof(long);
397                fmt++;
398                break;
399        case 'S':
400                isize = sizeof(short);
401                fmt++;
402                break;
403        default:
404                if (isdigit((unsigned char)*fmt)) {
405                        errno = 0;
406                        isize = (size_t)strtoul(fmt, &end, 10);
407                        if (errno != 0 || isize == 0)
408                                errx(exit_jump, 1, "%s: invalid size", fmt);
409                        if (isize != sizeof(char) && isize != sizeof(short) &&
410                            isize != sizeof(int) && isize != sizeof(long))
411                                errx(exit_jump, 1, "unsupported int size %lu",
412                                    (u_long)isize);
413                        fmt = (const char *)end;
414                }
415        }
416
417        /*
418         * Calculate the maximum number of digits we need to
419         * fit the number. Overestimate for decimal with log
420         * base 8. We need one extra space for signed numbers
421         * to store the sign.
422         */
423        n = (1ULL << (8 * isize)) - 1;
424        digits = 0;
425        while (n != 0) {
426                digits++;
427                n >>= (fchar == 'x') ? 4 : 3;
428        }
429        if (fchar == 'd')
430                digits++;
431        asprintf(&hdfmt, "%lu/%lu \"%*s%%%s%d%c\" \"\\n\"",
432            16UL / (u_long)isize, (u_long)isize, (int)(4 * isize - digits),
433            "", (fchar == 'd' || fchar == 'u') ? "" : "0", digits, fchar);
434        if (hdfmt == NULL)
435                err(exit_jump, 1, NULL);
436        odadd(globals, hdfmt);
437        free(hdfmt);
438
439        return (fmt);
440}
441
442static void
443odadd(rtems_shell_hexdump_globals* globals, const char *fmt)
444{
445        static int needpad;
446
447        if (needpad)
448                add(globals, "\""PADDING"\"");
449        add(globals, fmt);
450        needpad = 1;
451}
Note: See TracBrowser for help on using the repository browser.