source: MondoRescue/trunk/mindi-busybox/libbb/dump.c@ 904

Last change on this file since 904 was 821, checked in by Bruno Cornec, 18 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.