2 /* Copyright Gerhard Rieger and contributors (see file CHANGES) */
3 /* Published under the GNU General Public License V.2, see file COPYING */
5 /* idea of a low level data description language. currently only a most
6 primitive subset exists. */
18 /* test structure to find maximal alignment */
24 /* test structure to find minimal alignment */
30 /* test union to find kind of byte ordering */
34 } byteorder
= { "01" };
36 struct dalan_opts_s dalan_opts
= {
45 /* fill the dalan_opts structure with machine dependent defaults values. */
46 static void _dalan_dflts(struct dalan_opts_s
*dlo
) {
47 dlo
->c_int
= sizeof(int);
48 dlo
->c_short
= sizeof(short);
49 dlo
->c_long
= sizeof(long);
50 dlo
->c_char
= sizeof(char);
51 dlo
->c_float
= sizeof(float);
52 dlo
->c_double
= sizeof(double);
53 dlo
->maxalign
= (char *)&maxalign
.b
-&maxalign
.a
;
54 dlo
->minalign
= &minalign
.b
-&minalign
.a
;
55 dlo
->byteorder
= (byteorder
.b
!=7711);
58 /* allocate a new dalan_opts structure, fills it with machine dependent
59 defaults values, and returns the pointer. */
60 struct dalan_opts_s
*dalan_props(void) {
61 struct dalan_opts_s
*dlo
;
62 dlo
= malloc(sizeof(struct dalan_opts_s
));
70 void dalan_init(void) {
71 _dalan_dflts(&dalan_opts
);
74 /* Parses and coverts a data item.
76 -1 if the data was cut due to n limit,
77 1 if a syntax error occurred
78 2 if the actual character is white space
79 3 if the first character is not a type specifier
81 static int dalan_item(int c
, const char **line0
, uint8_t *data
, size_t *p
, size_t n
) {
82 const char *line
= *line0
;
93 switch (c
= *line
++) {
94 case '\0': fputs("unterminated string\n", stderr
);
100 if (!(c
= *line
++)) {
101 fputs("continuation line not implemented\n", stderr
);
106 case 'n': c
= '\n'; break;
107 case 'r': c
= '\r'; break;
108 case 't': c
= '\t'; break;
109 case 'f': c
= '\f'; break;
110 case 'b': c
= '\b'; break;
111 case 'a': c
= '\a'; break;
113 case 'e': c
= '\e'; break;
115 case 'e': c
= '\033'; break;
117 case '0': c
= '\0'; break;
134 switch (c
= *line
++) {
135 case '\0': fputs("unterminated character\n", stderr
);
138 case '\'': fputs("error in character\n", stderr
);
142 if (!(c
= *line
++)) {
143 fputs("continuation line not implemented\n", stderr
);
148 case 'n': c
= '\n'; break;
149 case 'r': c
= '\r'; break;
150 case 't': c
= '\t'; break;
151 case 'f': c
= '\f'; break;
152 case 'b': c
= '\b'; break;
153 case 'a': c
= '\a'; break;
155 case 'e': c
= '\e'; break;
157 case 'e': c
= '\033'; break;
162 if (p1
>= n
) { *p
= p1
; return -1; }
167 fputs("error in character termination\n", stderr
);
175 /* expecting hex data, must be an even number of digits!! */
179 if (isdigit(c
&0xff)) {
181 } else if (isxdigit(c
&0xff)) {
182 x
= ((c
&0x07) + 9) << 4;
187 if (isdigit(c
&0xff)) {
189 } else if (isxdigit(c
&0xff)) {
192 fputs("odd number of hexadecimal digits\n", stderr
);
207 /* expecting decimal number, with target type long */
210 *(long *)&data
[p1
] = strtol(line
, &endptr
, 10);
216 /* expecting decimal number, with target type unsigned long */
219 *(unsigned long *)&data
[p1
] = strtol(line
, &endptr
, 10);
220 p1
+= sizeof(unsigned long);
225 /* expecting decimal number, with target type int */
228 *(int *)&data
[p1
] = strtol(line
, &endptr
, 10);
234 /* expecting decimal number, with target type unsigned int */
237 *(unsigned int *)&data
[p1
] = strtol(line
, &endptr
, 10);
238 p1
+= sizeof(unsigned int);
243 /* expecting decimal number, with target type short */
246 *(short *)&data
[p1
] = strtol(line
, &endptr
, 10);
252 /* expecting decimal number, with target type unsigned short */
255 *(unsigned short *)&data
[p1
] = strtol(line
, &endptr
, 10);
256 p1
+= sizeof(unsigned short);
261 /* expecting decimal number, with target type byte (int8_t) */
264 *(int8_t *)&data
[p1
] = strtoul(line
, &endptr
, 10);
265 p1
+= sizeof(uint8_t);
269 /* expecting decimal number, with target type byte (uint8_t) */
272 *(uint8_t *)&data
[p1
] = strtoul(line
, &endptr
, 10);
273 p1
+= sizeof(uint8_t);
286 /* read data description from line (\0-terminated), write result to data; do
287 not write so much data that *p exceeds n !
288 *p must be initialized.
290 -1 if the data was cut due to n limit,
291 1 if a syntax error occurred
292 *p is a global data counter; especially it must be used when calculating
293 alignment. On successful return from the function *p must be actual!
295 int dalan(const char *line
, uint8_t *data
, size_t *p
, size_t n
, char deflt
) {
301 /* assume there is a type specifier on beginning of rest of line */
306 rc
= dalan_item(c
, &line
, data
, p
, n
);
308 deflt
= c
; /* continue with this type as default */
309 } else if (rc
== 2) {
312 } else if (rc
== 3) {
316 /* No, we did not recognize c as type specifier, try default type */
317 rc
= dalan_item(deflt
, &line
, data
, p
, n
);
319 /* Nothing was parsed */