controller_load.c 8.23 KB
Newer Older
Jeroen Vreeken's avatar
Jeroen Vreeken committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
	Copyright Jeroen Vreeken (pe1rxq@amsat.org), 2009
	Copyright Stichting C.A. Muller Radioastronomiestation, 2009

	This program is free software: you can redistribute it and/or modify
	it under the terms of the GNU General Public License as published by
	the Free Software Foundation, either version 3 of the License, or
	(at your option) any later version.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program.  If not, see <http://www.gnu.org/licenses/>.

 */

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdbool.h>
#include "controller_load_parser.tab.h"
Jeroen Vreeken's avatar
Jeroen Vreeken committed
25
#include "controller_load_parser.yy.h"
Jeroen Vreeken's avatar
Jeroen Vreeken committed
26
27
#include "controller_load.h"
#include "controller_sample.h"
28
#include "controller_block.h"
29
#include "../../common/include/dynarg.h"
Jeroen Vreeken's avatar
Jeroen Vreeken committed
30
#include <shell/shell.h>
31
#include "log.h"
Jeroen Vreeken's avatar
Jeroen Vreeken committed
32

33
34
35
36
struct controller_load_array {
	void *array;
	size_t size;
};
Jeroen Vreeken's avatar
Jeroen Vreeken committed
37

Jeroen Vreeken's avatar
Jeroen Vreeken committed
38

39
40
41
42
43
44
45
46
47
48
49
50
struct controller_load_extra {
	char *filename;
	int ret;
	bool va_list_start;
	va_list va_list;
	struct controller_load_va_entry *va_entries;
	struct controller_load_array *array;
	bool use_string;
	char *string;
	size_t stringlen;
	FILE *input_file;
};
Jeroen Vreeken's avatar
Jeroen Vreeken committed
51

52
53

int yyparse(yyscan_t scanner, FILE *);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
54

Jeroen Vreeken's avatar
Jeroen Vreeken committed
55
void yyerror(yyscan_t scanner, char const *s)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
56
{
57
58
	struct controller_load_extra *extra = yyget_extra(scanner);
	
59
	log_send(LOG_T_ERROR, "%s:%d: %s\n", 
60
	    extra->filename,
Jeroen Vreeken's avatar
Jeroen Vreeken committed
61
62
	    yyget_lineno(scanner),
	    s);
63
	extra->ret = -1;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
64
65
66
67
68
69
70
71
72
}


struct controller_load_va_entry {
	struct controller_load_va_entry *next;
	void *ptr;
};


73
void controller_load_var_add_str(char *string, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
74
{
75
76
	struct controller_load_extra *extra = yyget_extra(scanner);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
77
78
	struct controller_load_va_entry **entryp;
	
79
80
81
	if (!extra->va_list_start) {
		va_new(extra->va_list);
		extra->va_list_start = true;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
82
83
	}
	
84
	va_add(extra->va_list, char *, string);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
85
	
86
	for (entryp = &extra->va_entries; *entryp; entryp = &(*entryp)->next);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
87
88
89
90
91
92
	
	*entryp = malloc(sizeof(struct controller_load_va_entry));
	(*entryp)->next = NULL;
	(*entryp)->ptr = string;
}

93
void controller_load_var_add_dbl(double dbl, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
94
{
95
96
97
98
99
	struct controller_load_extra *extra = yyget_extra(scanner);

	if (!extra->va_list_start) {
		va_new(extra->va_list);
		extra->va_list_start = true;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
100
101
	}
	
102
	va_add(extra->va_list, double, dbl);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
103
104
}

105
void controller_load_var_add_flt(float flt, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
106
{
107
108
109
110
111
112
113
114
	struct controller_load_extra *extra = yyget_extra(scanner);

	if (extra->array) {
		extra->array->array = realloc(
		    extra->array->array,
		    extra->array->size + sizeof(float));
		*(float*)(extra->array->array + extra->array->size) = flt;
		extra->array->size += sizeof(float);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
115
116
	} else {
		/* float is promoted to double in a variadic function */
117
		controller_load_var_add_dbl(flt, scanner);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
118
119
120
	}
}

121
void controller_load_var_add_float_array_start(yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
122
{
123
124
125
126
127
	struct controller_load_extra *extra = yyget_extra(scanner);

	extra->array = malloc(sizeof(struct controller_load_array));
	extra->array->array = NULL;
	extra->array->size = 0;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
128
129
}

130
void controller_load_var_add_float_array_end(yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
131
{
132
	struct controller_load_extra *extra = yyget_extra(scanner);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
133
134
	struct controller_load_va_entry **entryp;
	
135
136
137
	if (!extra->va_list_start) {
		va_new(extra->va_list);
		extra->va_list_start = true;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
138
139
	}
	
140
	va_add(extra->va_list, float *, extra->array->array);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
141
	
142
	for (entryp = &extra->va_entries; *entryp; entryp = &(*entryp)->next);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
143
144
145
	
	*entryp = malloc(sizeof(struct controller_load_va_entry));
	(*entryp)->next = NULL;
146
	(*entryp)->ptr = extra->array->array;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
147
	
148
149
	free(extra->array);
	extra->array = NULL;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
150
151
}

152
void controller_load_var_add_int(int i, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
153
{
154
155
156
157
	struct controller_load_extra *extra = yyget_extra(scanner);
	if (!extra->va_list_start) {
		va_new(extra->va_list);
		extra->va_list_start = true;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
158
159
	}
	
160
	va_add(extra->va_list, int, i);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
161
162
}

163
void controller_load_var_add_ul(unsigned long ul, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
164
{
165
166
167
168
	struct controller_load_extra *extra = yyget_extra(scanner);
	if (!extra->va_list_start) {
		va_new(extra->va_list);
		extra->va_list_start = true;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
169
170
	}
	
171
	va_add(extra->va_list, unsigned long, ul);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
172
173
}

174
void controller_load_var_clear(yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
175
{
176
	struct controller_load_extra *extra = yyget_extra(scanner);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
177
178
	struct controller_load_va_entry *entry, *next;
	
179
	for (entry = extra->va_entries; entry; entry = next) {
Jeroen Vreeken's avatar
Jeroen Vreeken committed
180
181
182
183
184
		if (entry->ptr)
			free(entry->ptr);
		next = entry->next;
		free(entry);
	}
185
	extra->va_entries = NULL;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
186
	
187
188
189
	if (extra->va_list_start) {
		va_free(extra->va_list);
		extra->va_list_start = false;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
190
191
192
193
194
195
196
197
	}
}

void controller_load_frequency(double frequency)
{
	controller_sample_frequency_set(frequency);
}

198
199
200
201
202
203
int controller_load_block_create(char *type, char *name, yyscan_t scanner)
{
	struct controller_load_extra *extra = yyget_extra(scanner);

	return controller_block_create(type, name, extra->va_list);
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
204

205
int controller_load_block_param_set(char *block, char *param, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
206
{
207
208
209
210
211
212
213
214
215
	struct controller_load_extra *extra = yyget_extra(scanner);

	return controller_block_param_set(block, param, extra->va_list);
}

void controller_load_include(char *file_name)
{
	int r;

216
	log_send(LOG_T_DEBUG, "Include '%s'", file_name);
217
	r = controller_load(file_name);
218
	log_send(LOG_T_DEBUG, "End of include '%s': %d", file_name, r);
219
220
221
222
223
224
225
226
227
}


int controller_load_yy_input(char *buf, int *readbytes, int sizebytes, yyscan_t scanner)
{
	struct controller_load_extra *extra = yyget_extra(scanner);

	if (!extra->use_string) {
		*readbytes = fread(buf, 1, sizebytes, extra->input_file);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
228
229
230
231
	} else {
		int copybytes;
		
		copybytes = sizebytes;
232
233
		if (copybytes > extra->stringlen)
			copybytes = extra->stringlen;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
234
		*readbytes = copybytes;
235
236
237
		memcpy(buf, extra->string, copybytes);
		extra->string += copybytes;
		extra->stringlen -= copybytes;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
238
239
240
241
242
243
244
245
246
	}
	
	return 0;
}


static int controller_load_shell(char *args, char *out, int *outlen)
{
	int ret;
247
	struct controller_load_extra extra;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
248
	char *safe_context;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
249
	yyscan_t scanner;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
250

Jeroen Vreeken's avatar
Jeroen Vreeken committed
251
252
253
254
255
256
	if (!args) {
		*outlen = sprintf(out,
		     "no arguments\n");
		return *outlen;
	}

257
258
259
260
261
262
263
	extra.ret = 0;
	extra.va_entries = NULL;
	extra.va_list_start = false;
	extra.array = NULL;
	extra.use_string = true;
	extra.stringlen = strlen(args);
	extra.string = args;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
264

265
	log_send(LOG_T_DEBUG, "parsing: %s", args);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
266

267
	yylex_init_extra(&extra, &scanner);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
268

Jeroen Vreeken's avatar
Jeroen Vreeken committed
269
270
271
	safe_context = controller_block_context_get();
	controller_block_context_set("shell");

Jeroen Vreeken's avatar
Jeroen Vreeken committed
272
	ret = yyparse(scanner, NULL);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
273

Jeroen Vreeken's avatar
Jeroen Vreeken committed
274
275
	controller_block_context_set(safe_context);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
276
277
	yylex_destroy(scanner);
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
278
279
280
281
282
283
284
285
286
287
288
	if (ret) {
		*outlen = sprintf(out,
		     "failed to parse arguments\n");
	} else {
		*outlen = sprintf(out,
		     "parsed arguments\n");
	}
	
	return *outlen;
}

289
290
291
292
293
294
295
296
297
298
static int controller_load_file_shell(char *args, char *out, int *outlen)
{
	int ret;

	if (!args) {
		*outlen = sprintf(out,
		     "no arguments\n");
		return *outlen;
	}

299
	log_send(LOG_T_DEBUG, "loading: %s", args);
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322

	ret = controller_load(args);
	
	if (ret) {
		*outlen = sprintf(out,
		     "failed to load file\n");
	} else {
		*outlen = sprintf(out,
		     "parsed file\n");
	}
	
	return *outlen;
}

static struct shell_cmd controller_cmd[] = {
	{ "controller", 
	  "parse arguments as controller commands",
	  controller_load_shell
	},
	{ "controller_file", 
	  "load controller commands from file",
	  controller_load_file_shell
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
323
324
325
326
};

int controller_load_shell_add(void)
{
327
328
329
330
331
	int ret = 0, i;
	
	for (i = 0; i < sizeof(controller_cmd)/sizeof(struct shell_cmd); i++) {
		ret |= shell_cmd_add(&controller_cmd[i]);
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
332
333
334
335
336
337
	
	return ret;
}

int controller_load(char *filename)
{
338
	struct controller_load_extra extra;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
339
340
	char *safe_context;
	yyscan_t scanner;
341
342
343
344
345
346
347
348
	
	extra.filename = filename;
	extra.ret = 0;
	extra.va_entries = NULL;
	extra.va_list_start = false;
	extra.array = NULL;
	extra.use_string = false;
	extra.stringlen = 0;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
349

Jeroen Vreeken's avatar
Jeroen Vreeken committed
350

351
	extra.input_file = fopen(filename, "r");
Jeroen Vreeken's avatar
Jeroen Vreeken committed
352
353
354
355
	if (!extra.input_file) {
		extra.ret = -1;
		goto err_nofile;
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
356
	
357
	yylex_init_extra(&extra, &scanner);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
358

Jeroen Vreeken's avatar
Jeroen Vreeken committed
359
360
361
	safe_context = controller_block_context_get();
	controller_block_context_set(filename);

362
	extra.ret = yyparse(scanner, extra.input_file);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
363
364

	controller_block_context_set(safe_context);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
365
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
366
	yylex_destroy(scanner);
367
	fclose(extra.input_file);
368
369

	controller_block_link();
Jeroen Vreeken's avatar
Jeroen Vreeken committed
370
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
371
err_nofile:
372
	return extra.ret;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
373
}