/* source: dalan.c */ /* Copyright Gerhard Rieger */ /* Published under the GNU General Public License V.2, see file COPYING */ /* idea of a low level data description language. currently only a most primitive subset exists. */ #include "config.h" #include #include #if HAVE_STDBOOL_H #include #endif #include #include "dalan.h" /* test structure to find maximal alignment */ static struct { char a; long double b; } maxalign; /* test structure to find minimal alignment */ static struct { char a; char b; } minalign; /* test union to find kind of byte ordering */ static union { char a[2]; short b; } byteorder = { "01" }; struct dalan_opts_s dalan_opts = { sizeof(int), sizeof(short), sizeof(long), sizeof(char), sizeof(float), sizeof(double) } ; /* fill the dalan_opts structure with machine dependent defaults values. */ static void _dalan_dflts(struct dalan_opts_s *dlo) { dlo->c_int = sizeof(int); dlo->c_short = sizeof(short); dlo->c_long = sizeof(long); dlo->c_char = sizeof(char); dlo->c_float = sizeof(float); dlo->c_double = sizeof(double); dlo->maxalign = (char *)&maxalign.b-&maxalign.a; dlo->minalign = &minalign.b-&minalign.a; dlo->byteorder = (byteorder.b!=7711); } /* allocate a new dalan_opts structure, fills it with machine dependent defaults values, and returns the pointer. */ struct dalan_opts_s *dalan_props(void) { struct dalan_opts_s *dlo; dlo = malloc(sizeof(struct dalan_opts_s)); if (dlo == NULL) { return NULL; } _dalan_dflts(dlo); return dlo; } void dalan_init(void) { _dalan_dflts(&dalan_opts); } /* read data description from line, write result to data; do not write so much data that *p exceeds n ! p must be initialized to 0. return 0 on success, -1 if the data was cut due to n limit, 1 if a syntax error occurred *p is a global data counter; especially it must be used when calculating alignment. On successful return from the function *p must be actual! */ int dalan(const char *line, char *data, size_t *p, size_t n) { int align, mask, i, x; size_t p1 = *p; char c; /*fputs(line, stderr); fputc('\n', stderr);*/ while (c = *line++) { switch (c) { case ' ': case '\t': case '\r': case '\n': break; case ',': align = 2; while (*line == ',') { align <<= 1; ++line; } mask = align - 1; /* create the bitmask */ i = (align - (p1 & mask)) & mask; while (i && p1= n) { *p = p1; return -1; } data[p1++] = c; continue; } if (c == '"') break; } break; case '\'': switch (c = *line++) { case '\0': fputs("unterminated character\n", stderr); return 1; case '\'': fputs("error in character\n", stderr); return 1; case '\\': if (!(c = *line++)) { fputs("continuation line not implemented\n", stderr); return 1; } switch (c) { case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case 'f': c = '\f'; break; case 'b': c = '\b'; break; case 'a': c = '\a'; break; #if 0 case 'e': c = '\e'; break; #else case 'e': c = '\033'; break; #endif } /* PASSTHROUGH */ default: if (p1 >= n) { *p = p1; return -1; } data[p1++] = c; break; } if (*line != '\'') { fputs("error in character termination\n", stderr); *p = p1; return 1; } ++line; break; #if LATER case '0': c = *line++; if (c == 'x') { /* hexadecimal */ ; } else if (isdigit(c&0xff)) { /* octal */ } else { /* it was only 0 */ } break; #endif /* LATER */ case 'x': /* expecting hex data, must be an even number of digits!! */ while (true) { c = *line; if (isdigit(c&0xff)) { x = (c-'0') << 4; } else if (isxdigit(c&0xff)) { x = ((c&0x07) + 9) << 4; } else break; ++line; c = *line; if (isdigit(c&0xff)) { x |= (c-'0'); } else if (isxdigit(c&0xff)) { x |= (c&0x07) + 9; } else { fputs("odd number of hexadecimal digits\n", stderr); *p = p1; return 1; } ++line; if (p1 >= n) { *p = p1; return -1; } data[p1++] = x; } break; case 'A': case 'a': case 'C': case 'c': default: fprintf(stderr, "syntax error in \"%s\"\n", line-1); return 1; } } *p = p1; return 0; }