scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

unpack.c (3020B)


      1 static char sccsid[] = "@(#) ./lib/scc/lunpack.c";
      2 
      3 #include <ctype.h>
      4 #include <stdarg.h>
      5 #include <stdio.h>
      6 #include <stdlib.h>
      7 
      8 #include <scc/mach.h>
      9 #include "libmach.h"
     10 
     11 static int
     12 lunpack(unsigned char *src, char *fmt, va_list va)
     13 {
     14 	unsigned char *bp, *cp;
     15 	unsigned short *sp;
     16 	unsigned s;
     17 	unsigned long *lp, l;
     18 	unsigned long long *qp, q;
     19 	int n;
     20 
     21 	bp = src;
     22 	while (*fmt) {
     23 		switch (*fmt++) {
     24 		case '\'':
     25 			n = atoi(fmt);
     26 			while (isdigit(*fmt))
     27 				fmt++;
     28 			cp = va_arg(va, unsigned char *);
     29 			while (n--)
     30 				*cp++ = *bp++;
     31 			break;
     32 		case 'c':
     33 			cp = va_arg(va, unsigned char *);
     34 			*cp = *bp++;
     35 			break;
     36 		case 's':
     37 			sp = va_arg(va, unsigned short *);
     38 			s =  (unsigned) *bp++;
     39 			s |= (unsigned) *bp++ << 8;
     40 			*sp = s;
     41 			break;
     42 		case 'l':
     43 			lp = va_arg(va, unsigned long *);
     44 			l = (unsigned long) *bp++;
     45 			l |= (unsigned long) *bp++ << 8;
     46 			l |= (unsigned long) *bp++ << 16;
     47 			l |= (unsigned long) *bp++ << 24;
     48 			*lp = l;
     49 			break;
     50 		case 'q':
     51 			qp = va_arg(va, unsigned long long *);
     52 			q = (unsigned long long) *bp++;
     53 			q |= (unsigned long long) *bp++ << 8;
     54 			q |= (unsigned long long) *bp++ << 16;
     55 			q |= (unsigned long long) *bp++ << 24;
     56 			q |= (unsigned long long) *bp++ << 32;
     57 			q |= (unsigned long long) *bp++ << 40;
     58 			q |= (unsigned long long) *bp++ << 48;
     59 			q |= (unsigned long long) *bp++ << 56;
     60 			*qp = q;
     61 			break;
     62 		default:
     63 			va_end(va);
     64 			return -1;
     65 		}
     66 	}
     67 
     68 	return bp - src;
     69 }
     70 
     71 static int
     72 bunpack(unsigned char *src, char *fmt, va_list va)
     73 {
     74 	unsigned char *bp, *cp;
     75 	unsigned short *sp;
     76 	unsigned s;
     77 	unsigned long *lp, l;
     78 	unsigned long long *qp, q;
     79 	int n;
     80 
     81 	bp = src;
     82 	while (*fmt) {
     83 		switch (*fmt++) {
     84 		case '\'':
     85 			n = atoi(fmt);
     86 			while (isdigit(*fmt))
     87 				fmt++;
     88 			cp = va_arg(va, unsigned char *);
     89 			while (n--)
     90 				*cp++ = *bp++;
     91 			break;
     92 		case 'c':
     93 			cp = va_arg(va, unsigned char *);
     94 			*cp = *bp++;
     95 			break;
     96 		case 's':
     97 			sp = va_arg(va, unsigned short *);
     98 			s =  (unsigned) *bp++ << 8;
     99 			s |= (unsigned) *bp++;
    100 			*sp = s;
    101 			break;
    102 		case 'l':
    103 			lp = va_arg(va, unsigned long *);
    104 			l =  (unsigned long) *bp++ << 24;
    105 			l |= (unsigned long) *bp++ << 16;
    106 			l |= (unsigned long) *bp++ << 8;
    107 			l |= (unsigned long) *bp++;
    108 			*lp = l;
    109 			break;
    110 		case 'q':
    111 			qp = va_arg(va, unsigned long long *);
    112 			q =  (unsigned long long) *bp++ << 56;
    113 			q |= (unsigned long long) *bp++ << 48;
    114 			q |= (unsigned long long) *bp++ << 40;
    115 			q |= (unsigned long long) *bp++ << 32;
    116 			q |= (unsigned long long) *bp++ << 24;
    117 			q |= (unsigned long long) *bp++ << 16;
    118 			q |= (unsigned long long) *bp++ << 8;
    119 			q |= (unsigned long long) *bp++;
    120 			*qp = q;
    121 			break;
    122 		default:
    123 			va_end(va);
    124 			return -1;
    125 		}
    126 	}
    127 
    128 	return bp - src;
    129 }
    130 
    131 int
    132 unpack(int order, unsigned char *src, char *fmt, ...)
    133 {
    134 	int r;
    135         int (*fn)(unsigned char *dst, char *fmt, va_list va);
    136         va_list va;
    137 
    138         va_start(va, fmt);
    139         fn = (order == LITTLE_ENDIAN) ? lunpack : bunpack;
    140         r = (*fn)(src, fmt, va);
    141         va_end(va);
    142 
    143         return r;
    144 }