controller_load.c 8.37 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", 
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
void controller_load_fatal_error (char* msg , yyscan_t yyscanner)
{
    	log_send(LOG_T_ERROR, "Fatal: %s", msg );
	log_server_flush();
	exit(1);
}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
72
73
74
75
76
77
78

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


79
void controller_load_var_add_str(char *string, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
80
{
81
82
	struct controller_load_extra *extra = yyget_extra(scanner);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
83
84
	struct controller_load_va_entry **entryp;
	
85
86
87
	if (!extra->va_list_start) {
		va_new(extra->va_list);
		extra->va_list_start = true;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
88
89
	}
	
90
	va_add(extra->va_list, char *, string);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
91
	
92
	for (entryp = &extra->va_entries; *entryp; entryp = &(*entryp)->next);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
93
94
95
96
97
98
	
	*entryp = malloc(sizeof(struct controller_load_va_entry));
	(*entryp)->next = NULL;
	(*entryp)->ptr = string;
}

99
void controller_load_var_add_dbl(double dbl, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
100
{
101
102
103
104
105
	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
106
107
	}
	
108
	va_add(extra->va_list, double, dbl);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
109
110
}

111
void controller_load_var_add_flt(float flt, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
112
{
113
114
115
116
117
118
119
120
	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
121
122
	} else {
		/* float is promoted to double in a variadic function */
123
		controller_load_var_add_dbl(flt, scanner);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
124
125
126
	}
}

127
void controller_load_var_add_float_array_start(yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
128
{
129
130
131
132
133
	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
134
135
}

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

158
void controller_load_var_add_int(int i, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
159
{
160
161
162
163
	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
164
165
	}
	
166
	va_add(extra->va_list, int, i);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
167
168
}

169
void controller_load_var_add_ul(unsigned long ul, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
170
{
171
172
173
174
	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
175
176
	}
	
177
	va_add(extra->va_list, unsigned long, ul);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
178
179
}

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

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

204
205
206
207
208
209
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
210

211
int controller_load_block_param_set(char *block, char *param, yyscan_t scanner)
Jeroen Vreeken's avatar
Jeroen Vreeken committed
212
{
213
214
215
216
217
218
219
220
221
	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;

222
	log_send(LOG_T_DEBUG, "Include '%s'", file_name);
223
	r = controller_load(file_name);
224
	log_send(LOG_T_DEBUG, "End of include '%s': %d", file_name, r);
225
226
227
228
229
230
231
232
233
}


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
234
235
236
237
	} else {
		int copybytes;
		
		copybytes = sizebytes;
238
239
		if (copybytes > extra->stringlen)
			copybytes = extra->stringlen;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
240
		*readbytes = copybytes;
241
242
243
		memcpy(buf, extra->string, copybytes);
		extra->string += copybytes;
		extra->stringlen -= copybytes;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
244
245
246
247
248
249
250
251
252
	}
	
	return 0;
}


static int controller_load_shell(char *args, char *out, int *outlen)
{
	int ret;
253
	struct controller_load_extra extra;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
254
	char *safe_context;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
255
	yyscan_t scanner;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
256

Jeroen Vreeken's avatar
Jeroen Vreeken committed
257
258
259
260
261
262
	if (!args) {
		*outlen = sprintf(out,
		     "no arguments\n");
		return *outlen;
	}

263
264
265
266
267
268
269
	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
270

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

273
	yylex_init_extra(&extra, &scanner);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
274

Jeroen Vreeken's avatar
Jeroen Vreeken committed
275
276
277
	safe_context = controller_block_context_get();
	controller_block_context_set("shell");

Jeroen Vreeken's avatar
Jeroen Vreeken committed
278
	ret = yyparse(scanner, NULL);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
279

Jeroen Vreeken's avatar
Jeroen Vreeken committed
280
281
	controller_block_context_set(safe_context);

Jeroen Vreeken's avatar
Jeroen Vreeken committed
282
283
	yylex_destroy(scanner);
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
284
285
286
287
288
289
290
291
292
293
294
	if (ret) {
		*outlen = sprintf(out,
		     "failed to parse arguments\n");
	} else {
		*outlen = sprintf(out,
		     "parsed arguments\n");
	}
	
	return *outlen;
}

295
296
297
298
299
300
301
302
303
304
static int controller_load_file_shell(char *args, char *out, int *outlen)
{
	int ret;

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

305
	log_send(LOG_T_DEBUG, "loading: %s", args);
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328

	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
329
330
331
332
};

int controller_load_shell_add(void)
{
333
334
335
336
337
	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
338
339
340
341
342
343
	
	return ret;
}

int controller_load(char *filename)
{
344
	struct controller_load_extra extra;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
345
346
	char *safe_context;
	yyscan_t scanner;
347
348
349
350
351
352
353
354
	
	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
355

Jeroen Vreeken's avatar
Jeroen Vreeken committed
356

357
	extra.input_file = fopen(filename, "r");
Jeroen Vreeken's avatar
Jeroen Vreeken committed
358
359
360
361
	if (!extra.input_file) {
		extra.ret = -1;
		goto err_nofile;
	}
Jeroen Vreeken's avatar
Jeroen Vreeken committed
362
	
363
	yylex_init_extra(&extra, &scanner);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
364

Jeroen Vreeken's avatar
Jeroen Vreeken committed
365
366
367
	safe_context = controller_block_context_get();
	controller_block_context_set(filename);

368
	extra.ret = yyparse(scanner, extra.input_file);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
369
370

	controller_block_context_set(safe_context);
Jeroen Vreeken's avatar
Jeroen Vreeken committed
371
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
372
	yylex_destroy(scanner);
373
	fclose(extra.input_file);
374
375

	controller_block_link();
Jeroen Vreeken's avatar
Jeroen Vreeken committed
376
	
Jeroen Vreeken's avatar
Jeroen Vreeken committed
377
err_nofile:
378
	return extra.ret;
Jeroen Vreeken's avatar
Jeroen Vreeken committed
379
}