Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "date" on null in /usr/local/www/websvn.planix.org/blame.php on line 247

Warning: Attempt to read property "msg" on null in /usr/local/www/websvn.planix.org/blame.php on line 247
WebSVN – tendra.SVN – Blame – /branches/tendra5-amd64/src/utilities/calculus/template.c – Rev 6

Subversion Repositories tendra.SVN

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2 7u83 1
/*
6 7u83 2
 * Copyright (c) 2002-2005 The TenDRA Project <http://www.tendra.org/>.
3
 * All rights reserved.
4
 *
5
 * Redistribution and use in source and binary forms, with or without
6
 * modification, are permitted provided that the following conditions are met:
7
 *
8
 * 1. Redistributions of source code must retain the above copyright notice,
9
 *    this list of conditions and the following disclaimer.
10
 * 2. Redistributions in binary form must reproduce the above copyright notice,
11
 *    this list of conditions and the following disclaimer in the documentation
12
 *    and/or other materials provided with the distribution.
13
 * 3. Neither the name of The TenDRA Project nor the names of its contributors
14
 *    may be used to endorse or promote products derived from this software
15
 *    without specific, prior written permission.
16
 *
17
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS
18
 * IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
19
 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR
21
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22
 * EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
24
 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
25
 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
26
 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
27
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28
 *
29
 * $Id$
30
 */
31
/*
2 7u83 32
    		 Crown Copyright (c) 1997
6 7u83 33
 
2 7u83 34
    This TenDRA(r) Computer Program is subject to Copyright
35
    owned by the United Kingdom Secretary of State for Defence
36
    acting through the Defence Evaluation and Research Agency
37
    (DERA).  It is made available to Recipients with a
38
    royalty-free licence for its use, reproduction, transfer
39
    to other parties and amendment for any purpose not excluding
40
    product development provided that any such use et cetera
41
    shall be deemed to be acceptance of the following conditions:-
6 7u83 42
 
2 7u83 43
        (1) Its Recipients shall ensure that this Notice is
44
        reproduced upon any copies or amended versions of it;
6 7u83 45
 
2 7u83 46
        (2) Any amended version of it shall be clearly marked to
47
        show both the nature of and the organisation responsible
48
        for the relevant amendment or amendments;
6 7u83 49
 
2 7u83 50
        (3) Its onward transfer from a recipient to another
51
        party shall be deemed to be that party's acceptance of
52
        these conditions;
6 7u83 53
 
2 7u83 54
        (4) DERA gives no warranty or assurance as to its
55
        quality or suitability for any purpose and DERA accepts
56
        no liability whatsoever in relation to any use to which
57
        it may be put.
58
*/
59
 
60
 
61
#include "config.h"
62
#include "calculus.h"
63
#include "cmd_ops.h"
64
#include "error.h"
65
#include "common.h"
66
#include "output.h"
67
#include "template.h"
68
#include "xalloc.h"
69
 
70
 
71
/*
6 7u83 72
 * GET A COMMAND FROM A STRING
73
 *
74
 * This routine returns the address of the first non-white space character
75
 * from the string ps.  It returns the null pointer if the end of the line
76
 * is reached.
77
 */
2 7u83 78
 
6 7u83 79
static char *
80
get_command(char **ps)
2 7u83 81
{
6 7u83 82
    char *t = *ps;
83
    char *s = t;
84
    if (s) {
85
	char c;
86
	while (c = *s,(c == ' ' || c == '\t' || c == '\r')) {
87
	    *s = 0;
88
	    s++;
2 7u83 89
	}
6 7u83 90
	if (c == '#' || c == '\n' || c == 0) {
91
	    *s = 0;
92
	    *ps = NULL;
93
	    return(NULL);
2 7u83 94
	}
6 7u83 95
	t = s;
96
	while (c = *s, !(c == ' ' || c == '\t' || c == '\r' ||
97
			   c == '\n' || c == 0)) {
98
	    s++;
2 7u83 99
	}
6 7u83 100
	*ps = s;
2 7u83 101
    }
6 7u83 102
    return(t);
2 7u83 103
}
104
 
105
 
106
/*
6 7u83 107
 * READ A TEMPLATE FILE
108
 *
109
 * This routine reads a template file from the file f.
110
 */
2 7u83 111
 
6 7u83 112
static COMMAND
113
read_template(FILE *f, COMMAND p)
2 7u83 114
{
6 7u83 115
    int go = 1;
116
    char buff[1000];
117
    int ln1 = crt_line_no;
118
    LIST(COMMAND)q = NULL_list(COMMAND);
2 7u83 119
    do {
6 7u83 120
	COMMAND r = NULL_cmd;
121
	int ln2 = crt_line_no;
122
	char *s = fgets(buff, 1000, f);
123
	if (s == NULL) {
2 7u83 124
	    /* End of file */
6 7u83 125
	    if (IS_cmd_cond(p)) {
126
		error(ERROR_SERIOUS, "End of '@if' expected");
127
	    } else if (IS_cmd_loop(p)) {
128
		error(ERROR_SERIOUS, "End of '@loop' expected");
2 7u83 129
	    }
6 7u83 130
	    break;
2 7u83 131
	}
6 7u83 132
	s = xstrcpy(s);
133
	if (s[0] == '@') {
2 7u83 134
	    /* Complex command */
6 7u83 135
	    char *s1, *s2, *s3;
136
	    s++;
137
	    s1 = get_command(&s);
138
	    if (s1 == NULL) {
139
		    s1 = "<empty>";
140
	    }
141
	    s2 = get_command(&s);
142
	    s3 = get_command(&s);
143
	    if (streq(s1, "if")) {
144
		if (s2 == NULL) {
145
		    error(ERROR_SERIOUS, "Incomplete '@%s' command", s1);
146
		    s2 = "true";
2 7u83 147
		}
6 7u83 148
		MAKE_cmd_cond(ln2, s2, NULL_cmd, NULL_cmd, r);
149
	    } else if (streq(s1, "else")) {
150
		if (IS_cmd_cond(p)) {
151
		    COMMAND v = DEREF_cmd(cmd_cond_true_code(p));
152
		    if (!IS_NULL_cmd(v)) {
153
			error(ERROR_SERIOUS, "Duplicate '@%s' command", s1);
2 7u83 154
		    }
6 7u83 155
		    q = REVERSE_list(q);
156
		    MAKE_cmd_compound(ln1, q, v);
157
		    COPY_cmd(cmd_cond_true_code(p), v);
158
		    q = NULL_list(COMMAND);
159
		    ln1 = ln2;
2 7u83 160
		} else {
6 7u83 161
		    error(ERROR_SERIOUS, "Misplaced '@%s' command", s1);
2 7u83 162
		}
6 7u83 163
		s3 = s2;
164
	    } else if (streq(s1, "endif")) {
165
		if (IS_cmd_cond(p)) {
166
		    go = 0;
2 7u83 167
		} else {
6 7u83 168
		    error(ERROR_SERIOUS, "Misplaced '@%s' command", s1);
2 7u83 169
		}
6 7u83 170
		s3 = s2;
171
	    } else if (streq(s1, "loop")) {
172
		if (s2 == NULL) {
173
		    error(ERROR_SERIOUS, "Incomplete '@%s' command", s1);
174
		    s2 = "false";
2 7u83 175
		}
6 7u83 176
		MAKE_cmd_loop(ln2, s2, NULL_cmd, r);
177
	    } else if (streq(s1, "end")) {
178
		if (IS_cmd_loop(p)) {
179
		    go = 0;
2 7u83 180
		} else {
6 7u83 181
		    error(ERROR_SERIOUS, "Misplaced '@%s' command", s1);
2 7u83 182
		}
6 7u83 183
		s3 = s2;
184
	    } else if (streq(s1, "comment")) {
185
		s3 = NULL;
2 7u83 186
	    } else {
6 7u83 187
		error(ERROR_SERIOUS, "Unknown command, '@%s'", s1);
188
		s3 = NULL;
2 7u83 189
	    }
6 7u83 190
	    if (s3) {
191
		error(ERROR_SERIOUS, "End of '@%s' expected", s1);
2 7u83 192
	    }
6 7u83 193
	    crt_line_no = ln2 + 1;
194
	    if (!IS_NULL_cmd(r)) {
2 7u83 195
		/* Read body of command */
6 7u83 196
		COMMAND u = read_template(f, r);
197
		if (IS_cmd_cond(r)) {
198
		    COMMAND v = DEREF_cmd(cmd_cond_true_code(r));
199
		    if (IS_NULL_cmd(v)) {
200
			COPY_cmd(cmd_cond_true_code(r), u);
2 7u83 201
		    } else {
6 7u83 202
			COPY_cmd(cmd_cond_false_code(r), u);
2 7u83 203
		    }
6 7u83 204
		} else if (IS_cmd_loop(r)) {
205
		    COPY_cmd(cmd_loop_body(r), u);
2 7u83 206
		}
6 7u83 207
		CONS_cmd(r, q, q);
2 7u83 208
	    }
209
	} else {
210
	    /* Simple command */
6 7u83 211
	    MAKE_cmd_simple(ln2, s, r);
212
	    CONS_cmd(r, q, q);
213
	    crt_line_no = ln2 + 1;
2 7u83 214
	}
6 7u83 215
    } while (go);
216
    q = REVERSE_list(q);
217
    MAKE_cmd_compound(ln1, q, p);
218
    return(p);
2 7u83 219
}
220
 
221
 
222
/*
6 7u83 223
 * TOKEN CONDITION
224
 *
225
 * This variable gives the value of the token condition.
226
 */
2 7u83 227
 
6 7u83 228
int token_cond = 0;
2 7u83 229
 
230
 
231
/*
6 7u83 232
 * EVALUATE A CONDITION
233
 *
234
 * This routine evaluates the condition s.
235
 */
2 7u83 236
 
6 7u83 237
static int
238
eval_cond(char *s)
2 7u83 239
{
6 7u83 240
    if (s[0] == '!') {
2 7u83 241
	/* Negate condition */
6 7u83 242
	return(!eval_cond(s + 1));
2 7u83 243
    }
6 7u83 244
    if (streq(s, "comp.complex")) {
2 7u83 245
	/* Complex component type */
6 7u83 246
	if (HAVE_COMPONENT) {
247
	    TYPE_P_P pt = cmp_type(CRT_COMPONENT);
248
	    TYPE_P t = DEREF_ptr(pt);
249
	    return(is_complex_type(t));
2 7u83 250
	}
6 7u83 251
	return(0);
2 7u83 252
    }
6 7u83 253
    if (streq(s, "comp.default")) {
2 7u83 254
	/* Component default value */
6 7u83 255
	if (HAVE_COMPONENT) {
256
	    string_P pv = cmp_name(CRT_COMPONENT);
257
	    string v = DEREF_string(pv);
258
	    if (v) return(1);
2 7u83 259
	}
6 7u83 260
	return(0);
2 7u83 261
    }
6 7u83 262
    if (streq(s, "token")) {
263
	    return(token_cond);
264
    }
265
    if (streq(s, "true")) {
266
	    return(1);
267
    }
268
    if (streq(s, "false")) {
269
	    return(0);
270
    }
271
    error(ERROR_SERIOUS, "Unknown condition, '%s'", s);
272
    return(0);
2 7u83 273
}
274
 
275
 
276
/*
6 7u83 277
 * WRITE A TEMPLATE FILE
278
 *
279
 * This routine writes the template file given by the commands cmd.
280
 */
2 7u83 281
 
6 7u83 282
static void
283
write_template(COMMAND cmd)
2 7u83 284
{
6 7u83 285
    if (!IS_NULL_cmd(cmd)) {
286
	crt_line_no = DEREF_int(cmd_line(cmd));
287
	switch (TAG_cmd(cmd)) {
288
	    case cmd_simple_tag: {
289
		string s = DEREF_string(cmd_simple_text(cmd));
290
		output(s);
291
		break;
2 7u83 292
	    }
6 7u83 293
	    case cmd_compound_tag: {
294
		LIST(COMMAND)p;
295
		p = DEREF_list(cmd_compound_seq(cmd));
296
		while (!IS_NULL_list(p)) {
297
		    COMMAND a = DEREF_cmd(HEAD_list(p));
298
		    write_template(a);
299
		    p = TAIL_list(p);
2 7u83 300
		}
6 7u83 301
		break;
2 7u83 302
	    }
6 7u83 303
	    case cmd_loop_tag: {
304
		string s = DEREF_string(cmd_loop_control(cmd));
305
		COMMAND a = DEREF_cmd(cmd_loop_body(cmd));
306
		if (streq(s, "enum")) {
307
		    LOOP_ENUM write_template(a);
308
		} else if (streq(s, "enum.const")) {
309
		    if (HAVE_ENUM) {
310
			LOOP_ENUM_CONST write_template(a);
2 7u83 311
		    }
6 7u83 312
		} else if (streq(s, "identity")) {
313
		    LOOP_IDENTITY write_template(a);
314
		} else if (streq(s, "primitive")) {
315
		    LOOP_PRIMITIVE write_template(a);
316
		} else if (streq(s, "struct")) {
317
		    LOOP_STRUCTURE write_template(a);
318
		} else if (streq(s, "struct.comp")) {
319
		    if (HAVE_STRUCTURE) {
320
			LOOP_STRUCTURE_COMPONENT write_template(a);
2 7u83 321
		    }
6 7u83 322
		} else if (streq(s, "union")) {
323
		    LOOP_UNION write_template(a);
324
		} else if (streq(s, "union.comp")) {
325
		    if (HAVE_UNION) {
326
			LOOP_UNION_COMPONENT write_template(a);
2 7u83 327
		    }
6 7u83 328
		} else if (streq(s, "union.field")) {
329
		    if (HAVE_UNION) {
330
			LOOP_UNION_FIELD write_template(a);
2 7u83 331
		    }
6 7u83 332
		} else if (streq(s, "union.field.comp")) {
333
		    if (HAVE_UNION && HAVE_FIELD) {
334
			LOOP_FIELD_COMPONENT write_template(a);
2 7u83 335
		    }
6 7u83 336
		} else if (streq(s, "union.map")) {
337
		    if (HAVE_UNION) {
338
			LOOP_UNION_MAP write_template(a);
2 7u83 339
		    }
6 7u83 340
		} else if (streq(s, "union.map.arg")) {
341
		    if (HAVE_UNION && HAVE_MAP) {
342
			LOOP_MAP_ARGUMENT write_template(a);
2 7u83 343
		    }
344
		} else {
6 7u83 345
		    error(ERROR_SERIOUS, "Unknown control, '%s'", s);
2 7u83 346
		}
6 7u83 347
		break;
2 7u83 348
	    }
6 7u83 349
	    case cmd_cond_tag: {
350
		string s = DEREF_string(cmd_cond_control(cmd));
351
		COMMAND a = DEREF_cmd(cmd_cond_true_code(cmd));
352
		COMMAND b = DEREF_cmd(cmd_cond_false_code(cmd));
353
		if (eval_cond(s)) {
354
		    write_template(a);
2 7u83 355
		} else {
6 7u83 356
		    write_template(b);
2 7u83 357
		}
6 7u83 358
		break;
2 7u83 359
	    }
360
	}
361
    }
6 7u83 362
    return;
2 7u83 363
}
364
 
365
 
366
/*
6 7u83 367
 * PROCESS A TEMPLATE FILE
368
 *
369
 * This routine processes the template file in to the output file out.
370
 */
2 7u83 371
 
6 7u83 372
void
373
template_file(char *in, char *out)
2 7u83 374
{
6 7u83 375
    COMMAND cmd;
376
    FILE *input_file;
377
    crt_line_no = 1;
378
    crt_file_name = in;
379
    input_file = fopen(in, "r");
380
    if (input_file == NULL) {
381
	error(ERROR_SERIOUS, "Can't open template file, '%s'", in);
382
	return;
2 7u83 383
    }
6 7u83 384
    MAKE_cmd_simple(1, "<dummy>", cmd);
385
    cmd = read_template(input_file, cmd);
386
    fclose_v(input_file);
387
    if (streq(out, ".")) {
388
	output_file = stdout;
2 7u83 389
    } else {
6 7u83 390
	output_file = fopen(out, "w");
391
	if (output_file == NULL) {
392
	    error(ERROR_SERIOUS, "Can't open output file, '%s'", out);
393
	    return;
2 7u83 394
	}
395
    }
6 7u83 396
    have_varargs = 0;
397
    write_template(cmd);
398
    have_varargs = 1;
399
    flush_output();
400
    if (output_file != stdout) {
401
	    fclose_v(output_file);
402
    }
403
    return;
2 7u83 404
}