Mercurial > octave
comparison build-aux/mk-opts.pl @ 12733:b67c2d580a25 stable
maint: clean up top-level directory
* build-aux/bootstrap: Rename from bootstrap.
* build-aux/bootstrap.conf: Rename from bootstrap.conf.
* build-aux/changelog.tmpl: Rename from changelog.tmpl.
* build-aux/bootstrap.conf: Update for new file locations.
* build-aux/common.mk: Rename from common.mk.
* build-aux/diff-template: Rename from diff-template.
* build-aux/mk-opts.pl: Rename from mk-opts.pl.
* build-aux/mkinstalldirs: Rename from mkinstalldirs.
* build-aux/move-if-change: Rename from move-if-change.
* etc/CHECKLIST: Rename from CHECKLIST.
* etc/HACKING: Rename from HACKING.
* etc/NEWS.1: Rename from NEWS.1.
* etc/NEWS.2: Rename from NEWS.2.
* etc/NEWS.3: Rename from NEWS.3.
* etc/OLD-ChangeLogs/ChangeLog: Rename from OLD-ChangeLogs/ChangeLog.
* etc/OLD-ChangeLogs/ChangeLog.1: Rename from
OLD-ChangeLogs/ChangeLog.1.
* etc/OLD-ChangeLogs/doc-ChangeLog: Rename from
OLD-ChangeLogs/doc-ChangeLog.
* etc/OLD-ChangeLogs/libcruft-ChangeLog: Rename from
OLD-ChangeLogs/libcruft-ChangeLog.
* etc/OLD-ChangeLogs/liboctave-ChangeLog: Rename from
OLD-ChangeLogs/liboctave-ChangeLog.
* etc/OLD-ChangeLogs/scripts-ChangeLog: Rename from
OLD-ChangeLogs/scripts-ChangeLog.
* etc/OLD-ChangeLogs/src-ChangeLog: Rename from
OLD-ChangeLogs/src-ChangeLog.
* etc/OLD-ChangeLogs/test-ChangeLog: Rename from
OLD-ChangeLogs/test-ChangeLog.
* etc/PROJECTS: Rename from PROJECTS.
* etc/README.Cygwin: Rename from README.Cygwin.
* etc/README.Linux: Rename from README.Linux.
* etc/README.MacOS: Rename from README.MacOS.
* etc/README.MinGW: Rename from README.MinGW.
* etc/README.Windows: Rename from README.Windows.
* etc/README.devel: Rename from README.devel.
* etc/README.ftp: Rename from README.ftp.
* etc/README.gnuplot: Rename from README.gnuplot.
* etc/README.kpathsea: Rename from README.kpathsea.
* etc/README.mirrors: Rename from README.mirrors.
* etc/README.snapshots: Rename from README.snapshots.
* etc/gdbinit: Rename from gdbinit.
* m4/acinclude.m4: Rename from acinclude.m4.
* src/mkoctfile.cc.in: Rename from mkoctfile.cc.in.
* src/mkoctfile.in: Rename from mkoctfile.in.
* src/octave-config.cc.in: Rename from octave-config.cc.in.
* src/octave-config.in: Rename from octave-config.in.
* config.guess, config.sub, missing, octave-sh: Delete.
* Makefile.am: Include build-aux/common.mk instead of common.mk.
* examples/Makefile.am, libcruft/Makefile.am,
liboctave/Makefile.am, liboctave/config-ops.sh,
scripts/Makefile.am, src/DLD-FUNCTIONS/config-module.sh,
test/Makefile.am, autogen.sh, doc/Makefile.am,
doc/faq/Makefile.am, doc/icons/Makefile.am,
doc/interpreter/Makefile.am, doc/interpreter/config-images.sh,
doc/liboctave/Makefile.am, doc/refcard/Makefile.am,
build-aux/common.mk, src/Makefile.am: Update for new file locations.
* Makefile.am: Don't build mkoctfile or octave-config here.
* README: Update INSTALL info.
* build-aux/mkinstalldirs: Update to new version.
* src/Makefile.am (mkoctfile, octave-config): New targets.
author | John W. Eaton <jwe@octave.org> |
---|---|
date | Fri, 10 Jun 2011 14:35:42 -0400 |
parents | mk-opts.pl@16cca721117b |
children | 72c96de7a403 |
comparison
equal
deleted
inserted
replaced
12732:10f6727fbaa8 | 12733:b67c2d580a25 |
---|---|
1 #! /usr/bin/perl -w | |
2 # | |
3 # Copyright (C) 2002-2011 John W. Eaton | |
4 # | |
5 # This file is part of Octave. | |
6 # | |
7 # Octave is free software; you can redistribute it and/or modify it | |
8 # under the terms of the GNU General Public License as published by the | |
9 # Free Software Foundation; either version 3 of the License, or (at | |
10 # your option) any later version. | |
11 # | |
12 # Octave is distributed in the hope that it will be useful, but WITHOUT | |
13 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
14 # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
15 # for more details. | |
16 # | |
17 # You should have received a copy of the GNU General Public License | |
18 # along with Octave; see the file COPYING. If not, see | |
19 # <http://www.gnu.org/licenses/>. | |
20 | |
21 # Generate option handling code from a simpler input files for | |
22 # Octave's functions like lsode, dassl, etc. | |
23 | |
24 # FIXME: | |
25 # | |
26 # * Improve default documentation and/or individual documentation | |
27 # in data files. | |
28 # | |
29 # * Fix print/show code to display/return something more informative | |
30 # for special values (for example, -1 ==> infinite in some cases). | |
31 # Probably need more information in the data files for this. | |
32 | |
33 # Input file format: | |
34 # | |
35 # CLASS = string | |
36 # FCN_NAME = string | |
37 # INCLUDE = file | |
38 # DOC_STRING doc END_DOC_STRING | |
39 # OPTION | |
40 # NAME = string | |
41 # DOC_ITEM doc END_DOC_ITEM | |
42 # TYPE = string | |
43 # SET_ARG_TYPE = string (optional, defaults to TYPE) | |
44 # INIT_VALUE = string | INIT_BODY code END_INIT_BODY | |
45 # SET_EXPR = string | SET_BODY code END_SET_BODY | SET_CODE code END_SET_CODE | |
46 # END_OPTION | |
47 # | |
48 # END_* must appear at beginning of line (whitespace ignored). | |
49 | |
50 ################################################################################ | |
51 # Load packages to | |
52 # 1) process command line options | |
53 ################################################################################ | |
54 use Getopt::Long; | |
55 | |
56 ################################################################################ | |
57 # Extract command line arguments | |
58 &parse_options; | |
59 | |
60 $DEFN_FILE = shift @ARGV; | |
61 open (DEFN_FILE) or die "unable to open input definition file $DEFN_FILE"; | |
62 | |
63 ################################################################################ | |
64 # Initialize variables | |
65 $BLANK_LINE = qr/^\s*$/; | |
66 $COMMENT = qr/^\s*#/; | |
67 | |
68 ################################################################################ | |
69 # Process file | |
70 $OPT_NUM = 0; | |
71 | |
72 &parse_input; | |
73 | |
74 &process_data; | |
75 | |
76 # Produce desired style of output | |
77 &emit_opt_class_header if $opt_class_header; | |
78 &emit_opt_handler_fcns if $opt_handler_fcns; | |
79 &emit_options_debug if $opt_debug; | |
80 | |
81 # End of main code | |
82 | |
83 ################################################################################ | |
84 # Subroutines | |
85 ################################################################################ | |
86 | |
87 sub parse_input | |
88 { | |
89 LINE: while (<DEFN_FILE>) | |
90 { | |
91 next LINE if /$BLANK_LINE/; | |
92 next LINE if /$COMMENT/; | |
93 | |
94 if (/^\s*OPTION\s*$/) | |
95 { | |
96 &parse_option_block; | |
97 } | |
98 elsif (/^\s*CLASS\s*=\s*"(\w+)"\s*$/) | |
99 { | |
100 die "duplicate CLASS" if defined $CLASS; | |
101 $CLASS = $1; | |
102 $CLASS_NAME = "${CLASS}_options"; | |
103 $STRUCT_NAME = "${CLASS_NAME}_struct"; | |
104 $STATIC_TABLE_NAME = "${CLASS_NAME}_table"; | |
105 } | |
106 elsif (/^\s*FCN_NAME\s*=\s*"(\w+)"\s*$/) | |
107 { | |
108 die "duplicate FCN_NAME" if defined $FCN_NAME; | |
109 $FCN_NAME = $1; | |
110 } | |
111 elsif (/^\s*INCLUDE\s*=\s*"(\S+)"\s*$/) | |
112 { | |
113 $INCLUDE .= "#include <$1>\n"; | |
114 } | |
115 elsif (/^\s*DOC_STRING\s*$/) | |
116 { | |
117 die "duplicate DOC_STRING" if defined $DOC_STRING; | |
118 while (defined ($_ = <DEFN_FILE>) and not /^\s*END_DOC_STRING\s*$/) | |
119 { | |
120 $DOC_STRING .= $_; | |
121 } | |
122 $DOC_STRING =~ s/\n/\\n\\\n/g; | |
123 } | |
124 else | |
125 { | |
126 die "mk-opts.pl: unknown command: $_\n" | |
127 } | |
128 } | |
129 $INCLUDE = "" if not defined $INCLUDE; # Initialize value if required | |
130 } | |
131 | |
132 sub parse_option_block | |
133 { | |
134 while (<DEFN_FILE>) | |
135 { | |
136 next if /$BLANK_LINE/; | |
137 | |
138 die "missing END_OPTION" if /^\s*OPTION\s*$/; | |
139 | |
140 last if /^\s*END_OPTION\s*$/; | |
141 | |
142 if (/^\s*NAME\s*=\s*"(.*)"\s*$/) | |
143 { | |
144 die "duplicate NAME" if defined $NAME[$OPT_NUM]; | |
145 $NAME[$OPT_NUM] = $1; | |
146 ($OPT[$OPT_NUM] = $NAME[$OPT_NUM]) =~ s/\s+/_/g; | |
147 $OPTVAR[$OPT_NUM] = 'x_' . $OPT[$OPT_NUM]; | |
148 $KW_TOK[$OPT_NUM] = [ split (' ', $NAME[$OPT_NUM]) ]; | |
149 $N_TOKS[$OPT_NUM] = @{$KW_TOK[$OPT_NUM]}; | |
150 } | |
151 elsif (/^\s*DOC_ITEM\s*$/) | |
152 { | |
153 die "duplicate DOC_ITEM" if defined $DOC_ITEM[$OPT_NUM]; | |
154 while (defined ($_ = <DEFN_FILE>) and not /^\s*END_DOC_ITEM\s*$/) | |
155 { | |
156 $DOC_ITEM[$OPT_NUM] .= $_; | |
157 } | |
158 $DOC_ITEM[$OPT_NUM] =~ s/\n/\\n\\\n/g; | |
159 } | |
160 elsif (/^\s*TYPE\s*=\s*"(.*)"\s*$/) | |
161 { | |
162 die "duplicate TYPE" if defined $TYPE[$OPT_NUM]; | |
163 $TYPE[$OPT_NUM] = $1; | |
164 } | |
165 elsif (/^\s*SET_ARG_TYPE\s*=\s*"(.*)"\s*$/) | |
166 { | |
167 die "duplicate SET_ARG_TYPE" if defined $SET_ARG_TYPE[$OPT_NUM]; | |
168 $SET_ARG_TYPE[$OPT_NUM] = $1; | |
169 } | |
170 elsif (/^\s*INIT_VALUE\s*=\s*"(.*)"\s*$/) | |
171 { | |
172 die "duplicate INIT_VALUE" if defined $INIT_VALUE[$OPT_NUM]; | |
173 $INIT_VALUE[$OPT_NUM] = $1; | |
174 } | |
175 elsif (/^\s*SET_EXPR\s*=\s*"(.*)"\s*$/) | |
176 { | |
177 die "duplicate SET_EXPR" if defined $SET_EXPR[$OPT_NUM]; | |
178 $SET_EXPR[$OPT_NUM] = $1; | |
179 } | |
180 elsif (/^\s*INIT_BODY\s*$/) | |
181 { | |
182 die "duplicate INIT_BODY" if defined $INIT_BODY[$OPT_NUM]; | |
183 while (defined ($_ = <DEFN_FILE>) and not /^\s*END_INIT_BODY\s*$/) | |
184 { | |
185 $INIT_BODY[$OPT_NUM] .= $_; | |
186 } | |
187 } | |
188 elsif (/^\s*SET_BODY\s*$/) | |
189 { | |
190 die "duplicate SET_BODY" if defined $INIT_BODY[$OPT_NUM]; | |
191 while (defined ($_ = <DEFN_FILE>) and not /^\s*END_SET_BODY\s*$/) | |
192 { | |
193 $SET_BODY[$OPT_NUM] .= $_; | |
194 } | |
195 } | |
196 elsif (/^\s*SET_CODE\s*$/) | |
197 { | |
198 die "duplicate SET_CODE" if defined $SET_CODE[$OPT_NUM]; | |
199 while (defined ($_ = <DEFN_FILE>) and not /^\s*END_SET_CODE\s*$/) | |
200 { | |
201 $SET_CODE[$OPT_NUM] .= $_; | |
202 } | |
203 } | |
204 } | |
205 | |
206 if (not defined $SET_ARG_TYPE[$OPT_NUM]) | |
207 { | |
208 $SET_ARG_TYPE[$OPT_NUM] = $TYPE[$OPT_NUM]; | |
209 } | |
210 else | |
211 { | |
212 $SET_ARG_TYPE[$OPT_NUM] | |
213 = substopt ($SET_ARG_TYPE[$OPT_NUM], $OPTVAR[$OPT_NUM], | |
214 $OPT[$OPT_NUM], $TYPE[$OPT_NUM]); | |
215 } | |
216 | |
217 $OPT_NUM++; | |
218 } | |
219 | |
220 sub process_data | |
221 { | |
222 $MAX_TOKENS = max (@N_TOKS); | |
223 | |
224 &get_min_match_len_info; | |
225 | |
226 $FCN_NAME = lc ($CLASS) if not defined $FCN_NAME; | |
227 | |
228 $OPT_FCN_NAME = "${FCN_NAME}_options" if not defined $OPT_FCN_NAME; | |
229 | |
230 $STATIC_OBJECT_NAME = "${FCN_NAME}_opts"; | |
231 | |
232 if (not defined $DOC_STRING) | |
233 { | |
234 $DOC_STRING = "Query or set options for the function \@code{$FCN_NAME}.\\n\\ | |
235 When called with no arguments, the names of all available options and\\n\\ | |
236 their current values are displayed.\\n\\ | |
237 Given one argument, return the value of the corresponding option.\\n\\ | |
238 When called with two arguments, \@code{$OPT_FCN_NAME} set the option\\n\\ | |
239 \@var{opt} to value \@var{val}."; | |
240 } | |
241 } | |
242 | |
243 #FIXME: What does this routine do? And can it be simpler to understand? | |
244 sub get_min_match_len_info | |
245 { | |
246 my ($i, $j, $k); | |
247 | |
248 for ($i = 0; $i < $OPT_NUM; $i++) | |
249 { | |
250 for ($j = 0; $j < $MAX_TOKENS; $j++) | |
251 { | |
252 $MIN_TOK_LEN_TO_MATCH[$i][$j] = 0; | |
253 } | |
254 | |
255 $MIN_TOKS_TO_MATCH[$i] = 1; | |
256 | |
257 L1: for ($k = 0; $k < $OPT_NUM; $k++) | |
258 { | |
259 my $duplicate = 1; | |
260 | |
261 if ($i != $k) | |
262 { | |
263 L2: for ($j = 0; $j < $MAX_TOKENS; $j++) | |
264 { | |
265 if ($j < $N_TOKS[$i]) | |
266 { | |
267 if ($KW_TOK[$i][$j] eq $KW_TOK[$k][$j]) | |
268 { | |
269 if ($MIN_TOK_LEN_TO_MATCH[$i][$j] == 0) | |
270 { | |
271 $MIN_TOK_LEN_TO_MATCH[$i][$j] = 1; | |
272 } | |
273 | |
274 $MIN_TOKS_TO_MATCH[$i]++; | |
275 } | |
276 else | |
277 { | |
278 $duplicate = 0; | |
279 | |
280 if ($MIN_TOK_LEN_TO_MATCH[$i][$j] == 0) | |
281 { | |
282 $MIN_TOK_LEN_TO_MATCH[$i][$j] = 1; | |
283 } | |
284 | |
285 my @s = split (//, $KW_TOK[$i][$j]); | |
286 my @t = split (//, $KW_TOK[$k][$j]); | |
287 | |
288 my ($n, $ii); | |
289 $n = scalar (@s); | |
290 $n = scalar (@t) if (@t < $n); | |
291 | |
292 for ($ii = 0; $ii < $n; $ii++) | |
293 { | |
294 if ("$s[$ii]" eq "$t[$ii]") | |
295 { | |
296 if ($ii + 2 > $MIN_TOK_LEN_TO_MATCH[$i][$j]) | |
297 { | |
298 $MIN_TOK_LEN_TO_MATCH[$i][$j]++; | |
299 } | |
300 } | |
301 else | |
302 { | |
303 last L2; | |
304 } | |
305 } | |
306 | |
307 last L1; | |
308 } | |
309 } | |
310 else | |
311 { | |
312 die qq|ambiguous options "$NAME[$i]" and "$NAME[$k]"| if $duplicate; | |
313 } | |
314 } | |
315 } | |
316 } | |
317 } | |
318 } # end of get_min_match_len_info | |
319 | |
320 | |
321 sub emit_copy_body | |
322 { | |
323 my ($pfx, $var) = @_; | |
324 | |
325 for (my $i = 0; $i < $OPT_NUM; $i++) | |
326 { | |
327 print "${pfx}$OPTVAR[$i] = ${var}.$OPTVAR[$i];\n"; | |
328 } | |
329 | |
330 print "${pfx}reset = ${var}.reset;\n"; | |
331 } | |
332 | |
333 ## To silence GCC warnings, we create an initialization list even | |
334 ## though the init function actually does the work of initialization. | |
335 | |
336 sub emit_default_init_list | |
337 { | |
338 my ($prefix) = @_; | |
339 | |
340 print "$OPTVAR[0] (),\n" unless ($OPT_NUM == 0); | |
341 | |
342 for (my $i = 1; $i < $OPT_NUM; $i++) | |
343 { | |
344 print "${prefix}$OPTVAR[$i] (),\n"; | |
345 } | |
346 | |
347 print "${prefix}reset ()\n"; | |
348 } | |
349 | |
350 sub emit_copy_ctor_init_list | |
351 { | |
352 my ($prefix, $var) = @_; | |
353 | |
354 print "$OPTVAR[0] ($var.$OPTVAR[0]),\n" unless ($OPT_NUM == 0); | |
355 | |
356 for (my $i = 1; $i < $OPT_NUM; $i++) | |
357 { | |
358 print "${prefix}$OPTVAR[$i] ($var.$OPTVAR[$i]),\n"; | |
359 } | |
360 | |
361 print "${prefix}reset ($var.reset)\n"; | |
362 } | |
363 | |
364 sub emit_opt_class_header | |
365 { | |
366 my ($i, $s); | |
367 | |
368 print <<"_END_EMIT_OPT_CLASS_HEADER_"; | |
369 // DO NOT EDIT! | |
370 // Generated automatically from $DEFN_FILE. | |
371 | |
372 #if !defined (octave_${CLASS_NAME}_h) | |
373 #define octave_${CLASS_NAME}_h 1 | |
374 | |
375 #include <cfloat> | |
376 #include <cmath> | |
377 | |
378 $INCLUDE | |
379 | |
380 class | |
381 $CLASS_NAME | |
382 { | |
383 public: | |
384 | |
385 $CLASS_NAME (void) | |
386 _END_EMIT_OPT_CLASS_HEADER_ | |
387 | |
388 print ' : '; | |
389 emit_default_init_list (" "); | |
390 | |
391 print " { | |
392 init (); | |
393 } | |
394 | |
395 $CLASS_NAME (const ${CLASS_NAME}& opt) | |
396 : "; | |
397 | |
398 emit_copy_ctor_init_list (" ", "opt"); | |
399 | |
400 print " { } | |
401 | |
402 ${CLASS_NAME}& operator = (const ${CLASS_NAME}& opt) | |
403 { | |
404 if (this != &opt) | |
405 {\n"; | |
406 | |
407 emit_copy_body (' ', 'opt'); | |
408 | |
409 print " } | |
410 | |
411 return *this; | |
412 } | |
413 | |
414 ~$CLASS_NAME (void) { }\n"; | |
415 | |
416 print "\n void init (void)\n {\n"; | |
417 | |
418 for ($i = 0; $i < $OPT_NUM; $i++) | |
419 { | |
420 if ($INIT_VALUE[$i]) | |
421 { | |
422 print " $OPTVAR[$i] = $INIT_VALUE[$i];\n"; | |
423 } | |
424 elsif ($INIT_BODY[$i]) | |
425 { | |
426 $s = substopt ($INIT_BODY[$i], $OPTVAR[$i], $OPT[$i], $TYPE[$i]); | |
427 chomp ($s); | |
428 $s =~ s/^\s*/ /g; | |
429 $s =~ s/\n\s*/\n /g; | |
430 print $s,"\n"; | |
431 } | |
432 } | |
433 | |
434 print " reset = true;\n", | |
435 " }\n"; | |
436 | |
437 ## For backward compatibility and because set_options is probably | |
438 ## a better name in some contexts: | |
439 | |
440 print "\n void set_options (const ${CLASS_NAME}& opt)\n", | |
441 " {\n"; | |
442 | |
443 emit_copy_body (' ', 'opt'); | |
444 | |
445 print " }\n\n void set_default_options (void) { init (); }\n"; | |
446 | |
447 for ($i = 0; $i < $OPT_NUM; $i++) | |
448 { | |
449 if ($SET_EXPR[$i]) | |
450 { | |
451 emit_set_decl ($i); | |
452 | |
453 print "\n { $OPTVAR[$i] = $SET_EXPR[$i]; reset = true; }\n"; | |
454 } | |
455 elsif ($SET_BODY[$i]) | |
456 { | |
457 emit_set_decl ($i); | |
458 | |
459 $s = substopt ($SET_BODY[$i], $OPTVAR[$i], $OPT[$i], $TYPE[$i]); | |
460 chomp ($s); | |
461 $s = ' ' . $s; | |
462 $s =~ s/\n/\n /g; | |
463 print "\n {\n$s\n reset = true;\n }\n"; | |
464 } | |
465 elsif ($SET_CODE[$i]) | |
466 { | |
467 $s = substopt ($SET_CODE[$i], $OPTVAR[$i], $OPT[$i], $TYPE[$i]); | |
468 chomp ($s); | |
469 $s =~ s/^ //g; | |
470 $s =~ s/\n /\n/g; | |
471 print "\n",$s,"\n"; | |
472 } | |
473 } | |
474 | |
475 for ($i = 0; $i < $OPT_NUM; $i++) | |
476 { | |
477 print " $TYPE[$i] $OPT[$i] (void) const\n { return $OPTVAR[$i]; }\n\n"; | |
478 } | |
479 | |
480 print "private:\n\n"; | |
481 | |
482 for ($i = 0; $i < $OPT_NUM; $i++) | |
483 { | |
484 print " $TYPE[$i] $OPTVAR[$i];\n"; | |
485 } | |
486 | |
487 print "\nprotected:\n\n bool reset;\n};\n\n#endif\n"; | |
488 } | |
489 | |
490 sub emit_set_decl | |
491 { | |
492 my ($i) = @_; | |
493 | |
494 print "\n void set_$OPT[$i] ($SET_ARG_TYPE[$i] val)"; | |
495 } | |
496 | |
497 sub emit_opt_handler_fcns | |
498 { | |
499 my $header = $DEFN_FILE; | |
500 $header =~ s/[.]\w*$/.h/; # replace .in with .h | |
501 $header =~ s|^.*/([^/]*)$|$1|; # strip directory part | |
502 | |
503 print <<"_END_EMIT_OPT_HANDLER_FCNS_"; | |
504 // DO NOT EDIT! | |
505 // Generated automatically from $DEFN_FILE. | |
506 | |
507 #ifdef HAVE_CONFIG_H | |
508 #include <config.h> | |
509 #endif | |
510 | |
511 #include <iomanip> | |
512 #include <iostream> | |
513 | |
514 #include "$header" | |
515 | |
516 #include "defun-dld.h" | |
517 #include "pr-output.h" | |
518 | |
519 #include "oct-obj.h" | |
520 #include "utils.h" | |
521 #include "pager.h" | |
522 | |
523 static $CLASS_NAME $STATIC_OBJECT_NAME; | |
524 | |
525 _END_EMIT_OPT_HANDLER_FCNS_ | |
526 | |
527 &emit_struct_decl; | |
528 | |
529 &emit_struct_def; | |
530 | |
531 &emit_print_function; | |
532 | |
533 &emit_set_functions; | |
534 | |
535 &emit_show_function; | |
536 | |
537 &emit_options_function; | |
538 } | |
539 | |
540 sub emit_struct_decl | |
541 { | |
542 print <<"_END_PRINT_STRUCT_DECL_"; | |
543 #define MAX_TOKENS $MAX_TOKENS | |
544 | |
545 struct $STRUCT_NAME | |
546 { | |
547 const char *keyword; | |
548 const char *kw_tok[MAX_TOKENS + 1]; | |
549 int min_len[MAX_TOKENS + 1]; | |
550 int min_toks_to_match; | |
551 }; | |
552 | |
553 _END_PRINT_STRUCT_DECL_ | |
554 } | |
555 | |
556 sub emit_struct_def | |
557 { | |
558 my $i; | |
559 | |
560 print "#define NUM_OPTIONS $OPT_NUM\n\n"; | |
561 | |
562 print "static $STRUCT_NAME $STATIC_TABLE_NAME [] =\n{\n"; | |
563 | |
564 for ($i = 0; $i < ($OPT_NUM - 1); $i++) | |
565 { | |
566 emit_option_table_entry ($i, 0); | |
567 print "\n"; | |
568 } | |
569 emit_option_table_entry ($i, 0); | |
570 | |
571 print "};\n\n"; | |
572 } | |
573 | |
574 sub emit_option_table_entry | |
575 { | |
576 my ($i, $empty) = @_; | |
577 | |
578 my $k; | |
579 | |
580 if ($empty) | |
581 { | |
582 print " { 0,\n"; | |
583 } | |
584 else | |
585 { | |
586 print " { \"$NAME[$i]\",\n"; | |
587 } | |
588 | |
589 my $n = scalar $#{$KW_TOK[$i]}; | |
590 print " {"; | |
591 for $k (0 .. $MAX_TOKENS) | |
592 { | |
593 if ($empty or $k > $n) | |
594 { | |
595 print " 0,"; | |
596 } | |
597 else | |
598 { | |
599 print " \"$KW_TOK[$i][$k]\","; | |
600 } | |
601 } | |
602 print " },\n"; | |
603 | |
604 print " {"; | |
605 for $k (0 .. $MAX_TOKENS) | |
606 { | |
607 if ($empty or $k > $n) | |
608 { | |
609 print " 0,"; | |
610 } | |
611 else | |
612 { | |
613 print " $MIN_TOK_LEN_TO_MATCH[$i][$k],"; | |
614 } | |
615 } | |
616 print " }, $MIN_TOKS_TO_MATCH[$i], "; | |
617 | |
618 print "},\n"; | |
619 } | |
620 | |
621 sub emit_print_function | |
622 { | |
623 ## FIXME -- determine the width of the table automatically. | |
624 | |
625 print qq|static void | |
626 print_$CLASS_NAME (std::ostream& os) | |
627 { | |
628 std::ostringstream buf; | |
629 | |
630 os << "\\n" | |
631 << "Options for $CLASS include:\\n\\n" | |
632 << " keyword value\\n" | |
633 << " ------- -----\\n"; | |
634 | |
635 $STRUCT_NAME *list = $STATIC_TABLE_NAME;\n\n|; | |
636 | |
637 for (my $i = 0; $i < $OPT_NUM; $i++) | |
638 { | |
639 print qq| {\n os << " " | |
640 << std::setiosflags (std::ios::left) << std::setw (50) | |
641 << list[$i].keyword | |
642 << std::resetiosflags (std::ios::left) | |
643 << " ";\n\n|; | |
644 | |
645 if ($TYPE[$i] eq "double") | |
646 { | |
647 print qq| double val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n|; | |
648 print qq| os << val << "\\n";\n|; | |
649 } | |
650 elsif ($TYPE[$i] eq "float") | |
651 { | |
652 print qq| float val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n|; | |
653 print qq| os << val << "\\n";\n|; | |
654 } | |
655 elsif ($TYPE[$i] eq "int" or $TYPE[$i] eq "octave_idx_type") | |
656 { | |
657 print qq| int val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n|; | |
658 print qq| os << val << "\\n";\n|; | |
659 } | |
660 elsif ($TYPE[$i] eq "std::string") | |
661 { | |
662 print qq| os << $STATIC_OBJECT_NAME.$OPT[$i] () << "\\n";\n|; | |
663 } | |
664 elsif ($TYPE[$i] eq "Array<int>" or $TYPE[$i] eq "Array<octave_idx_type>") | |
665 { | |
666 my $elt_type; | |
667 if ($TYPE[$i] eq "Array<int>") | |
668 { | |
669 $elt_type = "int"; | |
670 } | |
671 else | |
672 { | |
673 $elt_type = "octave_idx_type"; | |
674 } | |
675 print qq| Array<$elt_type> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n|; | |
676 print qq| if (val.length () == 1) | |
677 { | |
678 os << val(0) << "\\n"; | |
679 } | |
680 else | |
681 { | |
682 os << "\\n\\n"; | |
683 octave_idx_type len = val.length (); | |
684 Matrix tmp (len, 1); | |
685 for (octave_idx_type i = 0; i < len; i++) | |
686 tmp(i,0) = val(i); | |
687 octave_print_internal (os, tmp, false, 2); | |
688 os << "\\n\\n"; | |
689 }\n|; | |
690 } | |
691 elsif ($TYPE[$i] eq "Array<double>") | |
692 { | |
693 print qq| Array<double> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n|; | |
694 print qq| if (val.length () == 1) | |
695 { | |
696 os << val(0) << "\\n"; | |
697 } | |
698 else | |
699 { | |
700 os << "\\n\\n"; | |
701 Matrix tmp = Matrix (ColumnVector (val)); | |
702 octave_print_internal (os, tmp, false, 2); | |
703 os << "\\n\\n"; | |
704 }\n|; | |
705 } | |
706 elsif ($TYPE[$i] eq "Array<float>") | |
707 { | |
708 print qq| Array<float> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n|; | |
709 print qq| if (val.length () == 1) | |
710 { | |
711 os << val(0) << "\\n"; | |
712 } | |
713 else | |
714 { | |
715 os << "\\n\\n"; | |
716 FloatMatrix tmp = FloatMatrix (FloatColumnVector (val)); | |
717 octave_print_internal (os, tmp, false, 2); | |
718 os << "\\n\\n"; | |
719 }\n|; | |
720 } | |
721 else | |
722 { | |
723 die ("unknown type $TYPE[$i]"); | |
724 } | |
725 | |
726 print " }\n\n"; | |
727 } | |
728 | |
729 print qq| os << "\\n";\n}\n\n|; | |
730 } | |
731 | |
732 sub emit_set_functions | |
733 { | |
734 print "static void | |
735 set_$CLASS_NAME (const std::string& keyword, const octave_value& val) | |
736 { | |
737 $STRUCT_NAME *list = $STATIC_TABLE_NAME;\n\n"; | |
738 | |
739 my $iftok = "if"; | |
740 | |
741 for (my $i = 0; $i < $OPT_NUM; $i++) | |
742 { | |
743 $iftok = "else if" if ($i > 0); | |
744 | |
745 print " $iftok (keyword_almost_match (list[$i].kw_tok, list[$i].min_len, | |
746 keyword, list[$i].min_toks_to_match, MAX_TOKENS)) | |
747 {\n"; | |
748 | |
749 if ($TYPE[$i] eq "double") | |
750 { | |
751 print " double tmp = val.double_value ();\n\n"; | |
752 print " if (! error_state) | |
753 $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\n"; | |
754 } | |
755 elsif ($TYPE[$i] eq "float") | |
756 { | |
757 print " float tmp = val.float_value ();\n\n"; | |
758 print " if (! error_state) | |
759 $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\n"; | |
760 } | |
761 elsif ($TYPE[$i] eq "int" or $TYPE[$i] eq "octave_idx_type") | |
762 { | |
763 print " int tmp = val.int_value ();\n\n"; | |
764 print " if (! error_state) | |
765 $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\n"; | |
766 } | |
767 elsif ($TYPE[$i] eq "std::string") | |
768 { | |
769 print " std::string tmp = val.string_value ();\n\n"; | |
770 print " if (! error_state) | |
771 $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\n"; | |
772 } | |
773 elsif ($TYPE[$i] eq "Array<int>" or $TYPE[$i] eq "Array<octave_idx_type>") | |
774 { | |
775 print " Array<int> tmp = val.int_vector_value ();\n\n"; | |
776 print " if (! error_state) | |
777 $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\n"; | |
778 } | |
779 elsif ($TYPE[$i] eq "Array<double>") | |
780 { | |
781 print " Array<double> tmp = val.vector_value ();\n\n"; | |
782 print " if (! error_state) | |
783 $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\n"; | |
784 } | |
785 elsif ($TYPE[$i] eq "Array<float>") | |
786 { | |
787 print " Array<float> tmp = val.float_vector_value ();\n\n"; | |
788 print " if (! error_state) | |
789 $STATIC_OBJECT_NAME.set_$OPT[$i] (tmp);\n"; | |
790 } | |
791 else | |
792 { | |
793 die ("unknown type $TYPE[$i]"); | |
794 } | |
795 | |
796 print " }\n"; | |
797 } | |
798 | |
799 print qq| else | |
800 { | |
801 warning ("$OPT_FCN_NAME: no match for `%s'", keyword.c_str ()); | |
802 } | |
803 }\n\n|; | |
804 } | |
805 | |
806 sub emit_show_function | |
807 { | |
808 print "static octave_value_list | |
809 show_$CLASS_NAME (const std::string& keyword) | |
810 { | |
811 octave_value retval; | |
812 | |
813 $STRUCT_NAME *list = $STATIC_TABLE_NAME;\n\n"; | |
814 | |
815 my $iftok = "if"; | |
816 | |
817 for (my $i = 0; $i < $OPT_NUM; $i++) | |
818 { | |
819 $iftok = "else if" if ($i > 0); | |
820 | |
821 print " $iftok (keyword_almost_match (list[$i].kw_tok, list[$i].min_len, | |
822 keyword, list[$i].min_toks_to_match, MAX_TOKENS)) | |
823 {\n"; | |
824 | |
825 if ($TYPE[$i] eq "double") | |
826 { | |
827 print " double val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n"; | |
828 print " retval = val;\n"; | |
829 } | |
830 elsif ($TYPE[$i] eq "float") | |
831 { | |
832 print " float val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n"; | |
833 print " retval = val;\n"; | |
834 } | |
835 elsif ($TYPE[$i] eq "int" or $TYPE[$i] eq "octave_idx_type") | |
836 { | |
837 print " int val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n"; | |
838 print " retval = static_cast<double> (val);\n"; | |
839 } | |
840 elsif ($TYPE[$i] eq "std::string") | |
841 { | |
842 print " retval = $STATIC_OBJECT_NAME.$OPT[$i] ();\n"; | |
843 } | |
844 elsif ($TYPE[$i] eq "Array<int>" or $TYPE[$i] eq "Array<octave_idx_type>") | |
845 { | |
846 my $elt_type; | |
847 if ($TYPE[$i] eq "Array<int>") | |
848 { | |
849 $elt_type = "int"; | |
850 } | |
851 else | |
852 { | |
853 $elt_type = "octave_idx_type"; | |
854 } | |
855 print " Array<$elt_type> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n"; | |
856 print " if (val.length () == 1) | |
857 { | |
858 retval = static_cast<double> (val(0)); | |
859 } | |
860 else | |
861 { | |
862 octave_idx_type len = val.length (); | |
863 ColumnVector tmp (len); | |
864 for (octave_idx_type i = 0; i < len; i++) | |
865 tmp(i) = val(i); | |
866 retval = tmp; | |
867 }\n"; | |
868 } | |
869 elsif ($TYPE[$i] eq "Array<double>") | |
870 { | |
871 print " Array<double> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n"; | |
872 print " if (val.length () == 1) | |
873 { | |
874 retval = val(0); | |
875 } | |
876 else | |
877 { | |
878 retval = ColumnVector (val); | |
879 }\n"; | |
880 } | |
881 elsif ($TYPE[$i] eq "Array<float>") | |
882 { | |
883 print " Array<float> val = $STATIC_OBJECT_NAME.$OPT[$i] ();\n\n"; | |
884 print " if (val.length () == 1) | |
885 { | |
886 retval = val(0); | |
887 } | |
888 else | |
889 { | |
890 retval = FloatColumnVector (val); | |
891 }\n"; | |
892 } | |
893 else | |
894 { | |
895 die ("unknown type $TYPE[$i]"); | |
896 } | |
897 | |
898 print " }\n"; | |
899 } | |
900 | |
901 print qq| else | |
902 { | |
903 warning ("$OPT_FCN_NAME: no match for `%s'", keyword.c_str ()); | |
904 } | |
905 | |
906 return retval;\n}\n\n|; | |
907 } | |
908 | |
909 sub emit_options_function | |
910 { | |
911 print <<"_END_EMIT_OPTIONS_FUNCTION_HDR_"; | |
912 DEFUN_DLD ($OPT_FCN_NAME, args, , | |
913 "-*- texinfo -*-\\n\\ | |
914 \@deftypefn {Loadable Function} {} $OPT_FCN_NAME ()\\n\\ | |
915 \@deftypefnx {Loadable Function} {val =} $OPT_FCN_NAME (\@var{opt})\\n\\ | |
916 \@deftypefnx {Loadable Function} {} $OPT_FCN_NAME (\@var{opt}, \@var{val})\\n\\ | |
917 $DOC_STRING\\n\\ | |
918 \\n\\ | |
919 Options include\\n\\ | |
920 \\n\\ | |
921 \@table \@code\\n\\ | |
922 _END_EMIT_OPTIONS_FUNCTION_HDR_ | |
923 # FIXME: Add extra newline above | |
924 | |
925 for (my $i = 0; $i < $OPT_NUM; $i++) | |
926 { | |
927 print '@item \"', $NAME[$i], '\"\n\\', "\n"; | |
928 print $DOC_ITEM[$i] if $DOC_ITEM[$i]; | |
929 } | |
930 | |
931 print <<"_END_EMIT_OPTIONS_FUNCTION_BODY_"; | |
932 \@end table\\n\\ | |
933 \@end deftypefn") | |
934 { | |
935 octave_value_list retval; | |
936 | |
937 int nargin = args.length (); | |
938 | |
939 if (nargin == 0) | |
940 { | |
941 print_$CLASS_NAME (octave_stdout); | |
942 } | |
943 else if (nargin == 1 || nargin == 2) | |
944 { | |
945 std::string keyword = args(0).string_value (); | |
946 | |
947 if (! error_state) | |
948 { | |
949 if (nargin == 1) | |
950 retval = show_$CLASS_NAME (keyword); | |
951 else | |
952 set_$CLASS_NAME (keyword, args(1)); | |
953 } | |
954 else | |
955 error ("$OPT_FCN_NAME: expecting keyword as first argument"); | |
956 } | |
957 else | |
958 print_usage (); | |
959 | |
960 return retval; | |
961 } | |
962 _END_EMIT_OPTIONS_FUNCTION_BODY_ | |
963 | |
964 } | |
965 | |
966 sub emit_options_debug | |
967 { | |
968 print qq|CLASS = "$CLASS"\n|; | |
969 | |
970 for (my $i = 0; $i < $OPT_NUM; $i++) | |
971 { | |
972 print "\nOPTION\n"; | |
973 print qq| NAME = "$NAME[$i]"\n|; | |
974 print qq| TYPE = "$TYPE[$i]"\n|; | |
975 if ($SET_ARG_TYPE[$i]) | |
976 { | |
977 print eval ("\" SET_ARG_TYPE = \\\"$SET_ARG_TYPE[$i]\\\"\"") . "\n"; | |
978 } | |
979 if ($INIT_VALUE[$i]) | |
980 { | |
981 print qq| INIT_VALUE = "$INIT_VALUE[$i]"\n|; | |
982 } | |
983 if ($INIT_BODY[$i]) | |
984 { | |
985 print " INIT_BODY\n"; | |
986 print &substopt ($INIT_BODY[$i]); | |
987 print " END_INIT_BODY\n"; | |
988 } | |
989 if ($SET_EXPR[$i]) | |
990 { | |
991 print qq| SET_EXPR = "$SET_EXPR[$i]"\n|; | |
992 } | |
993 if ($SET_BODY[$i]) | |
994 { | |
995 print " SET_BODY\n"; | |
996 print &substopt ($SET_BODY[$i]); | |
997 print " END_SET_BODY\n"; | |
998 } | |
999 if ($SET_CODE[$i]) | |
1000 { | |
1001 print " SET_CODE\n"; | |
1002 print &substopt ($SET_CODE[$i]); | |
1003 print " END_SET_CODE\n"; | |
1004 } | |
1005 print "END_OPTION\n"; | |
1006 } | |
1007 } | |
1008 | |
1009 sub substopt | |
1010 { | |
1011 my ($string, $optvar, $opt, $type) = @_; | |
1012 | |
1013 $string =~ s/\$OPTVAR/$optvar/g; | |
1014 $string =~ s/\$OPT/$opt/g; | |
1015 $string =~ s/\$TYPE/$type/g; | |
1016 | |
1017 return $string; | |
1018 } | |
1019 | |
1020 sub max | |
1021 { | |
1022 my $max = shift; | |
1023 | |
1024 foreach (@_) | |
1025 { | |
1026 $max = $_ if $max < $_; | |
1027 } | |
1028 | |
1029 return $max; | |
1030 } | |
1031 | |
1032 ################################################################################ | |
1033 # Subroutine processes any command line arguments | |
1034 ################################################################################ | |
1035 sub parse_options | |
1036 { | |
1037 my $result; | |
1038 | |
1039 $opt_help = 0; | |
1040 $opt_class_header = 0; | |
1041 $opt_handler_fcns = 0; | |
1042 $opt_debug = 0; | |
1043 | |
1044 $result = GetOptions ("opt-class-header" => \$opt_class_header, | |
1045 "opt-handler-fcns" => \$opt_handler_fcns, | |
1046 "debug" => \$opt_debug, | |
1047 "help" => \$opt_help); | |
1048 | |
1049 # give user info if options incorrect or -h(elp) given | |
1050 &usage_info if (!$result or (@ARGV != 1) or $opt_help); | |
1051 if ($opt_class_header and $opt_handler_fcns) | |
1052 { | |
1053 die "Only one of [-opt-class-header | -opt-handler-fcns ] may be specified"; | |
1054 } | |
1055 | |
1056 } | |
1057 | |
1058 ################################################################################ | |
1059 # Subroutine displays usage information | |
1060 ################################################################################ | |
1061 sub usage_info | |
1062 { | |
1063 warn <<_END_OF_USAGE_; | |
1064 ////////////////////////////////////////////////////////////////////////////// | |
1065 USAGE : mk-opts.pl -opt-class-header|-opt-handler-fcns [-debug] [-help] DEFN_FILE | |
1066 ////////////////////////////////////////////////////////////////////////////// | |
1067 | |
1068 Automatically generate C++ code for option handling code (DASSL, DASRT, etc.) | |
1069 from definition file. | |
1070 | |
1071 See the head of mk-opts.pl for a description of the format that is parsed. | |
1072 _END_OF_USAGE_ | |
1073 | |
1074 exit(1); # exit with error code | |
1075 } | |
1076 |