source: rtems/cpukit/libmisc/shell/hexdump-odsyntax.c @ 88353c4

4.104.115
Last change on this file since 88353c4 was bab5c5fa, checked in by Joel Sherrill <joel.sherrill@…>, on 03/12/10 at 16:26:16

2010-03-12 Joel Sherrill <joel.sherrill@…>

  • ftpd/ftpd.c, httpd/asp.c, httpd/ejparse.c, httpd/emfdb.c, httpd/misc.c, httpd/um.c, httpd/webs.c, httpd/websuemf.c, libfs/src/dosfs/msdos_dir.c, libfs/src/dosfs/msdos_format.c, libfs/src/dosfs/msdos_misc.c, libfs/src/nfsclient/src/nfs.c, libmisc/capture/capture-cli.c, libmisc/monitor/mon-network.c, libmisc/shell/hexdump-odsyntax.c, libmisc/shell/main_ifconfig.c, libmisc/shell/shell.c, libmisc/shell/shell_makeargs.c, libmisc/uuid/parse.c, libnetworking/libc/gethostbydns.c, libnetworking/libc/gethostbyht.c, libnetworking/libc/gethostnamadr.c, libnetworking/libc/getnetnamadr.c, libnetworking/libc/inet_addr.c, libnetworking/libc/inet_network.c, libnetworking/libc/res_debug.c, libnetworking/libc/res_init.c, libnetworking/libc/res_query.c, libnetworking/rtems/rtems_mii_ioctl.c, score/src/objectgetnameasstring.c: Readdress use of ctype methods per recommendation from D.J. Delorie on the newlib mailing list. We should pass an unsigned char into these methods.
  • 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#ifndef lint
35#if 0
36static char sccsid[] = "@(#)odsyntax.c  8.2 (Berkeley) 5/4/95";
37#endif /* not lint */
38#include <sys/cdefs.h>
39__FBSDID("$FreeBSD: src/usr.bin/hexdump/odsyntax.c,v 1.17 2004/07/22 13:14:42 johan Exp $");
40#endif
41
42#include <sys/types.h>
43
44#include <ctype.h>
45#include <err.h>
46#include <errno.h>
47#include <float.h>
48#include <stdio.h>
49#include <stdlib.h>
50#include <string.h>
51#include <unistd.h>
52
53#include "hexdump.h"
54
55#define __need_getopt_newlib
56#include <getopt.h>
57
58#define PADDING "         "
59
60#if RTEMS_REMOVED
61int odmode;
62#endif
63
64static void odadd(rtems_shell_hexdump_globals*, const char *);
65static void odformat(rtems_shell_hexdump_globals*, const char *);
66static const char *odformatfp(rtems_shell_hexdump_globals*, char, const char *);
67static const char *odformatint(rtems_shell_hexdump_globals*, char, const char *);
68static void odoffset(rtems_shell_hexdump_globals*, int, char ***);
69static void odusage(rtems_shell_hexdump_globals*);
70
71void
72oldsyntax(rtems_shell_hexdump_globals* globals, int argc, char ***argvp)
73{
74        static char empty[] = "", padding[] = PADDING;
75        int ch;
76        char **argv, *end;
77
78  struct getopt_data getopt_reent;
79  memset(&getopt_reent, 0, sizeof(getopt_data));
80
81        /* Add initial (default) address format. -A may change it later. */
82#define TYPE_OFFSET     7
83        add(globals, "\"%07.7_Ao\n\"");
84        add(globals, "\"%07.7_ao  \"");
85
86        odmode = 1;
87        argv = *argvp;
88        while ((ch = getopt_r(argc, argv, "A:aBbcDdeFfHhIij:LlN:Oost:vXx", &getopt_reent)) != -1)
89                switch (ch) {
90                case 'A':
91                        switch (*optarg) {
92                        case 'd': case 'o': case 'x':
93                                fshead->nextfu->fmt[TYPE_OFFSET] = *optarg;
94                                fshead->nextfs->nextfu->fmt[TYPE_OFFSET] =
95                                    *optarg;
96                                break;
97                        case 'n':
98                                fshead->nextfu->fmt = empty;
99                                fshead->nextfs->nextfu->fmt = padding;
100                                break;
101                        default:
102                                errx(exit_jump, 1, "%s: invalid address base", optarg);
103                        }
104                        break;
105                case 'a':
106                        odformat(globals, "a");
107                        break;
108                case 'B':
109                case 'o':
110                        odformat(globals, "o2");
111                        break;
112                case 'b':
113                        odformat(globals, "o1");
114                        break;
115                case 'c':
116                        odformat(globals, "c");
117                        break;
118                case 'd':
119                        odformat(globals, "u2");
120                        break;
121                case 'D':
122                        odformat(globals, "u4");
123                        break;
124                case 'e':               /* undocumented in od */
125                case 'F':
126                        odformat(globals, "fD");
127                        break;
128                case 'f':
129                        odformat(globals, "fF");
130                        break;
131                case 'H':
132                case 'X':
133                        odformat(globals, "x4");
134                        break;
135                case 'h':
136                case 'x':
137                        odformat(globals, "x2");
138                        break;
139                case 'I':
140                case 'L':
141                case 'l':
142                        odformat(globals, "dL");
143                        break;
144                case 'i':
145                        odformat(globals, "dI");
146                        break;
147                case 'j':
148                        errno = 0;
149                        skip = strtoll(optarg, &end, 0);
150                        if (*end == 'b')
151                                skip *= 512;
152                        else if (*end == 'k')
153                                skip *= 1024;
154                        else if (*end == 'm')
155                                skip *= 1048576L;
156                        if (errno != 0 || skip < 0 || strlen(end) > 1)
157                                errx(exit_jump, 1, "%s: invalid skip amount", optarg);
158                        break;
159                case 'N':
160                        if ((length = atoi(optarg)) <= 0)
161                                errx(exit_jump, 1, "%s: invalid length", optarg);
162                        break;
163                case 'O':
164                        odformat(globals, "o4");
165                        break;
166                case 's':
167                        odformat(globals, "d2");
168                        break;
169                case 't':
170                        odformat(globals, optarg);
171                        break;
172                case 'v':
173                        vflag = ALL;
174                        break;
175                case '?':
176                default:
177                        odusage(globals);
178                }
179
180        if (fshead->nextfs->nextfs == NULL)
181                odformat(globals, "oS");
182
183        argc -= getopt_reent.optind;
184        *argvp += getopt_reent.optind;
185
186        if (argc)
187                odoffset(globals, argc, argvp);
188}
189
190static void
191odusage(rtems_shell_hexdump_globals* globals)
192{
193
194        fprintf(stderr,
195"usage: od [-aBbcDdeFfHhIiLlOosvXx] [-A base] [-j skip] [-N length] [-t type]\n");
196        fprintf(stderr,
197"          [[+]offset[.][Bb]] [file ...]\n");
198        exit(1);
199}
200
201static void
202odoffset(rtems_shell_hexdump_globals* globals, int argc, char ***argvp)
203{
204        char *p, *num, *end;
205        int base;
206
207        /*
208         * The offset syntax of od(1) was genuinely bizarre.  First, if
209         * it started with a plus it had to be an offset.  Otherwise, if
210         * there were at least two arguments, a number or lower-case 'x'
211         * followed by a number makes it an offset.  By default it was
212         * octal; if it started with 'x' or '0x' it was hex.  If it ended
213         * in a '.', it was decimal.  If a 'b' or 'B' was appended, it
214         * multiplied the number by 512 or 1024 byte units.  There was
215         * no way to assign a block count to a hex offset.
216         *
217         * We assume it's a file if the offset is bad.
218         */
219        p = argc == 1 ? (*argvp)[0] : (*argvp)[1];
220
221        if (*p != '+' && (argc < 2 ||
222            (!isdigit((unsigned char)p[0]) && (p[0] != 'x' || !isxdigit((unsigned char)p[1])))))
223                return;
224
225        base = 0;
226        /*
227         * skip over leading '+', 'x[0-9a-fA-f]' or '0x', and
228         * set base.
229         */
230        if (p[0] == '+')
231                ++p;
232        if (p[0] == 'x' && isxdigit((unsigned char)p[1])) {
233                ++p;
234                base = 16;
235        } else if (p[0] == '0' && p[1] == 'x') {
236                p += 2;
237                base = 16;
238        }
239
240        /* skip over the number */
241        if (base == 16)
242                for (num = p; isxdigit((unsigned char)*p); ++p);
243        else
244                for (num = p; isdigit((unsigned char)*p); ++p);
245
246        /* check for no number */
247        if (num == p)
248                return;
249
250        /* if terminates with a '.', base is decimal */
251        if (*p == '.') {
252                if (base)
253                        return;
254                base = 10;
255        }
256
257        skip = strtoll(num, &end, base ? base : 8);
258
259        /* if end isn't the same as p, we got a non-octal digit */
260        if (end != p) {
261                skip = 0;
262                return;
263        }
264
265        if (*p) {
266                if (*p == 'B') {
267                        skip *= 1024;
268                        ++p;
269                } else if (*p == 'b') {
270                        skip *= 512;
271                        ++p;
272                }
273        }
274
275        if (*p) {
276                skip = 0;
277                return;
278        }
279
280        /*
281         * If the offset uses a non-octal base, the base of the offset
282         * is changed as well.  This isn't pretty, but it's easy.
283         */
284        if (base == 16) {
285                fshead->nextfu->fmt[TYPE_OFFSET] = 'x';
286                fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'x';
287        } else if (base == 10) {
288                fshead->nextfu->fmt[TYPE_OFFSET] = 'd';
289                fshead->nextfs->nextfu->fmt[TYPE_OFFSET] = 'd';
290        }
291
292        /* Terminate file list. */
293        (*argvp)[1] = NULL;
294}
295
296static void
297odformat(rtems_shell_hexdump_globals* globals, const char *fmt)
298{
299        char fchar;
300
301        while (*fmt != '\0') {
302                switch ((fchar = *fmt++)) {
303                case 'a':
304                        odadd(globals, "16/1 \"%3_u \" \"\\n\"");
305                        break;
306                case 'c':
307                        odadd(globals, "16/1 \"%3_c \" \"\\n\"");
308                        break;
309                case 'o': case 'u': case 'd': case 'x':
310                        fmt = odformatint(globals, fchar, fmt);
311                        break;
312                case 'f':
313                        fmt = odformatfp(globals, fchar, fmt);
314                        break;
315                default:
316                        errx(exit_jump, 1, "%c: unrecognised format character", fchar);
317                }
318        }
319}
320#define __unused
321
322static const char *
323odformatfp(rtems_shell_hexdump_globals* globals, char fchar __unused, const char *fmt)
324{
325        size_t isize;
326        int digits;
327        char *end, *hdfmt;
328
329        isize = sizeof(double);
330        switch (*fmt) {
331        case 'F':
332                isize = sizeof(float);
333                fmt++;
334                break;
335        case 'D':
336                isize = sizeof(double);
337                fmt++;
338                break;
339        case 'L':
340                isize = sizeof(long double);
341                fmt++;
342                break;
343        default:
344                if (isdigit((unsigned char)*fmt)) {
345                        errno = 0;
346                        isize = (size_t)strtoul(fmt, &end, 10);
347                        if (errno != 0 || isize == 0)
348                                errx(exit_jump, 1, "%s: invalid size", fmt);
349                        fmt = (const char *)end;
350                }
351        }
352        if (isize == sizeof(float) ) {
353                digits = FLT_DIG;
354        } else if (isize == sizeof(double)) {
355                digits = DBL_DIG;
356        } else if (isize == sizeof(long double)) {
357                digits = LDBL_DIG;
358        } else {
359                errx(exit_jump, 1, "unsupported floating point size %zu",
360                        isize);
361        }
362
363        asprintf(&hdfmt, "%lu/%lu \" %%%d.%de \" \"\\n\"",
364            16UL / (u_long)isize, (u_long)isize, digits + 8, digits);
365        if (hdfmt == NULL)
366                err(exit_jump, 1, NULL);
367        odadd(globals, hdfmt);
368        free(hdfmt);
369
370        return (fmt);
371}
372
373static const char *
374odformatint(rtems_shell_hexdump_globals* globals, char fchar, const char *fmt)
375{
376        unsigned long long n;
377        size_t isize;
378        int digits;
379        char *end, *hdfmt;
380
381        isize = sizeof(int);
382        switch (*fmt) {
383        case 'C':
384                isize = sizeof(char);
385                fmt++;
386                break;
387        case 'I':
388                isize = sizeof(int);
389                fmt++;
390                break;
391        case 'L':
392                isize = sizeof(long);
393                fmt++;
394                break;
395        case 'S':
396                isize = sizeof(short);
397                fmt++;
398                break;
399        default:
400                if (isdigit((unsigned char)*fmt)) {
401                        errno = 0;
402                        isize = (size_t)strtoul(fmt, &end, 10);
403                        if (errno != 0 || isize == 0)
404                                errx(exit_jump, 1, "%s: invalid size", fmt);
405                        if (isize != sizeof(char) && isize != sizeof(short) &&
406                            isize != sizeof(int) && isize != sizeof(long))
407                                errx(exit_jump, 1, "unsupported int size %lu",
408                                    (u_long)isize);
409                        fmt = (const char *)end;
410                }
411        }
412
413        /*
414         * Calculate the maximum number of digits we need to
415         * fit the number. Overestimate for decimal with log
416         * base 8. We need one extra space for signed numbers
417         * to store the sign.
418         */
419        n = (1ULL << (8 * isize)) - 1;
420        digits = 0;
421        while (n != 0) {
422                digits++;
423                n >>= (fchar == 'x') ? 4 : 3;
424        }
425        if (fchar == 'd')
426                digits++;
427        asprintf(&hdfmt, "%lu/%lu \"%*s%%%s%d%c\" \"\\n\"",
428            16UL / (u_long)isize, (u_long)isize, (int)(4 * isize - digits),
429            "", (fchar == 'd' || fchar == 'u') ? "" : "0", digits, fchar);
430        if (hdfmt == NULL)
431                err(exit_jump, 1, NULL);
432        odadd(globals, hdfmt);
433        free(hdfmt);
434
435        return (fmt);
436}
437
438static void
439odadd(rtems_shell_hexdump_globals* globals, const char *fmt)
440{
441        static int needpad;
442
443        if (needpad)
444                add(globals, "\""PADDING"\"");
445        add(globals, fmt);
446        needpad = 1;
447}
Note: See TracBrowser for help on using the repository browser.