source: rtems/cpukit/libmisc/shell/hexdump-display.c @ 0c1cb8a

4.104.115
Last change on this file since 0c1cb8a was 0893220, checked in by Ralf Corsepius <ralf.corsepius@…>, on 11/29/09 at 12:12:39

Whitespace removal.

  • Property mode set to 100644
File size: 9.6 KB
Line 
1/*
2 * Copyright (c) 1989, 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[] = "@(#)display.c   8.1 (Berkeley) 6/6/93";
37#endif
38#endif /* not lint */
39#if 0
40#include <sys/cdefs.h>
41__FBSDID("$FreeBSD: src/usr.bin/hexdump/display.c,v 1.22 2004/08/04 02:47:32 tjr Exp $");
42#endif
43
44#include <sys/param.h>
45#include <sys/stat.h>
46
47#include <stdint.h>
48
49#include <ctype.h>
50#include <err.h>
51#include <errno.h>
52#include <stdio.h>
53#include <stdlib.h>
54#include <string.h>
55#include <unistd.h>
56#include "hexdump.h"
57
58#if RTEMS_REMOVED
59enum _vflag vflag = FIRST;
60
61static off_t address;                   /* address/offset in stream */
62static off_t eaddress;                  /* end address */
63#endif
64
65static void print(rtems_shell_hexdump_globals*, PR *, u_char *);
66
67void
68display(rtems_shell_hexdump_globals* globals)
69{
70        FS *fs;
71        FU *fu;
72        PR *pr;
73        int cnt;
74        u_char *bp;
75        off_t saveaddress;
76        u_char savech, *savebp;
77
78        savech = 0;
79        while ((bp = get(globals)))
80                for (fs = fshead, savebp = bp, saveaddress = address; fs;
81                fs = fs->nextfs, bp = savebp, address = saveaddress)
82                    for (fu = fs->nextfu; fu; fu = fu->nextfu) {
83                        if (fu->flags&F_IGNORE)
84                                break;
85                        for (cnt = fu->reps; cnt; --cnt)
86                            for (pr = fu->nextpr; pr; address += pr->bcnt,
87                                bp += pr->bcnt, pr = pr->nextpr) {
88                                    if (eaddress && address >= eaddress &&
89                                        !(pr->flags & (F_TEXT|F_BPAD)))
90                                            bpad(pr);
91                                    if (cnt == 1 && pr->nospace) {
92                                        savech = *pr->nospace;
93                                        *pr->nospace = '\0';
94                                    }
95                                    print(globals, pr, bp);
96                                    if (cnt == 1 && pr->nospace)
97                                        *pr->nospace = savech;
98                            }
99                    }
100        if (endfu) {
101                /*
102                 * If eaddress not set, error or file size was multiple of
103                 * blocksize, and no partial block ever found.
104                 */
105                if (!eaddress) {
106                        if (!address)
107                                return;
108                        eaddress = address;
109                }
110                for (pr = endfu->nextpr; pr; pr = pr->nextpr)
111                        switch(pr->flags) {
112                        case F_ADDRESS:
113                                (void)printf(pr->fmt, (quad_t)eaddress);
114                                break;
115                        case F_TEXT:
116                                (void)printf("%s", pr->fmt);
117                                break;
118                        }
119        }
120}
121
122static void
123print(rtems_shell_hexdump_globals* globals, PR *pr, u_char *bp)
124{
125        long double ldbl;
126           double f8;
127            float f4;
128          int16_t s2;
129           int8_t s8;
130          int32_t s4;
131        u_int16_t u2;
132        u_int32_t u4;
133        u_int64_t u8;
134
135        switch(pr->flags) {
136        case F_ADDRESS:
137                (void)printf(pr->fmt, (quad_t)address);
138                break;
139        case F_BPAD:
140                (void)printf(pr->fmt, "");
141                break;
142        case F_C:
143                conv_c(globals, pr, bp, eaddress ? eaddress - address :
144                    blocksize - address % blocksize);
145                break;
146        case F_CHAR:
147                (void)printf(pr->fmt, *bp);
148                break;
149        case F_DBL:
150                switch(pr->bcnt) {
151                case 4:
152                        bcopy(bp, &f4, sizeof(f4));
153                        (void)printf(pr->fmt, f4);
154                        break;
155                case 8:
156                        bcopy(bp, &f8, sizeof(f8));
157                        (void)printf(pr->fmt, f8);
158                        break;
159                default:
160                        if (pr->bcnt == sizeof(long double)) {
161                                bcopy(bp, &ldbl, sizeof(ldbl));
162                                (void)printf(pr->fmt, ldbl);
163                        }
164                        break;
165                }
166                break;
167        case F_INT:
168                switch(pr->bcnt) {
169                case 1:
170                        (void)printf(pr->fmt, (quad_t)(signed char)*bp);
171                        break;
172                case 2:
173                        bcopy(bp, &s2, sizeof(s2));
174                        (void)printf(pr->fmt, (quad_t)s2);
175                        break;
176                case 4:
177                        bcopy(bp, &s4, sizeof(s4));
178                        (void)printf(pr->fmt, (quad_t)s4);
179                        break;
180                case 8:
181                        bcopy(bp, &s8, sizeof(s8));
182                        (void)printf(pr->fmt, s8);
183                        break;
184                }
185                break;
186        case F_P:
187                (void)printf(pr->fmt, isprint(*bp) ? *bp : '.');
188                break;
189        case F_STR:
190                (void)printf(pr->fmt, (char *)bp);
191                break;
192        case F_TEXT:
193                (void)printf("%s", pr->fmt);
194                break;
195        case F_U:
196                conv_u(globals, pr, bp);
197                break;
198        case F_UINT:
199                switch(pr->bcnt) {
200                case 1:
201                        (void)printf(pr->fmt, (u_quad_t)*bp);
202                        break;
203                case 2:
204                        bcopy(bp, &u2, sizeof(u2));
205                        (void)printf(pr->fmt, (u_quad_t)u2);
206                        break;
207                case 4:
208                        bcopy(bp, &u4, sizeof(u4));
209                        (void)printf(pr->fmt, (u_quad_t)u4);
210                        break;
211                case 8:
212                        bcopy(bp, &u8, sizeof(u8));
213                        (void)printf(pr->fmt, u8);
214                        break;
215                }
216                break;
217        }
218}
219
220void
221bpad(PR *pr)
222{
223        static char const *spec = " -0+#";
224        char *p1, *p2;
225
226        /*
227         * Remove all conversion flags; '-' is the only one valid
228         * with %s, and it's not useful here.
229         */
230        pr->flags = F_BPAD;
231        pr->cchar[0] = 's';
232        pr->cchar[1] = '\0';
233        for (p1 = pr->fmt; *p1 != '%'; ++p1);
234        for (p2 = ++p1; *p1 && index(spec, *p1); ++p1);
235        while ((*p2++ = *p1++));
236}
237
238static char **_argv;
239
240u_char *
241get(rtems_shell_hexdump_globals* globals)
242{
243#if RTEMS_REMOVED
244        static int ateof = 1;
245        static u_char *curp, *savp;
246#endif
247        int n;
248        int need, nread;
249        int valid_save = 0;
250        u_char *tmpp;
251
252        if (!curp) {
253                if ((curp = calloc(1, blocksize)) == NULL)
254                        err(exit_jump, 1, NULL);
255                if ((savp = calloc(1, blocksize)) == NULL)
256                        err(exit_jump, 1, NULL);
257        } else {
258                tmpp = curp;
259                curp = savp;
260                savp = tmpp;
261                address += blocksize;
262                valid_save = 1;
263        }
264        for (need = blocksize, nread = 0;;) {
265                /*
266                 * if read the right number of bytes, or at EOF for one file,
267                 * and no other files are available, zero-pad the rest of the
268                 * block and set the end flag.
269                 */
270                if (!length || (ateof && !next(globals, (char **)NULL))) {
271                        if (odmode && address < skip)
272                                errx(exit_jump, 1, "cannot skip past end of input");
273                        if (need == blocksize)
274                                return((u_char *)NULL);
275                        /*
276                         * XXX bcmp() is not quite right in the presence
277                         * of multibyte characters.
278                         */
279                        if (vflag != ALL &&
280                            valid_save &&
281                            bcmp(curp, savp, nread) == 0) {
282                                if (vflag != DUP)
283                                        (void)printf("*\n");
284                                return((u_char *)NULL);
285                        }
286                        bzero((char *)curp + nread, need);
287                        eaddress = address + nread;
288                        return(curp);
289                }
290                n = fread((char *)curp + nread, sizeof(u_char),
291                    length == -1 ? need : MIN(length, need), hdstdin);
292                if (!n) {
293                        if (ferror(hdstdin))
294                                warn("%s", _argv[-1]);
295                        ateof = 1;
296                        continue;
297                }
298                ateof = 0;
299                if (length != -1)
300                        length -= n;
301                if (!(need -= n)) {
302                        /*
303                         * XXX bcmp() is not quite right in the presence
304                         * of multibyte characters.
305                         */
306                        if (vflag == ALL || vflag == FIRST ||
307                            valid_save == 0 ||
308                            bcmp(curp, savp, blocksize) != 0) {
309                                if (vflag == DUP || vflag == FIRST)
310                                        vflag = WAIT;
311                                return(curp);
312                        }
313                        if (vflag == WAIT)
314                                (void)printf("*\n");
315                        vflag = DUP;
316                        address += blocksize;
317                        need = blocksize;
318                        nread = 0;
319                }
320                else
321                        nread += n;
322        }
323}
324
325size_t
326peek(rtems_shell_hexdump_globals* globals, u_char *buf, size_t nbytes)
327{
328        size_t n, nread;
329        int c;
330
331        if (length != -1 && nbytes > (unsigned int)length)
332                nbytes = length;
333        nread = 0;
334        while (nread < nbytes && (c = getchar()) != EOF) {
335                *buf++ = c;
336                nread++;
337        }
338        n = nread;
339        while (n-- > 0) {
340                c = *--buf;
341                ungetc(c, hdstdin);
342        }
343        return (nread);
344}
345
346int
347next(rtems_shell_hexdump_globals* globals, char **argv)
348{
349#if RTEMS_REMOVED
350        static int done;
351#endif
352        int statok;
353
354        if (argv) {
355                _argv = argv;
356                return(1);
357        }
358        for (;;) {
359                if (*_argv) {
360                        done = 1;
361      if (!hdstdin) {
362        hdstdin = malloc(sizeof(FILE));
363        if (!hdstdin)
364        {
365          errno = ENOMEM;
366          err(exit_jump, 1, "file name allocation");
367        }
368        memset (hdstdin, 0, sizeof(FILE));
369      }
370                        if (!(hdstdin = freopen(*_argv, "r", hdstdin))) {
371                                warn("%s", *_argv);
372                                exitval = 1;
373                                ++_argv;
374                                continue;
375                        }
376                        statok = 1;
377                } else {
378      errno = ECANCELED;
379      err(exit_jump, 1, "no file (stdin no supported)");
380                        if (done++)
381                                return(0);
382                        statok = 0;
383                }
384                if (skip)
385                        doskip(globals, statok ? *_argv : "stdin", statok);
386                if (*_argv)
387                        ++_argv;
388                if (!skip)
389                        return(1);
390        }
391        /* NOTREACHED */
392}
393
394void
395doskip(rtems_shell_hexdump_globals* globals, const char *fname, int statok)
396{
397        int cnt;
398        struct stat sb;
399
400        if (statok) {
401                if (fstat(fileno(hdstdin), &sb))
402                        err(exit_jump, 1, "%s", fname);
403    /* can seek block devices on RTEMS */
404                if (0 && S_ISREG(sb.st_mode) && skip >= sb.st_size) {
405                        address += sb.st_size;
406                        skip -= sb.st_size;
407                        return;
408                }
409                if (1 || S_ISREG(sb.st_mode)) {
410                        if (fseeko(hdstdin, skip, SEEK_SET))
411                                err(exit_jump, 1, "%s", fname);
412                        address += skip;
413                        skip = 0;
414                } else {
415                        for (cnt = 0; cnt < skip; ++cnt)
416                                if (getchar() == EOF)
417                                        break;
418                        address += cnt;
419                        skip -= cnt;
420                }
421        }
422}
Note: See TracBrowser for help on using the repository browser.