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