diff options
Diffstat (limited to 'pack.c')
-rw-r--r-- | pack.c | 256 |
1 files changed, 147 insertions, 109 deletions
@@ -19,6 +19,36 @@ +(((x)>>24)&0xFF) \ +(((x)&0x0000FF00)<<8) \ +(((x)&0x00FF0000)>>8) ) + +#ifdef DYNAMIC_ENDIAN +#ifdef ntohs +#undef ntohs +#undef ntohl +#undef htons +#undef htonl +#endif +static int +endian() +{ + static int init = 0; + static int endian_value; + char *p; + + if (init) return endian_value; + init = 1; + p = (char*)&init; + return endian_value = p[0]?0:1; +} + +#define ntohs(x) (endian()?(x):swaps(x)) +#define ntohl(x) (endian()?(x):swapl(x)) +#define htons(x) (endian()?(x):swaps(x)) +#define htonl(x) (endian()?(x):swapl(x)) +#define htovs(x) (endian()?swaps(x):(x)) +#define htovl(x) (endian()?swapl(x):(x)) +#define vtohs(x) (endian()?swaps(x):(x)) +#define vtohl(x) (endian()?swapl(x):(x)) +#else #ifdef WORDS_BIGENDIAN #ifndef ntohs #define ntohs(x) (x) @@ -42,13 +72,15 @@ #define vtohs(x) (x) #define vtohl(x) (x) #endif +#endif extern VALUE cString, cArray; +#ifndef atof double atof(); +#endif static char *toofew = "too few arguments"; -int strtoul(); static void encodes(); static VALUE @@ -58,11 +90,11 @@ pack_pack(ary, fmt) { static char *nul10 = "\0\0\0\0\0\0\0\0\0\0"; static char *spc10 = " "; - char *p, *pend; + UCHAR *p, *pend; VALUE res, from; char type; int items, len, idx; - char *ptr; + UCHAR *ptr; int plen; Check_Type(fmt, T_STRING); @@ -84,7 +116,7 @@ pack_pack(ary, fmt) p++; } else if (isdigit(*p)) { - len = strtoul(p, &p, 10); + len = strtoul(p, (char**)&p, 10); } else { len = 1; @@ -117,13 +149,10 @@ pack_pack(ary, fmt) str_cat(res, ptr, plen); len -= plen; while (len >= 10) { - if (type == 'A') - str_cat(res, spc10, 10); - else - str_cat(res, nul10, 10); + str_cat(res, (type == 'A')?spc10:nul10, 10); len -= 10; } - str_cat(res, nul10, len); + str_cat(res, (type == 'A')?spc10:nul10, len); } break; @@ -290,7 +319,7 @@ pack_pack(ary, fmt) case 'n': while (len-- > 0) { - short s; + unsigned short s; from = NEXTFROM; if (NIL_P(from)) s = 0; @@ -304,7 +333,7 @@ pack_pack(ary, fmt) case 'N': while (len-- > 0) { - long l; + unsigned long l; from = NEXTFROM; if (NIL_P(from)) l = 0; @@ -316,6 +345,34 @@ pack_pack(ary, fmt) } break; + case 'v': + while (len-- > 0) { + unsigned short s; + + from = NEXTFROM; + if (NIL_P(from)) s = 0; + else { + s = NUM2INT(from); + } + s = htovs(s); + str_cat(res, &s, sizeof(short)); + } + break; + + case 'V': + while (len-- > 0) { + unsigned long l; + + from = NEXTFROM; + if (NIL_P(from)) l = 0; + else { + l = NUM2INT(from); + } + l = htovl(l); + str_cat(res, &l, sizeof(long)); + } + break; + case 'f': case 'F': while (len-- > 0) { @@ -356,34 +413,6 @@ pack_pack(ary, fmt) } break; - case 'v': - while (len-- > 0) { - short s; - - from = NEXTFROM; - if (NIL_P(from)) s = 0; - else { - s = NUM2INT(from); - } - s = htovs(s); - str_cat(res, &s, sizeof(short)); - } - break; - - case 'V': - while (len-- > 0) { - long l; - - from = NEXTFROM; - if (NIL_P(from)) l = 0; - else { - l = NUM2INT(from); - } - l = htovl(l); - str_cat(res, &l, sizeof(long)); - } - break; - case 'x': grow: while (len >= 10) { @@ -445,11 +474,11 @@ pack_pack(ary, fmt) static void encodes(str, s, len) struct RString *str; - char *s; + UCHAR *s; int len; { char hunk[4]; - char *p, *pend; + UCHAR *p, *pend; *hunk = len + ' '; str_cat(str, hunk, 1); @@ -477,8 +506,8 @@ pack_unpack(str, fmt) struct RString *str, *fmt; { static char *hexdigits = "0123456789abcdef0123456789ABCDEFx"; - char *s, *send; - char *p, *pend; + UCHAR *s, *send; + UCHAR *p, *pend; VALUE ary; char type; int len; @@ -498,7 +527,7 @@ pack_unpack(str, fmt) p++; } else if (isdigit(*p)) { - len = strtoul(p, &p, 10); + len = strtoul(p, (char**)&p, 10); } else { len = (type != '@'); @@ -512,14 +541,19 @@ pack_unpack(str, fmt) case 'A': if (len > send - s) len = send - s; { - char *t = s + len - 1; + int end = len; + UCHAR *t = s + len - 1; while (t >= s) { if (*t != ' ' && *t != '\0') break; t--; len--; } + ary_push(ary, str_new(s, len)); + s += end; } + break; + case 'a': if (len > send - s) len = send - s; ary_push(ary, str_new(s, len)); @@ -529,50 +563,51 @@ pack_unpack(str, fmt) case 'b': { VALUE bitstr; - char *t; + UCHAR *t; int bits, i; if (p[-1] == '*' || len > (send - s) * 8) len = (send - s) * 8; - ary_push(ary, bitstr = str_new(0, len + 1)); + bits = 0; + ary_push(ary, bitstr = str_new(0, len)); t = RSTRING(bitstr)->ptr; for (i=0; i<len; i++) { if (i & 7) bits >>= 1; else bits = *s++; *t++ = (bits & 1) ? '1' : '0'; } - *t = '\0'; } break; case 'B': { VALUE bitstr; - char *t; + UCHAR *t; int bits, i; if (p[-1] == '*' || len > (send - s) * 8) len = (send - s) * 8; - ary_push(ary, bitstr = str_new(0, len + 1)); + bits = 0; + ary_push(ary, bitstr = str_new(0, len)); t = RSTRING(bitstr)->ptr; for (i=0; i<len; i++) { if (i & 7) bits <<= 1; else bits = *s++; *t++ = (bits & 128) ? '1' : '0'; } - *t = '\0'; } break; case 'h': { VALUE bitstr; - char *t; + UCHAR *t; int bits, i; if (p[-1] == '*' || len > (send - s) * 2) len = (send - s) * 2; - ary_push(ary, bitstr = str_new(0, len + 1)); + bits = 0; + ary_push(ary, bitstr = str_new(0, len)); t = RSTRING(bitstr)->ptr; for (i=0; i<len; i++) { if (i & 1) @@ -581,19 +616,19 @@ pack_unpack(str, fmt) bits = *s++; *t++ = hexdigits[bits & 15]; } - *t = '\0'; } break; case 'H': { VALUE bitstr; - char *t; + UCHAR *t; int bits, i; if (p[-1] == '*' || len > (send - s) * 2) len = (send - s) * 2; - ary_push(ary, bitstr = str_new(0, len + 1)); + bits = 0; + ary_push(ary, bitstr = str_new(0, len)); t = RSTRING(bitstr)->ptr; for (i=0; i<len; i++) { if (i & 1) @@ -602,7 +637,6 @@ pack_unpack(str, fmt) bits = *s++; *t++ = hexdigits[(bits >> 4) & 15]; } - *t = '\0'; } break; @@ -611,9 +645,7 @@ pack_unpack(str, fmt) len = send - s; while (len-- > 0) { int c = *s++; -#ifdef __CHAR_UNSIGNED__ if (c > (char)127) c-=256; -#endif ary_push(ary, INT2FIX(c)); } break; @@ -622,7 +654,7 @@ pack_unpack(str, fmt) if (len > send - s) len = send - s; while (len-- > 0) { - unsigned char c = *s++; + UCHAR c = *s++; ary_push(ary, INT2FIX(c)); } break; @@ -639,12 +671,12 @@ pack_unpack(str, fmt) break; case 'S': - if (len >= (send - s) / sizeof(unsigned short)) - len = (send - s) / sizeof(unsigned short); + if (len >= (send - s) / sizeof(short)) + len = (send - s) / sizeof(short); while (len-- > 0) { unsigned short tmp; - memcpy(&tmp, s, sizeof(unsigned short)); - s += sizeof(unsigned short); + memcpy(&tmp, s, sizeof(short)); + s += sizeof(short); ary_push(ary, INT2FIX(tmp)); } break; @@ -661,12 +693,12 @@ pack_unpack(str, fmt) break; case 'I': - if (len >= (send - s) / sizeof(unsigned int)) - len = (send - s) / sizeof(unsigned int); + if (len >= (send - s) / sizeof(int)) + len = (send - s) / sizeof(int); while (len-- > 0) { unsigned int tmp; - memcpy(&tmp, s, sizeof(unsigned int)); - s += sizeof(unsigned int); + memcpy(&tmp, s, sizeof(int)); + s += sizeof(int); ary_push(ary, int2inum(tmp)); } break; @@ -683,13 +715,13 @@ pack_unpack(str, fmt) break; case 'L': - if (len >= (send - s) / sizeof(unsigned long)) - len = (send - s) / sizeof(unsigned long); + if (len >= (send - s) / sizeof(long)) + len = (send - s) / sizeof(long); while (len-- > 0) { unsigned long tmp; - memcpy(&tmp, s, sizeof(unsigned long)); - s += sizeof(unsigned long); - ary_push(ary, int2inum(tmp)); + memcpy(&tmp, s, sizeof(long)); + s += sizeof(long); + ary_push(ary, uint2inum(tmp)); } break; @@ -697,11 +729,11 @@ pack_unpack(str, fmt) if (len >= (send - s) / sizeof(short)) len = (send - s) / sizeof(short); while (len-- > 0) { - short tmp; + unsigned short tmp; memcpy(&tmp, s, sizeof(short)); s += sizeof(short); tmp = ntohs(tmp); - ary_push(ary, int2inum(tmp)); + ary_push(ary, uint2inum(tmp)); } break; @@ -709,16 +741,40 @@ pack_unpack(str, fmt) if (len >= (send - s) / sizeof(long)) len = (send - s) / sizeof(long); while (len-- > 0) { - long tmp; + unsigned long tmp; memcpy(&tmp, s, sizeof(long)); s += sizeof(long); tmp = ntohl(tmp); - ary_push(ary, int2inum(tmp)); + ary_push(ary, uint2inum(tmp)); + } + break; + + case 'v': + if (len >= (send - s) / sizeof(short)) + len = (send - s) / sizeof(short); + while (len-- > 0) { + unsigned short tmp; + memcpy(&tmp, s, sizeof(short)); + s += sizeof(short); + tmp = vtohs(tmp); + ary_push(ary, uint2inum(tmp)); + } + break; + + case 'V': + if (len >= (send - s) / sizeof(long)) + len = (send - s) / sizeof(long); + while (len-- > 0) { + unsigned long tmp; + memcpy(&tmp, s, sizeof(long)); + s += sizeof(long); + tmp = vtohl(tmp); + ary_push(ary, uint2inum(tmp)); } break; - case 'F': case 'f': + case 'F': if (len >= (send - s) / sizeof(float)) len = (send - s) / sizeof(float); while (len-- > 0) { @@ -741,34 +797,10 @@ pack_unpack(str, fmt) } break; - case 'v': - if (len >= (send - s) / sizeof(short)) - len = (send - s) / sizeof(short); - while (len-- > 0) { - short tmp; - memcpy(&tmp, s, sizeof(short)); - s += sizeof(short); - tmp = vtohs(tmp); - ary_push(ary, int2inum(tmp)); - } - break; - - case 'V': - if (len >= (send - s) / sizeof(long)) - len = (send - s) / sizeof(long); - while (len-- > 0) { - long tmp; - memcpy(&tmp, s, sizeof(long)); - s += sizeof(long); - tmp = vtohl(tmp); - ary_push(ary, int2inum(tmp)); - } - break; - case 'u': { VALUE str = str_new(0, (send - s)*3/4); - char *ptr = RSTRING(str)->ptr; + UCHAR *ptr = RSTRING(str)->ptr; int total = 0; while (s < send && *s > ' ' && *s < 'a') { @@ -778,8 +810,14 @@ pack_unpack(str, fmt) hunk[3] = '\0'; len = (*s++ - ' ') & 077; total += len; + if (total > RSTRING(str)->len) { + len -= total - RSTRING(str)->len; + total = RSTRING(str)->len; + } while (len > 0) { + int mlen = len > 3 ? 3 : len; + if (s < send && *s >= ' ') a = (*s++ - ' ') & 077; else @@ -799,13 +837,13 @@ pack_unpack(str, fmt) hunk[0] = a << 2 | b >> 4; hunk[1] = b << 4 | c >> 2; hunk[2] = c << 6 | d; - memcpy(ptr, hunk, len > 3 ? 3 : len); - ptr += 3; - len -= 3; + memcpy(ptr, hunk, mlen); + ptr += mlen; + len -= mlen; } - if (*s == '\n' || *s == '\r') - s++; - else if (s+1 == send || s[1] == '\n' || s[1] == '\r') + if (*s == '\r') s++; + if (*s == '\n') s++; + else if (s < send && (s+1 == send || s[1] == '\n')) s += 2; /* possible checksum byte */ } RSTRING(str)->len = total; |