version 1.7.3.0
[socat.git] / dalan.c
blob2bf4dd217e37479c8e15b967888c6f37c6933fcd
1 /* source: dalan.c */
2 /* Copyright Gerhard Rieger */
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. */
8 #include "config.h"
9 #include <stdio.h>
10 #include <stdlib.h>
11 #if HAVE_STDBOOL_H
12 #include <stdbool.h>
13 #endif
14 #include <ctype.h>
15 #include "dalan.h"
17 /* test structure to find maximal alignment */
18 static struct {
19 char a;
20 long double b;
21 } maxalign;
23 /* test structure to find minimal alignment */
24 static struct {
25 char a;
26 char b;
27 } minalign;
29 /* test union to find kind of byte ordering */
30 static union {
31 char a[2];
32 short b;
33 } byteorder = { "01" };
35 struct dalan_opts_s dalan_opts = {
36 sizeof(int),
37 sizeof(short),
38 sizeof(long),
39 sizeof(char),
40 sizeof(float),
41 sizeof(double)
42 } ;
44 /* fill the dalan_opts structure with machine dependent defaults values. */
45 static void _dalan_dflts(struct dalan_opts_s *dlo) {
46 dlo->c_int = sizeof(int);
47 dlo->c_short = sizeof(short);
48 dlo->c_long = sizeof(long);
49 dlo->c_char = sizeof(char);
50 dlo->c_float = sizeof(float);
51 dlo->c_double = sizeof(double);
52 dlo->maxalign = (char *)&maxalign.b-&maxalign.a;
53 dlo->minalign = &minalign.b-&minalign.a;
54 dlo->byteorder = (byteorder.b!=7711);
57 /* allocate a new dalan_opts structure, fills it with machine dependent
58 defaults values, and returns the pointer. */
59 struct dalan_opts_s *dalan_props(void) {
60 struct dalan_opts_s *dlo;
61 dlo = malloc(sizeof(struct dalan_opts_s));
62 if (dlo == NULL) {
63 return NULL;
65 _dalan_dflts(dlo);
66 return dlo;
69 void dalan_init(void) {
70 _dalan_dflts(&dalan_opts);
73 /* read data description from line, write result to data; do not write
74 so much data that *p exceeds n !
75 p must be initialized to 0.
76 return 0 on success,
77 -1 if the data was cut due to n limit,
78 1 if a syntax error occurred
79 *p is a global data counter; especially it must be used when calculating
80 alignment. On successful return from the function *p must be actual!
82 int dalan(const char *line, char *data, size_t *p, size_t n) {
83 int align, mask, i, x;
84 size_t p1 = *p;
85 char c;
87 /*fputs(line, stderr); fputc('\n', stderr);*/
88 while (c = *line++) {
89 switch (c) {
90 case ' ':
91 case '\t':
92 case '\r':
93 case '\n':
94 break;
95 case ',':
96 align = 2;
97 while (*line == ',') {
98 align <<= 1;
99 ++line;
101 mask = align - 1; /* create the bitmask */
102 i = (align - (p1 & mask)) & mask;
103 while (i && p1<n) data[p1++] = 0, --i;
104 if (i) { *p = p1; return -1; }
105 break;
106 case ';':
107 align = dalan_opts.c_int;
108 mask = align - 1;
109 i = (align - (p1 & mask)) & mask;
110 while (i && p1<n) data[p1++] = 0, --i;
111 if (i) { *p = p1; return -1; }
112 break;
113 case '"':
114 while (1) {
115 switch (c = *line++) {
116 case '\0': fputs("unterminated string\n", stderr);
117 return 1;
118 case '"':
119 break;
120 case '\\':
121 if (!(c = *line++)) {
122 fputs("continuation line not implemented\n", stderr);
123 return 1;
125 switch (c) {
126 case 'n': c = '\n'; break;
127 case 'r': c = '\r'; break;
128 case 't': c = '\t'; break;
129 case 'f': c = '\f'; break;
130 case 'b': c = '\b'; break;
131 case 'a': c = '\a'; break;
132 #if 0
133 case 'e': c = '\e'; break;
134 #else
135 case 'e': c = '\033'; break;
136 #endif
137 case '0': c = '\0'; break;
139 /* PASSTHROUGH */
140 default:
141 if (p1 >= n) { *p = p1; return -1; }
142 data[p1++] = c;
143 continue;
145 if (c == '"')
146 break;
148 break;
149 case '\'':
150 switch (c = *line++) {
151 case '\0': fputs("unterminated character\n", stderr);
152 return 1;
153 case '\'': fputs("error in character\n", stderr);
154 return 1;
155 case '\\':
156 if (!(c = *line++)) {
157 fputs("continuation line not implemented\n", stderr);
158 return 1;
160 switch (c) {
161 case 'n': c = '\n'; break;
162 case 'r': c = '\r'; break;
163 case 't': c = '\t'; break;
164 case 'f': c = '\f'; break;
165 case 'b': c = '\b'; break;
166 case 'a': c = '\a'; break;
167 #if 0
168 case 'e': c = '\e'; break;
169 #else
170 case 'e': c = '\033'; break;
171 #endif
173 /* PASSTHROUGH */
174 default:
175 if (p1 >= n) { *p = p1; return -1; }
176 data[p1++] = c;
177 break;
179 if (*line != '\'') {
180 fputs("error in character termination\n", stderr);
181 *p = p1; return 1;
183 ++line;
184 break;
185 #if LATER
186 case '0':
187 c = *line++;
188 if (c == 'x') {
189 /* hexadecimal */ ;
190 } else if (isdigit(c&0xff)) {
191 /* octal */
192 } else {
193 /* it was only 0 */
195 break;
196 #endif /* LATER */
197 case 'x':
198 /* expecting hex data, must be an even number of digits!! */
199 while (true) {
200 c = *line;
201 if (isdigit(c&0xff)) {
202 x = (c-'0') << 4;
203 } else if (isxdigit(c&0xff)) {
204 x = ((c&0x07) + 9) << 4;
205 } else
206 break;
207 ++line;
208 c = *line;
209 if (isdigit(c&0xff)) {
210 x |= (c-'0');
211 } else if (isxdigit(c&0xff)) {
212 x |= (c&0x07) + 9;
213 } else {
214 fputs("odd number of hexadecimal digits\n", stderr);
215 *p = p1; return 1;
217 ++line;
218 if (p1 >= n) { *p = p1; return -1; }
219 data[p1++] = x;
221 break;
222 case 'A': case 'a':
223 case 'C': case 'c':
224 default: fprintf(stderr, "syntax error in \"%s\"\n", line-1);
225 return 1;
228 *p = p1; return 0;