scc

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

pack.c (2171B)


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