2 # PSPP - a program for statistical analysis.
3 # Copyright (C) 2017, 2021 Free Software Foundation, Inc.
5 # This program is free software: you can redistribute it and/or modify
6 # it under the terms of the GNU General Public License as published by
7 # the Free Software Foundation, either version 3 of the License, or
8 # (at your option) any later version.
10 # This program is distributed in the hope that it will be useful,
11 # but WITHOUT ANY WARRANTY; without even the implied warranty of
12 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 # GNU General Public License for more details.
15 # You should have received a copy of the GNU General Public License
16 # along with this program. If not, see <http://www.gnu.org/licenses/>.
26 Defines all our types.
28 Initializes 'types' global.
34 # Common user-visible types used throughout evaluation trees.
35 init_type('number', 'any', C_TYPE='double',
36 ATOM='number', MANGLE='n', HUMAN_NAME='number',
37 STACK='ns', MISSING_VALUE='SYSMIS')
38 init_type('string', 'any', C_TYPE='struct substring',
39 ATOM='string', MANGLE='s', HUMAN_NAME='string',
40 STACK='ss', MISSING_VALUE='empty_string')
41 init_type('boolean', 'any', C_TYPE='double',
42 ATOM='number', MANGLE='n', HUMAN_NAME='boolean',
43 STACK='ns', MISSING_VALUE='SYSMIS')
46 init_type('format', 'atom')
47 init_type('ni_format', 'leaf', C_TYPE='const struct fmt_spec *',
48 ATOM='format', MANGLE='f',
49 HUMAN_NAME='num_input_format')
50 init_type('no_format', 'leaf', C_TYPE='const struct fmt_spec *',
51 ATOM='format', MANGLE='f',
52 HUMAN_NAME='num_output_format')
55 init_type('integer', 'leaf', C_TYPE='int',
56 ATOM='integer', MANGLE='n', HUMAN_NAME='integer')
57 init_type('pos_int', 'leaf', C_TYPE='int',
58 ATOM='integer', MANGLE='n',
59 HUMAN_NAME='positive_integer_constant')
62 init_type('variable', 'atom')
63 init_type('num_var', 'leaf', C_TYPE='const struct variable *',
64 ATOM='variable', MANGLE='Vn',
65 HUMAN_NAME='num_variable')
66 init_type('str_var', 'leaf', C_TYPE='const struct variable *',
67 ATOM='variable', MANGLE='Vs',
68 HUMAN_NAME='string_variable')
69 init_type('var', 'leaf', C_TYPE='const struct variable *',
70 ATOM='variable', MANGLE='V',
71 HUMAN_NAME='variable')
74 init_type('vector', 'leaf', C_TYPE='const struct vector *',
75 ATOM='vector', MANGLE='v', HUMAN_NAME='vector')
78 init_type('expression', 'fixed', C_TYPE='struct expression *',
80 init_type('case', 'fixed', C_TYPE='const struct ccase *',
82 init_type('case_idx', 'fixed', C_TYPE='size_t',
83 FIXED_VALUE='case_idx')
84 init_type('dataset', 'fixed', C_TYPE='struct dataset *',
87 # One of these is emitted at the end of each expression as a sentinel
88 # that tells expr_evaluate() to return the value on the stack.
89 init_type('return_number', 'atom')
90 init_type('return_string', 'atom')
92 # Used only for debugging purposes.
93 init_type('operation', 'atom')
95 def init_type(name, role, **rest):
97 init_type has 2 required arguments:
101 'name' is the type's name in operations.def.
103 `OP_$name' is the terminal's type in operations.h.
105 `expr_allocate_$name()' allocates a node of the given type.
107 ROLE: How the type may be used:
109 "any": Usable as operands and function arguments, and
110 function and operator results.
112 "leaf": Usable as operands and function arguments, but
113 not function arguments or results. (Thus, they appear
114 only in leaf nodes in the parse type.)
116 "fixed": Not allowed either as an operand or argument
117 type or a result type. Used only as auxiliary data.
119 "atom": Not allowed anywhere; just adds the name to
122 All types except those with "atom" as their role also require:
124 C_TYPE: The C type that represents this abstract type.
126 Types with "any" or "leaf" role require:
130 `$atom' is the `struct operation_data' member name.
132 get_$atom_name() obtains the corresponding data from a
135 MANGLE: Short string for name mangling. Use identical strings
136 if two types should not be overloaded.
138 HUMAN_NAME: Name for a type when we describe it to the user.
140 Types with role "any" require:
142 STACK: Name of the local variable in expr_evaluate(), used for
143 maintaining the stack for this type.
145 MISSING_VALUE: Expression used for the missing value of this
148 Types with role "fixed" require:
150 FIXED_VALUE: Expression used for the value of this type.
153 new_type = { 'NAME': name, 'ROLE': role } | rest
155 need_keys = ['NAME', 'ROLE']
157 need_keys += ['C_TYPE', 'ATOM', 'MANGLE', 'HUMAN_NAME', 'STACK', 'MISSING_VALUE']
159 need_keys += ['C_TYPE', 'ATOM', 'MANGLE', 'HUMAN_NAME']
160 elif role == 'fixed':
161 need_keys += ['C_TYPE', 'FIXED_VALUE']
165 sys.stderr.write("no role '%s'\n" % role)
168 for key in new_type.keys():
169 if not key in new_type:
170 sys.stderr.write("%s lacks %s\n" % (name, key))
172 for key in need_keys:
173 if not key in need_keys:
174 sys.stderr.write("%s has superfluous key %s\n" % (name, key))
177 types[name] = new_type
182 """Returns the C type of the given type as a string designed to be
183 prepended to a variable name to produce a declaration. (That
184 won't work in general but it works well enough for our types.)
186 c_type = type_["C_TYPE"]
187 if not c_type.endswith('*'):
194 """Parses the entire input.
196 Initializes ops, funcs, opers."""
215 while toktype != 'eof':
218 'UNIMPLEMENTED': False,
221 'ABSORB_MISS': False,
225 if match('extension'):
226 op['EXTENSION'] = True
227 elif match('no_opt'):
228 op['OPTIMIZABLE'] = False
229 elif match('absorb_miss'):
230 op['ABSORB_MISS'] = True
231 elif match('perm_only'):
232 op['PERM_ONLY'] = True
233 elif match('no_abbrev'):
234 op['NO_ABBREV'] = True
238 return_type = parse_type()
239 if return_type is None:
240 return_type = types['number']
241 if return_type['NAME'] not in ['number', 'string', 'boolean']:
242 sys.stderr.write('%s is not a valid return type\n' % return_type['NAME'])
244 op['RETURNS'] = return_type
246 op['CATEGORY'] = token
247 if op['CATEGORY'] not in ['operator', 'function']:
248 sys.stderr.write("'operator' or 'function' expected at '%s'" % token)
253 if op['CATEGORY'] == 'function' and '_' in name:
254 sys.stderr.write("function name '%s' may not contain underscore\n" % name)
256 elif op['CATEGORY'] == 'operator' and '.' in name:
257 sys.stderr.write("operator name '%s' may not contain period\n" % name)
260 m = re.match(r'(.*)\.(\d+)$', name)
262 prefix, suffix = m.groups()
264 op['MIN_VALID'] = int(suffix)
265 op['ABSORB_MISS'] = True
272 while not match(')'):
278 sys.stderr.write('array must be last argument\n')
284 for arg in op['ARGS']:
285 if 'CONDITION' in arg:
286 any_arg = '|'.join([a['NAME'] for a in op['ARGS']])
287 arg['CONDITION'] = re.sub(r'\b(%s)\b' % any_arg, r'arg_\1',
290 opname = 'OP_' + op['NAME']
291 opname = opname.replace('.', '_')
292 if op['CATEGORY'] == 'function':
294 mangle = ''.join([a['TYPE']['MANGLE'] for a in op['ARGS']])
295 op['MANGLE'] = mangle
296 opname += '_' + mangle
297 op['OPNAME'] = opname
299 if op['MIN_VALID'] > 0:
302 sys.stderr.write("can't have minimum valid count without array arg\n")
304 if aa['TYPE']['NAME'] != 'number':
305 sys.stderr.write('minimum valid count allowed only with double array\n')
308 sys.stderr.write("can't have minimu valid count if array has multiplication factor\n")
312 while toktype == 'id':
315 sys.stderr.write('parse error\n')
317 if type_['ROLE'] not in ['leaf', 'fixed']:
318 sys.stderr.write("'%s' is not allowed as auxiliary data\n"
322 op['AUX'] += [{'TYPE': type_, 'NAME': name}]
325 if op['OPTIMIZABLE']:
326 if op['NAME'].startswith('RV.'):
327 sys.stderr.write("random variate functions must be marked 'no_opt'\n")
329 for key in ['CASE', 'CASE_IDX']:
331 sys.stderr.write("operators with %s aux data must be marked 'no_opt'\n" % key)
334 if op['RETURNS']['NAME'] == 'string' and not op['ABSORB_MISS']:
335 for arg in op['ARGS']:
336 if arg['TYPE']['NAME'] in ['number', 'boolean']:
337 sys.stderr.write("'%s' returns string and has double or bool "
338 "argument, but is not marked ABSORB_MISS\n"
341 if 'CONDITION' in arg:
342 sys.stderr.write("'%s' returns string but has argument with condition\n")
345 if toktype == 'block':
346 op['BLOCK'] = force('block')
347 elif toktype == 'expression':
348 if token == 'unimplemented':
349 op['UNIMPLEMENTED'] = True
351 op['EXPRESSION'] = token
354 sys.stderr.write("block or expression expected\n")
358 sys.stderr.write("duplicate operation name %s\n" % opname)
361 if op['CATEGORY'] == 'function':
367 funcs = sorted(funcs, key=lambda name: (ops[name]['NAME'], ops[name]['OPNAME']))
368 opers = sorted(opers, key=lambda name: ops[name]['NAME'])
369 order = funcs + opers
372 """Reads the next token into 'token' and 'toktype'."""
382 print('%s %s' % (line, toktype))
383 m = re.match(r'([a-zA-Z_][a-zA-Z_.0-9]*)(.*)$', line)
385 token, line = m.groups()
389 m = re.match(r'([0-9]+)(.*)$', line)
391 token, line = m.groups()
396 m = re.match(r'([][(),*;.])(.*)$', line)
398 token, line = m.groups()
402 m = re.match(r'=\s*(.*)$', line)
404 toktype = 'expression'
406 token = accumulate_balanced(';')
409 m = re.match(r'{(.*)$', line)
413 token = accumulate_balanced('}')
414 token = token.rstrip('\n')
417 sys.stderr.write("bad character '%s' in input\n" % line[0])
421 """Skip whitespace."""
424 sys.stderr.write("unexpected end of file\n")
439 def accumulate_balanced(end, swallow_end=True):
440 """Accumulates input until a character in 'end' is encountered,
441 except that balanced pairs of (), [], or {} cause 'end' to be
442 ignored. Returns the input read.
447 print("line='%s'" % line)
450 for idx, c in enumerate(line):
451 print('nest=%s %s end=%s' % (nest, c, end))
452 if c in end and nest == 0:
464 sys.stderr.write('unbalanced parentheses\n')
471 """Reads the next line from INPUT into 'line'."""
474 line = in_file.readline()
476 print("%s\n" % line_number)
480 line = line.rstrip('\r\n')
481 comment_ofs = line.find('//')
483 line = line[:comment_ofs]
486 """If the current token is an identifier that names a type, returns
487 the type and skips to the next token. Otherwise, returns
491 for type_ in types.values():
492 if type_.get("NAME") == token:
498 """Makes sure that 'toktype' equals 'type', reads the next token, and
499 returns the previous 'token'.
503 sys.stderr.write("parse error at `%s' expecting %s\n" % (token, type_))
510 """If 'token' equals 'tok', reads the next token and returns true.
511 Otherwise, returns false."""
518 def force_match(tok):
519 """If 'token' equals 'tok', reads the next token. Otherwise, flags an
523 sys.stderr.write("parse error at `%s' expecting `%s'\n" % (token, tok))
527 """Parses and returns a function argument."""
529 arg['TYPE'] = parse_type()
530 if arg['TYPE'] is None:
531 arg['TYPE'] = types['number']
534 sys.stderr.write("argument name expected at `%s'\n" % token)
540 print("line[0]=%s" % line[0])
543 print('token=%s toktype=%s' % (token, toktype))
545 if arg['TYPE']['NAME'] not in ('number', 'string'):
546 sys.stderr.write('only double and string arrays supported\n')
548 arg['IDX'] = force('id')
550 arg['TIMES'] = force('int')
551 if arg['TIMES'] != 2:
552 sys.stderr.write('multiplication factor must be two\n')
558 arg['CONDITION'] = arg['NAME'] + ' ' + accumulate_balanced(',)', swallow_end=False)
563 """Prints the output file header."""
566 Generated from %s by generate.py.
569 """ % (out_file_name, in_file_name))
572 """Prints the output file trailer."""
583 def generate_evaluate_h():
584 out_file.write("#include \"helpers.h\"\n\n")
588 if op['UNIMPLEMENTED']:
592 for arg in op['ARGS']:
594 args += [c_type(arg['TYPE']) + arg['NAME']]
596 args += [c_type(arg['TYPE']) + arg['NAME'] + '[]']
597 args += ['size_t %s' % arg['IDX']]
598 for aux in op['AUX']:
599 args += [c_type(aux['TYPE']) + aux['NAME']]
604 statements = op['BLOCK'] + '\n'
606 statements = " return %s;\n" % op['EXPRESSION']
608 out_file.write("static inline %s\n" % c_type (op['RETURNS']))
609 out_file.write("eval_%s (%s)\n" % (opname, ', '.join(args)))
610 out_file.write("{\n")
611 out_file.write(statements)
612 out_file.write("}\n\n")
614 def generate_evaluate_inc():
617 if op['UNIMPLEMENTED']:
618 out_file.write("case %s:\n" % opname)
619 out_file.write(" NOT_REACHED ();\n\n")
624 for arg in op['ARGS']:
627 ctype = c_type(type_)
628 args += ['arg_%s' % name]
630 decl = '%sarg_%s' % (ctype, name)
631 if type_['ROLE'] == 'any':
632 decls = ['%s = *--%s' % (decl, type_['STACK'])] + decls
633 elif type_['ROLE'] == 'leaf':
634 decls += ['%s = op++->%s' % (decl, type_['ATOM'])]
639 stack = type_['STACK']
640 decls = ['%s*arg_%s = %s -= arg_%s' % (ctype, name, stack, idx)] + decls
641 decls = ['size_t arg_%s = op++->integer' % idx] + decls
644 if arg['TIMES'] != 1:
645 idx += ' / %s' % arg['TIMES']
647 for aux in op['AUX']:
650 if type_['ROLE'] == 'leaf':
651 ctype = c_type(type_)
652 decls += ['%saux_%s = op++->%s' % (ctype, name, type_['ATOM'])]
653 args += ['aux_%s' % name]
654 elif type_['ROLE'] == 'fixed':
655 args += [type_['FIXED_VALUE']]
657 sysmis_cond = make_sysmis_decl(op, 'op++->integer')
658 if sysmis_cond is not None:
659 decls += [sysmis_cond]
662 result = 'eval_%s (%s)' % (op['OPNAME'], ', '.join(args))
664 stack = op['RETURNS']['STACK']
666 out_file.write("case %s:\n" % opname)
668 out_file.write(" {\n")
670 out_file.write(" %s;\n" % decl)
671 if sysmis_cond is not None:
672 miss_ret = op['RETURNS']['MISSING_VALUE']
673 out_file.write(" *%s++ = force_sysmis ? %s : %s;\n" % (stack, miss_ret, result))
675 out_file.write(" *%s++ = %s;\n" % (stack, result))
676 out_file.write(" }\n")
678 out_file.write(" *%s++ = %s;\n" % (stack, result))
679 out_file.write(" break;\n\n")
681 def generate_operations_h():
682 out_file.write("#include <stdlib.h>\n")
683 out_file.write("#include <stdbool.h>\n\n")
685 out_file.write("typedef enum")
686 out_file.write(" {\n")
688 for type_ in types.values():
689 if type_['ROLE'] != 'fixed':
690 atoms += ["OP_%s" % type_['NAME']]
692 print_operations('atom', 1, atoms)
693 print_operations('function', "OP_atom_last + 1", funcs)
694 print_operations('operator', "OP_function_last + 1", opers)
695 print_range("OP_composite", "OP_function_first", "OP_operator_last")
696 out_file.write(",\n\n")
697 print_range("OP", "OP_atom_first", "OP_composite_last")
698 out_file.write("\n }\n")
699 out_file.write("operation_type, atom_type;\n")
701 print_predicate('is_operation', 'OP')
702 for key in ('atom', 'composite', 'function', 'operator'):
703 print_predicate("is_%s" % key, "OP_%s" % key)
705 def print_operations(type_, first, names):
706 out_file.write(" /* %s types. */\n" % type_.title())
707 out_file.write(" %s = %s,\n" % (names[0], first))
708 for name in names[1:]:
709 out_file.write(" %s,\n" % name)
710 print_range("OP_%s" % type_, names[0], names[len(names) - 1])
711 out_file.write(",\n\n")
713 def print_range(prefix, first, last):
714 out_file.write(" %s_first = %s,\n" % (prefix, first))
715 out_file.write(" %s_last = %s,\n" % (prefix, last))
716 out_file.write(" n_%s = %s_last - %s_first + 1" % (prefix, prefix, prefix))
718 def print_predicate(function, category):
721 out_file.write("\nstatic inline bool\n")
722 out_file.write("%s (operation_type op)\n" % function)
723 out_file.write("{\n")
724 if function != 'is_operation':
725 out_file.write(" assert (is_operation (op));\n")
726 out_file.write(" return op >= %s_first && op <= %s_last;\n" % (category, category))
727 out_file.write("}\n")
729 def generate_optimize_inc():
733 if not op['OPTIMIZABLE'] or op['UNIMPLEMENTED']:
734 out_file.write("case %s:\n" % opname)
735 out_file.write(" NOT_REACHED ();\n\n")
740 for arg in op['ARGS']:
743 ctype = c_type(type_)
745 func = "get_%s_arg" % type_['ATOM']
746 decls += ["%sarg_%s = %s (node, %s)" % (ctype, name, func, arg_idx)]
749 decl = "size_t arg_%s = node->n_args" % idx
751 decl += " - %s" % arg_idx
754 decls += ["%s*arg_%s = get_%s_args (node, %s, arg_%s, e)" % (ctype, name, type_['ATOM'], arg_idx, idx)]
757 sysmis_cond = make_sysmis_decl (op, "node->min_valid")
758 if sysmis_cond is not None:
759 decls += [sysmis_cond]
762 for arg in op['ARGS']:
763 args += ["arg_%s" % arg['NAME']]
765 idx = 'arg_%s' % arg['IDX']
766 if arg['TIMES'] != 1:
767 idx += " / %s" % arg['TIMES']
770 for aux in op['AUX']:
772 if type_['ROLE'] == 'leaf':
773 func = "get_%s_arg" % type_['ATOM']
774 args += "%s (node, %s)" % (func, arg_idx)
776 elif type_['ROLE'] == 'fixed':
777 args += [type_['FIXED_VALUE']]
781 result = "eval_%s (%s)" % (op['OPNAME'], ', '.join(args))
782 if decls and sysmis_cond is not None:
783 miss_ret = op['RETURNS']['MISSING_VALUE']
784 decls += ['%sresult = force_sysmis ? %s : %s' % (c_type(op['RETURNS']), miss_ret, result)]
787 out_file.write("case %s:\n" % opname)
788 alloc_func = "expr_allocate_%s" % op['RETURNS']['NAME']
790 out_file.write(" {\n")
792 out_file.write(" %s;\n" % decl)
793 out_file.write(" return %s (e, %s);\n" % (alloc_func, result))
794 out_file.write(" }\n")
796 out_file.write(" return %s (e, %s);\n" % (alloc_func, result))
799 def generate_parse_inc():
800 members = ['""', '""', '0', '0', '0', "{}", '0', '0']
801 out_file.write("{%s},\n" % ', '.join(members))
803 for type_ in types.values():
804 if type_['ROLE'] != 'fixed':
805 human_name = type_.get('HUMAN_NAME', type_['NAME'])
806 members = ('"%s"' % type_['NAME'], '"%s"' % human_name, '0', "OP_%s" % type_['NAME'], '0', "{}", '0', '0')
807 out_file.write("{%s},\n" % ', '.join(members))
813 members += ['"%s"' % op['NAME']]
815 if op['CATEGORY'] == 'function':
818 for arg in op['ARGS']:
820 args += [arg['TYPE']['HUMAN_NAME']]
822 array = array_arg(op)
823 if array is not None:
824 if op['MIN_VALID'] == 0:
826 for i in range(array['TIMES']):
827 array_args += [array['TYPE']['HUMAN_NAME']]
829 opt_args = array_args
831 for i in range(op['MIN_VALID']):
832 args += [array['TYPE']['HUMAN_NAME']]
833 opt_args += [array['TYPE']['HUMAN_NAME']]
834 human = "%s(%s" % (op['NAME'], ', '.join(args))
836 human += '[, %s]...' % ', '.join(opt_args)
838 members += ['"%s"' % human]
843 if op['ABSORB_MISS']:
844 flags += ['OPF_ABSORB_MISS']
846 flags += ['OPF_ARRAY_OPERAND']
847 if op['MIN_VALID'] > 0:
848 flags += ['OPF_MIN_VALID']
849 if not op['OPTIMIZABLE']:
850 flags += ['OPF_NONOPTIMIZABLE']
852 flags += ['OPF_EXTENSION']
853 if op['UNIMPLEMENTED']:
854 flags += ['OPF_UNIMPLEMENTED']
856 flags += ['OPF_PERM_ONLY']
858 flags += ['OPF_NO_ABBREV']
859 members += [' | '.join(flags) if flags else '0']
861 members += ['OP_%s' % op['RETURNS']['NAME']]
863 members += ['%s' % len(op['ARGS'])]
865 arg_types = ["OP_%s" % arg['TYPE']['NAME'] for arg in op['ARGS']]
866 members += ['{%s}' % ', '.join(arg_types)]
868 members += ['%s' % op['MIN_VALID']]
870 members += ['%s' % (array_arg(op)['TIMES'] if array_arg(op) else 0)]
872 out_file.write('{%s},\n' % ', '.join(members))
876 def make_sysmis_decl(op, min_valid_src):
877 """Returns a declaration for a boolean variable called `force_sysmis',
878 which will be true when operation 'op' should be system-missing.
879 Returns None if there are no such circumstances.
881 If 'op' has a minimum number of valid arguments, 'min_valid_src'
882 should be an an expression that evaluates to the minimum number of
883 valid arguments for 'op'.
887 if not op['ABSORB_MISS']:
888 for arg in op['ARGS']:
889 arg_name = 'arg_%s' % arg['NAME']
891 if arg['TYPE']['NAME'] in ['number', 'boolean']:
892 sysmis_cond += ["!is_valid (%s)" % arg_name]
893 elif arg['TYPE']['NAME'] == 'number':
895 n = 'arg_%s' % arg['IDX']
896 sysmis_cond += ['count_valid (%s, %s) < %s' % (a, n, n)]
897 elif op['MIN_VALID'] > 0:
900 a = 'arg_%s' % arg['NAME']
901 n = 'arg_%s' % arg['IDX']
902 sysmis_cond += ["count_valid (%s, %s) < %s" % (a, n, min_valid_src)]
903 for arg in op['ARGS']:
904 if 'CONDITION' in arg:
905 sysmis_cond += ['!(%s)' % arg['CONDITION']]
907 return 'bool force_sysmis = %s' % ' || '.join(sysmis_cond)
911 """If 'op' has an array argument, returns it. Otherwise, returns
917 if 'IDX' in last_arg:
923 %(argv0)s, for generating expression parsers and evaluators from definitions
924 usage: generate.pl -o OUTPUT [-i INPUT] [-h]
925 -i INPUT input file containing definitions (default: operations.def)
926 -o OUTPUT output file
927 -h display this help message
928 """ % {'argv0': argv0})
931 if __name__ == "__main__":
933 options, args = getopt.gnu_getopt(sys.argv[1:], 'hi:o:',
937 except getopt.GetoptError as geo:
938 sys.stderr.write("%s: %s\n" % (argv0, geo.msg))
941 in_file_name = 'operations.def'
943 for key, value in options:
944 if key in ['-h', '--help']:
946 elif key in ['-i', '--input']:
948 elif key in ['-o', '--output']:
949 out_file_name = value
953 if out_file_name is None:
954 sys.stderr.write("%(argv0)s: output file must be specified "
955 "(use --help for help)\n" % {'argv0': argv0})
958 in_file = open(in_file_name, 'r')
959 out_file = open(out_file_name, 'w')
965 if out_file_name.endswith('evaluate.h'):
966 generate_evaluate_h()
967 elif out_file_name.endswith('evaluate.inc'):
968 generate_evaluate_inc()
969 elif out_file_name.endswith('operations.h'):
970 generate_operations_h()
971 elif out_file_name.endswith('optimize.inc'):
972 generate_optimize_inc()
973 elif out_file_name.endswith('parse.inc'):
976 sys.stderr.write("%(argv0)s: unknown output type\n")