source: branches/2.2.2/mindi-busybox/libbb/dump.c @ 1247

Last change on this file since 1247 was 821, checked in by Bruno Cornec, 14 years ago

Addition of busybox 1.2.1 as a mindi-busybox new package
This should avoid delivering binary files in mindi not built there (Fedora and Debian are quite serious about that)

File size: 19.1 KB
Line 
1/*
2 * Support code for the hexdump and od applets,
3 * based on code from util-linux v 2.11l
4 *
5 * Copyright (c) 1989
6 *  The Regents of the University of California.  All rights reserved.
7 *
8 * Licensed under GPLv2 or later, see file LICENSE in this tarball for details.
9 *
10 * Original copyright notice is retained at the end of this file.
11 */
12
13#include "libbb.h"
14#include <string.h>
15#include <unistd.h>
16#include <ctype.h>      /* for isdigit() */
17#include "dump.h"
18
19enum _vflag bb_dump_vflag = FIRST;
20FS *bb_dump_fshead;             /* head of format strings */
21static FU *endfu;
22static char **_argv;
23static off_t savaddress;    /* saved address/offset in stream */
24static off_t eaddress;  /* end address */
25static off_t address;   /* address/offset in stream */
26off_t bb_dump_skip;             /* bytes to skip */
27static int exitval;         /* final exit value */
28int bb_dump_blocksize;          /* data block size */
29int bb_dump_length = -1;        /* max bytes to read */
30
31static const char index_str[] = ".#-+ 0123456789";
32
33static const char size_conv_str[] =
34"\x1\x4\x4\x4\x4\x4\x4\x8\x8\x8\x8\010cdiouxXeEfgG";
35
36static const char lcc[] = "diouxX";
37
38int bb_dump_size(FS * fs)
39{
40    register FU *fu;
41    register int bcnt, cur_size;
42    register char *fmt;
43    const char *p;
44    int prec;
45
46    /* figure out the data block bb_dump_size needed for each format unit */
47    for (cur_size = 0, fu = fs->nextfu; fu; fu = fu->nextfu) {
48        if (fu->bcnt) {
49            cur_size += fu->bcnt * fu->reps;
50            continue;
51        }
52        for (bcnt = prec = 0, fmt = fu->fmt; *fmt; ++fmt) {
53            if (*fmt != '%')
54                continue;
55            /*
56             * bb_dump_skip any special chars -- save precision in
57             * case it's a %s format.
58             */
59            while (strchr(index_str + 1, *++fmt));
60            if (*fmt == '.' && isdigit(*++fmt)) {
61                prec = atoi(fmt);
62                while (isdigit(*++fmt));
63            }
64            if (!(p = strchr(size_conv_str + 12, *fmt))) {
65                if (*fmt == 's') {
66                    bcnt += prec;
67                } else if (*fmt == '_') {
68                    ++fmt;
69                    if ((*fmt == 'c') || (*fmt == 'p') || (*fmt == 'u')) {
70                        bcnt += 1;
71                    }
72                }
73            } else {
74                bcnt += size_conv_str[p - (size_conv_str + 12)];
75            }
76        }
77        cur_size += bcnt * fu->reps;
78    }
79    return (cur_size);
80}
81
82static void rewrite(FS * fs)
83{
84    enum { NOTOKAY, USEBCNT, USEPREC } sokay;
85    PR *pr, **nextpr = NULL;
86    FU *fu;
87    char *p1, *p2, *p3;
88    char savech, *fmtp;
89    const char *byte_count_str;
90    int nconv, prec = 0;
91
92    for (fu = fs->nextfu; fu; fu = fu->nextfu) {
93        /*
94         * break each format unit into print units; each
95         * conversion character gets its own.
96         */
97        for (nconv = 0, fmtp = fu->fmt; *fmtp; nextpr = &pr->nextpr) {
98            /* NOSTRICT */
99            /* DBU:[dvae@cray.com] calloc so that forward ptrs start out NULL*/
100            pr = xzalloc(sizeof(PR));
101            if (!fu->nextpr)
102                fu->nextpr = pr;
103            /* ignore nextpr -- its unused inside the loop and is
104             * uninitialized 1st time thru.
105             */
106
107            /* bb_dump_skip preceding text and up to the next % sign */
108            for (p1 = fmtp; *p1 && *p1 != '%'; ++p1);
109
110            /* only text in the string */
111            if (!*p1) {
112                pr->fmt = fmtp;
113                pr->flags = F_TEXT;
114                break;
115            }
116
117            /*
118             * get precision for %s -- if have a byte count, don't
119             * need it.
120             */
121            if (fu->bcnt) {
122                sokay = USEBCNT;
123                /* bb_dump_skip to conversion character */
124                for (++p1; strchr(index_str, *p1); ++p1);
125            } else {
126                /* bb_dump_skip any special chars, field width */
127                while (strchr(index_str + 1, *++p1));
128                if (*p1 == '.' && isdigit(*++p1)) {
129                    sokay = USEPREC;
130                    prec = atoi(p1);
131                    while (isdigit(*++p1));
132                } else
133                    sokay = NOTOKAY;
134            }
135
136            p2 = p1 + 1;    /* set end pointer */
137
138            /*
139             * figure out the byte count for each conversion;
140             * rewrite the format as necessary, set up blank-
141             * pbb_dump_adding for end of data.
142             */
143
144            if (*p1 == 'c') {
145                pr->flags = F_CHAR;
146            DO_BYTE_COUNT_1:
147                byte_count_str = "\001";
148            DO_BYTE_COUNT:
149                if (fu->bcnt) {
150                    do {
151                        if (fu->bcnt == *byte_count_str) {
152                            break;
153                        }
154                    } while (*++byte_count_str);
155                }
156                /* Unlike the original, output the remainder of the format string. */
157                if (!*byte_count_str) {
158                    bb_error_msg_and_die("bad byte count for conversion character %s.", p1);
159                }
160                pr->bcnt = *byte_count_str;
161            } else if (*p1 == 'l') {
162                ++p2;
163                ++p1;
164            DO_INT_CONV:
165                {
166                    const char *e;
167                    if (!(e = strchr(lcc, *p1))) {
168                        goto DO_BAD_CONV_CHAR;
169                    }
170                    pr->flags = F_INT;
171                    if (e > lcc + 1) {
172                        pr->flags = F_UINT;
173                    }
174                    byte_count_str = "\004\002\001";
175                    goto DO_BYTE_COUNT;
176                }
177                /* NOTREACHED */
178            } else if (strchr(lcc, *p1)) {
179                goto DO_INT_CONV;
180            } else if (strchr("eEfgG", *p1)) {
181                pr->flags = F_DBL;
182                byte_count_str = "\010\004";
183                goto DO_BYTE_COUNT;
184            } else if (*p1 == 's') {
185                pr->flags = F_STR;
186                if (sokay == USEBCNT) {
187                    pr->bcnt = fu->bcnt;
188                } else if (sokay == USEPREC) {
189                    pr->bcnt = prec;
190                } else {    /* NOTOKAY */
191                    bb_error_msg_and_die("%%s requires a precision or a byte count.");
192                }
193            } else if (*p1 == '_') {
194                ++p2;
195                switch (p1[1]) {
196                case 'A':
197                    endfu = fu;
198                    fu->flags |= F_IGNORE;
199                    /* FALLTHROUGH */
200                case 'a':
201                    pr->flags = F_ADDRESS;
202                    ++p2;
203                    if ((p1[2] != 'd') && (p1[2] != 'o') && (p1[2] != 'x')) {
204                        goto DO_BAD_CONV_CHAR;
205                    }
206                    *p1 = p1[2];
207                    break;
208                case 'c':
209                    pr->flags = F_C;
210                    /* *p1 = 'c';   set in conv_c */
211                    goto DO_BYTE_COUNT_1;
212                case 'p':
213                    pr->flags = F_P;
214                    *p1 = 'c';
215                    goto DO_BYTE_COUNT_1;
216                case 'u':
217                    pr->flags = F_U;
218                    /* *p1 = 'c';   set in conv_u */
219                    goto DO_BYTE_COUNT_1;
220                default:
221                    goto DO_BAD_CONV_CHAR;
222                }
223            } else {
224            DO_BAD_CONV_CHAR:
225                bb_error_msg_and_die("bad conversion character %%%s.\n", p1);
226            }
227
228            /*
229             * copy to PR format string, set conversion character
230             * pointer, update original.
231             */
232            savech = *p2;
233            p1[1] = '\0';
234            pr->fmt = bb_xstrdup(fmtp);
235            *p2 = savech;
236            pr->cchar = pr->fmt + (p1 - fmtp);
237
238            /* DBU:[dave@cray.com] w/o this, trailing fmt text, space is lost.
239             * Skip subsequent text and up to the next % sign and tack the
240             * additional text onto fmt: eg. if fmt is "%x is a HEX number",
241             * we lose the " is a HEX number" part of fmt.
242             */
243            for (p3 = p2; *p3 && *p3 != '%'; p3++);
244            if (p3 > p2)
245            {
246                savech = *p3;
247                *p3 = '\0';
248                pr->fmt = xrealloc(pr->fmt, strlen(pr->fmt)+(p3-p2)+1);
249                strcat(pr->fmt, p2);
250                *p3 = savech;
251                p2 = p3;
252            }
253
254            fmtp = p2;
255
256            /* only one conversion character if byte count */
257            if (!(pr->flags & F_ADDRESS) && fu->bcnt && nconv++) {
258                bb_error_msg_and_die("byte count with multiple conversion characters.\n");
259            }
260        }
261        /*
262         * if format unit byte count not specified, figure it out
263         * so can adjust rep count later.
264         */
265        if (!fu->bcnt)
266            for (pr = fu->nextpr; pr; pr = pr->nextpr)
267                fu->bcnt += pr->bcnt;
268    }
269    /*
270     * if the format string interprets any data at all, and it's
271     * not the same as the bb_dump_blocksize, and its last format unit
272     * interprets any data at all, and has no iteration count,
273     * repeat it as necessary.
274     *
275     * if, rep count is greater than 1, no trailing whitespace
276     * gets output from the last iteration of the format unit.
277     */
278    for (fu = fs->nextfu;; fu = fu->nextfu) {
279        if (!fu->nextfu && fs->bcnt < bb_dump_blocksize &&
280            !(fu->flags & F_SETREP) && fu->bcnt)
281            fu->reps += (bb_dump_blocksize - fs->bcnt) / fu->bcnt;
282        if (fu->reps > 1) {
283            for (pr = fu->nextpr;; pr = pr->nextpr)
284                if (!pr->nextpr)
285                    break;
286            for (p1 = pr->fmt, p2 = NULL; *p1; ++p1)
287                p2 = isspace(*p1) ? p1 : NULL;
288            if (p2)
289                pr->nospace = p2;
290        }
291        if (!fu->nextfu)
292            break;
293    }
294}
295
296static void do_skip(char *fname, int statok)
297{
298    struct stat sbuf;
299
300    if (statok) {
301        if (fstat(STDIN_FILENO, &sbuf)) {
302            bb_perror_msg_and_die("%s", fname);
303        }
304        if ((!(S_ISCHR(sbuf.st_mode) ||
305               S_ISBLK(sbuf.st_mode) ||
306               S_ISFIFO(sbuf.st_mode))) && bb_dump_skip >= sbuf.st_size) {
307            /* If bb_dump_size valid and bb_dump_skip >= size */
308            bb_dump_skip -= sbuf.st_size;
309            address += sbuf.st_size;
310            return;
311        }
312    }
313    if (fseek(stdin, bb_dump_skip, SEEK_SET)) {
314        bb_perror_msg_and_die("%s", fname);
315    }
316    savaddress = address += bb_dump_skip;
317    bb_dump_skip = 0;
318}
319
320static int next(char **argv)
321{
322    static int done;
323    int statok;
324
325    if (argv) {
326        _argv = argv;
327        return (1);
328    }
329    for (;;) {
330        if (*_argv) {
331            if (!(freopen(*_argv, "r", stdin))) {
332                bb_perror_msg("%s", *_argv);
333                exitval = 1;
334                ++_argv;
335                continue;
336            }
337            statok = done = 1;
338        } else {
339            if (done++)
340                return (0);
341            statok = 0;
342        }
343        if (bb_dump_skip)
344            do_skip(statok ? *_argv : "stdin", statok);
345        if (*_argv)
346            ++_argv;
347        if (!bb_dump_skip)
348            return (1);
349    }
350    /* NOTREACHED */
351}
352
353static unsigned char *get(void)
354{
355    static int ateof = 1;
356    static unsigned char *curp=NULL, *savp; /*DBU:[dave@cray.com]initialize curp */
357    register int n;
358    int need, nread;
359    unsigned char *tmpp;
360
361    if (!curp) {
362        address = (off_t)0; /*DBU:[dave@cray.com] initialize,initialize..*/
363        curp = (unsigned char *) xmalloc(bb_dump_blocksize);
364        savp = (unsigned char *) xmalloc(bb_dump_blocksize);
365    } else {
366        tmpp = curp;
367        curp = savp;
368        savp = tmpp;
369        address = savaddress += bb_dump_blocksize;
370    }
371    for (need = bb_dump_blocksize, nread = 0;;) {
372        /*
373         * if read the right number of bytes, or at EOF for one file,
374         * and no other files are available, zero-pad the rest of the
375         * block and set the end flag.
376         */
377        if (!bb_dump_length || (ateof && !next((char **) NULL))) {
378            if (need == bb_dump_blocksize) {
379                return ((unsigned char *) NULL);
380            }
381            if (bb_dump_vflag != ALL && !memcmp(curp, savp, nread)) {
382                if (bb_dump_vflag != DUP) {
383                    printf("*\n");
384                }
385                return ((unsigned char *) NULL);
386            }
387            memset((char *) curp + nread, 0, need);
388            eaddress = address + nread;
389            return (curp);
390        }
391        n = fread((char *) curp + nread, sizeof(unsigned char),
392                  bb_dump_length == -1 ? need : MIN(bb_dump_length, need), stdin);
393        if (!n) {
394            if (ferror(stdin)) {
395                bb_perror_msg("%s", _argv[-1]);
396            }
397            ateof = 1;
398            continue;
399        }
400        ateof = 0;
401        if (bb_dump_length != -1) {
402            bb_dump_length -= n;
403        }
404        if (!(need -= n)) {
405            if (bb_dump_vflag == ALL || bb_dump_vflag == FIRST
406                || memcmp(curp, savp, bb_dump_blocksize)) {
407                if (bb_dump_vflag == DUP || bb_dump_vflag == FIRST) {
408                    bb_dump_vflag = WAIT;
409                }
410                return (curp);
411            }
412            if (bb_dump_vflag == WAIT) {
413                printf("*\n");
414            }
415            bb_dump_vflag = DUP;
416            address = savaddress += bb_dump_blocksize;
417            need = bb_dump_blocksize;
418            nread = 0;
419        } else {
420            nread += n;
421        }
422    }
423}
424
425static void bpad(PR * pr)
426{
427    char *p1, *p2;
428
429    /*
430     * remove all conversion flags; '-' is the only one valid
431     * with %s, and it's not useful here.
432     */
433    pr->flags = F_BPAD;
434    *pr->cchar = 's';
435    for (p1 = pr->fmt; *p1 != '%'; ++p1);
436    for (p2 = ++p1; *p1 && strchr(" -0+#", *p1); ++p1)
437        if (pr->nospace) pr->nospace--;
438    while ((*p2++ = *p1++) != 0);
439}
440
441static const char conv_str[] =
442    "\0\\0\0"
443    "\007\\a\0"             /* \a */
444    "\b\\b\0"
445    "\f\\b\0"
446    "\n\\n\0"
447    "\r\\r\0"
448    "\t\\t\0"
449    "\v\\v\0"
450    "\0";
451
452
453static void conv_c(PR * pr, unsigned char * p)
454{
455    const char *str = conv_str;
456    char buf[10];
457
458    do {
459        if (*p == *str) {
460            ++str;
461            goto strpr;
462        }
463        str += 4;
464    } while (*str);
465
466    if (isprint(*p)) {
467        *pr->cchar = 'c';
468        (void) printf(pr->fmt, *p);
469    } else {
470        sprintf(buf, "%03o", (int) *p);
471        str = buf;
472      strpr:
473        *pr->cchar = 's';
474        printf(pr->fmt, str);
475    }
476}
477
478static void conv_u(PR * pr, unsigned char * p)
479{
480    static const char list[] =
481        "nul\0soh\0stx\0etx\0eot\0enq\0ack\0bel\0"
482        "bs\0_ht\0_lf\0_vt\0_ff\0_cr\0_so\0_si\0_"
483        "dle\0dcl\0dc2\0dc3\0dc4\0nak\0syn\0etb\0"
484        "can\0em\0_sub\0esc\0fs\0_gs\0_rs\0_us";
485
486    /* od used nl, not lf */
487    if (*p <= 0x1f) {
488        *pr->cchar = 's';
489        printf(pr->fmt, list + (4 * (int)*p));
490    } else if (*p == 0x7f) {
491        *pr->cchar = 's';
492        printf(pr->fmt, "del");
493    } else if (isprint(*p)) {
494        *pr->cchar = 'c';
495        printf(pr->fmt, *p);
496    } else {
497        *pr->cchar = 'x';
498        printf(pr->fmt, (int) *p);
499    }
500}
501
502static void display(void)
503{
504/*  extern FU *endfu; */
505    register FS *fs;
506    register FU *fu;
507    register PR *pr;
508    register int cnt;
509    register unsigned char *bp;
510
511    off_t saveaddress;
512    unsigned char savech = 0, *savebp;
513
514    while ((bp = get()) != NULL) {
515        for (fs = bb_dump_fshead, savebp = bp, saveaddress = address; fs;
516             fs = fs->nextfs, bp = savebp, address = saveaddress) {
517            for (fu = fs->nextfu; fu; fu = fu->nextfu) {
518                if (fu->flags & F_IGNORE) {
519                    break;
520                }
521                for (cnt = fu->reps; cnt; --cnt) {
522                    for (pr = fu->nextpr; pr; address += pr->bcnt,
523                         bp += pr->bcnt, pr = pr->nextpr) {
524                        if (eaddress && address >= eaddress &&
525                            !(pr->flags & (F_TEXT | F_BPAD))) {
526                            bpad(pr);
527                        }
528                        if (cnt == 1 && pr->nospace) {
529                            savech = *pr->nospace;
530                            *pr->nospace = '\0';
531                        }
532/*                      PRINT; */
533                        switch (pr->flags) {
534                        case F_ADDRESS:
535                            printf(pr->fmt, (unsigned int) address);
536                            break;
537                        case F_BPAD:
538                            printf(pr->fmt, "");
539                            break;
540                        case F_C:
541                            conv_c(pr, bp);
542                            break;
543                        case F_CHAR:
544                            printf(pr->fmt, *bp);
545                            break;
546                        case F_DBL:{
547                            double dval;
548                            float fval;
549
550                            switch (pr->bcnt) {
551                            case 4:
552                                memmove((char *) &fval, (char *) bp,
553                                      sizeof(fval));
554                                printf(pr->fmt, fval);
555                                break;
556                            case 8:
557                                memmove((char *) &dval, (char *) bp,
558                                      sizeof(dval));
559                                printf(pr->fmt, dval);
560                                break;
561                            }
562                            break;
563                        }
564                        case F_INT:{
565                            int ival;
566                            short sval;
567
568                            switch (pr->bcnt) {
569                            case 1:
570                                printf(pr->fmt, (int) *bp);
571                                break;
572                            case 2:
573                                memmove((char *) &sval, (char *) bp,
574                                      sizeof(sval));
575                                printf(pr->fmt, (int) sval);
576                                break;
577                            case 4:
578                                memmove((char *) &ival, (char *) bp,
579                                      sizeof(ival));
580                                printf(pr->fmt, ival);
581                                break;
582                            }
583                            break;
584                        }
585                        case F_P:
586                            printf(pr->fmt, isprint(*bp) ? *bp : '.');
587                            break;
588                        case F_STR:
589                            printf(pr->fmt, (char *) bp);
590                            break;
591                        case F_TEXT:
592                            printf(pr->fmt);
593                            break;
594                        case F_U:
595                            conv_u(pr, bp);
596                            break;
597                        case F_UINT:{
598                            unsigned int ival;
599                            unsigned short sval;
600
601                            switch (pr->bcnt) {
602                            case 1:
603                                printf(pr->fmt, (unsigned int) * bp);
604                                break;
605                            case 2:
606                                memmove((char *) &sval, (char *) bp,
607                                      sizeof(sval));
608                                printf(pr->fmt, (unsigned int) sval);
609                                break;
610                            case 4:
611                                memmove((char *) &ival, (char *) bp,
612                                      sizeof(ival));
613                                printf(pr->fmt, ival);
614                                break;
615                            }
616                            break;
617                        }
618                        }
619                        if (cnt == 1 && pr->nospace) {
620                            *pr->nospace = savech;
621                        }
622                    }
623                }
624            }
625        }
626    }
627    if (endfu) {
628        /*
629         * if eaddress not set, error or file bb_dump_size was multiple of
630         * bb_dump_blocksize, and no partial block ever found.
631         */
632        if (!eaddress) {
633            if (!address) {
634                return;
635            }
636            eaddress = address;
637        }
638        for (pr = endfu->nextpr; pr; pr = pr->nextpr) {
639            switch (pr->flags) {
640            case F_ADDRESS:
641                (void) printf(pr->fmt, (unsigned int) eaddress);
642                break;
643            case F_TEXT:
644                (void) printf(pr->fmt);
645                break;
646            }
647        }
648    }
649}
650
651int bb_dump_dump(char **argv)
652{
653    register FS *tfs;
654
655    /* figure out the data block bb_dump_size */
656    for (bb_dump_blocksize = 0, tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
657        tfs->bcnt = bb_dump_size(tfs);
658        if (bb_dump_blocksize < tfs->bcnt) {
659            bb_dump_blocksize = tfs->bcnt;
660        }
661    }
662    /* rewrite the rules, do syntax checking */
663    for (tfs = bb_dump_fshead; tfs; tfs = tfs->nextfs) {
664        rewrite(tfs);
665    }
666
667    next(argv);
668    display();
669
670    return (exitval);
671}
672
673void bb_dump_add(const char *fmt)
674{
675    const char *p;
676    char *p1;
677    char *p2;
678    static FS **nextfs;
679    FS *tfs;
680    FU *tfu, **nextfu;
681    const char *savep;
682
683    /* start new linked list of format units */
684    tfs = xzalloc(sizeof(FS)); /*DBU:[dave@cray.com] start out NULL */
685    if (!bb_dump_fshead) {
686        bb_dump_fshead = tfs;
687    } else {
688        *nextfs = tfs;
689    }
690    nextfs = &tfs->nextfs;
691    nextfu = &tfs->nextfu;
692
693    /* take the format string and break it up into format units */
694    for (p = fmt;;) {
695        /* bb_dump_skip leading white space */
696        p = skip_whitespace(p);
697        if (!*p) {
698            break;
699        }
700
701        /* allocate a new format unit and link it in */
702        /* NOSTRICT */
703        /* DBU:[dave@cray.com] calloc so that forward pointers start out NULL */
704        tfu = xzalloc(sizeof(FU));
705        *nextfu = tfu;
706        nextfu = &tfu->nextfu;
707        tfu->reps = 1;
708
709        /* if leading digit, repetition count */
710        if (isdigit(*p)) {
711            for (savep = p; isdigit(*p); ++p);
712            if (!isspace(*p) && *p != '/') {
713                bb_error_msg_and_die("bad format {%s}", fmt);
714            }
715            /* may overwrite either white space or slash */
716            tfu->reps = atoi(savep);
717            tfu->flags = F_SETREP;
718            /* bb_dump_skip trailing white space */
719            p = skip_whitespace(++p);
720        }
721
722        /* bb_dump_skip slash and trailing white space */
723        if (*p == '/') {
724            p = skip_whitespace(++p);
725        }
726
727        /* byte count */
728        if (isdigit(*p)) {
729            for (savep = p; isdigit(*p); ++p);
730            if (!isspace(*p)) {
731                bb_error_msg_and_die("bad format {%s}", fmt);
732            }
733            tfu->bcnt = atoi(savep);
734            /* bb_dump_skip trailing white space */
735            p = skip_whitespace(++p);
736        }
737
738        /* format */
739        if (*p != '"') {
740            bb_error_msg_and_die("bad format {%s}", fmt);
741        }
742        for (savep = ++p; *p != '"';) {
743            if (*p++ == 0) {
744                bb_error_msg_and_die("bad format {%s}", fmt);
745            }
746        }
747        tfu->fmt = xmalloc(p - savep + 1);
748        strncpy(tfu->fmt, savep, p - savep);
749        tfu->fmt[p - savep] = '\0';
750/*      escape(tfu->fmt); */
751
752        p1 = tfu->fmt;
753
754        /* alphabetic escape sequences have to be done in place */
755        for (p2 = p1;; ++p1, ++p2) {
756            if (!*p1) {
757                *p2 = *p1;
758                break;
759            }
760            if (*p1 == '\\') {
761                const char *cs = conv_str + 4;
762                ++p1;
763                *p2 = *p1;
764                do {
765                    if (*p1 == cs[2]) {
766                        *p2 = cs[0];
767                        break;
768                    }
769                    cs += 4;
770                } while (*cs);
771            }
772        }
773
774        p++;
775    }
776}
777
778/*
779 * Copyright (c) 1989 The Regents of the University of California.
780 * All rights reserved.
781 *
782 * Redistribution and use in source and binary forms, with or without
783 * modification, are permitted provided that the following conditions
784 * are met:
785 * 1. Redistributions of source code must retain the above copyright
786 *    notice, this list of conditions and the following disclaimer.
787 * 2. Redistributions in binary form must reproduce the above copyright
788 *    notice, this list of conditions and the following disclaimer in the
789 *    documentation and/or other materials provided with the distribution.
790 * 3. Neither the name of the University nor the names of its contributors
791 *    may be used to endorse or promote products derived from this software
792 *    without specific prior written permission.
793 *
794 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
795 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
796 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
797 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
798 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
799 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
800 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
801 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
802 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
803 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
804 * SUCH DAMAGE.
805 */
Note: See TracBrowser for help on using the repository browser.