Imported Upstream version 0.19.7
[platform/upstream/gettext.git] / build-aux / moopp
1 #!/bin/sh
2 # Minimal Object-Oriented style PreProcessor.
3
4 # Copyright (C) 2006-2008, 2015 Free Software Foundation, Inc.
5 # Written by Bruno Haible <bruno@clisp.org>, 2006.
6 #
7 # This program is free software: you can redistribute it and/or modify
8 # it under the terms of the GNU General Public License as published by
9 # the Free Software Foundation; either version 3 of the License, or
10 # (at your option) any later version.
11 #
12 # This program is distributed in the hope that it will be useful,
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 # GNU General Public License for more details.
16 #
17 # You should have received a copy of the GNU General Public License
18 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
19
20 # As a special exception to the GNU General Public License, if you
21 # distribute this file as part of a program that contains a
22 # configuration script generated by Autoconf, you may include it under
23 # the same distribution terms that you use for the rest of that program.
24
25 # Usage: moopp source.oo.c source.oo.h superclass.oo.h ...
26 # Arguments:
27 #   - the source file of the class,
28 #   - the header file declaring the class,
29 #   - the header file declaring its superclass,
30 #   - etc. up to the root class.
31 # Creates four files in the current directory:
32 #   - source.c, the preprocessing result of source.oo.c,
33 #   - source.h, the preprocessing result of source.oo.h,
34 #   - class.priv.h, a file declaring the private fields of the class,
35 #   - class.vt.h, a file declaring the virtual function table of the class.
36
37 # This implementation of the preprocessor is a quick hack. It makes assumptions
38 # about the source code:
39 #   - GNU indentation style,
40 #   - the struct declaration must be in a single line,
41 #   - no comments on the struct declaration line,
42 #   - no #ifs in relevant position,
43 #   - ...
44 # Someday this should be rewritten to use a proper tokenizer and parser.
45
46 # func_usage
47 # outputs to stdout the --help usage message.
48 func_usage ()
49 {
50   echo "\
51 Usage: moopp [OPTION]... SOURCE.oo.c SOURCE.oo.h SUPERCLASS.oo.h ...
52
53 Preprocesses SOURCE.oo.c into CLASS.c and SOURCE.oo.h into CLASS.h,
54 where CLASS is the name of the class defined in these files.
55
56 See moo.h for the object-oriented features and the syntax of the input files.
57
58 Options:
59       --help           print this help and exit
60       --version        print version information and exit
61       --dllexport=NAME Arrange so that the specified class name can be accessed
62                        from outside the shared library it is compiled into.
63                        This option can be repeated.
64
65 Report bugs to <bruno@clisp.org>."
66 }
67
68 # func_version
69 # outputs to stdout the --version message.
70 func_version ()
71 {
72   echo "$progname (GNU $package) $version"
73   echo "Copyright (C) 2006-2007 Free Software Foundation, Inc.
74 License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
75 This is free software: you are free to change and redistribute it.
76 There is NO WARRANTY, to the extent permitted by law."
77   echo "Written by" "Bruno Haible"
78 }
79
80 # func_fatal_error message
81 # outputs to stderr a fatal error message, and terminates the program.
82 func_fatal_error ()
83 {
84   echo "moopp: *** $1" 1>&2
85   echo "moopp: *** Stop." 1>&2
86   exit 1
87 }
88
89 # Command-line option processing.
90 # Removes the OPTIONS from the arguments. Sets the variables:
91 # - dllexports      list of class names to export from Woe32 DLLs
92 dllexports=
93 while test $# -gt 0; do
94   case "$1" in
95     --dllexport | --dllexpor | --dllexpo | --dllexp | --dllex | --dlle )
96       shift
97       if test $# = 0; then
98         func_fatal_error "missing argument for --dllexport"
99       fi
100       case "$1" in
101         -*) func_fatal_error "missing argument for --dllexport" ;;
102       esac
103       dllexports="$dllexports $1"
104       shift ;;
105     --dllexport=* )
106       arg=`echo "X$1" | sed -e 's/^X--dllexport=//'`
107       dllexports="$dllexports $arg"
108       shift ;;
109     --help | --hel | --he | --h )
110       func_usage
111       exit 0 ;;
112    --version | --versio | --versi | --vers | --ver | --ve | --v )
113       func_version
114       exit 0 ;;
115     -- )      # Stop option prcessing
116       shift; break ;;
117     -* )
118       func_fatal_error "unrecognized option: $option"
119       ;;
120     * )
121       break ;;
122   esac
123 done
124
125 if test $# -lt 2; then
126   func_fatal_error "Usage: $0 [OPTION]... source.oo.c source.oo.h superclass.oo.h ..."
127 fi
128
129 # Check that all files exist.
130 for file
131 do
132   test -r "$file" || {
133     func_fatal_error "file $file does not exist"
134   }
135 done
136
137 source_impl_file="$1"
138 source_header_file="$2"
139 shift
140 shift
141
142 case "$source_impl_file" in
143   *.oo.c) ;;
144   *) func_fatal_error "invalid class source file name: $source_impl_file" ;;
145 esac
146 case "$source_header_file" in
147   *.oo.h) ;;
148   *) func_fatal_error "invalid class header file name: $source_header_file" ;;
149 esac
150
151 # A sed expression that removes empty lines.
152 sed_remove_empty_lines='/^$/d'
153
154 # A sed expression that removes ANSI C and ISO C99 comments.
155 sed_remove_comments="
156 /[/][/*]/{
157   ta
158   :a
159   s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)//.*,\\1,
160   te
161   s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)/[*]\\([^*]\\|[*][^/*]\\)*[*][*]*/,\\1 ,
162   ta
163   /^\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*[/][*]/{
164     s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)/[*].*,\\1 ,
165     tu
166     :u
167     n
168     s,^\\([^*]\\|[*][^/*]\\)*[*][*]*/,,
169     tv
170     s,^.*\$,,
171     bu
172     :v
173   }
174   :e
175 }"
176 # The same thing as an extended regular expression, for use with
177 # sed --regexp-extended.
178 sed_remove_comments_ERE="
179 /[/][/*]/{
180   ta
181   :a
182   s,^(([^\"'/]|\"([^\\\"]|[\\].)*\"|'([^\\']|[\\].)*'|[/][^\"'/*]|[/]\"([^\\\"]|[\\].)*\"|[/]'([^\\']|[\\].)*')*)//.*,\\1,
183   te
184   s,^(([^\"'/]|\"([^\\\"]|[\\].)*\"|'([^\\']|[\\].)*'|[/][^\"'/*]|[/]\"([^\\\"]|[\\].)*\"|[/]'([^\\']|[\\].)*')*)/[*]([^*]|[*][^/*])*[*][*]*/,\\1 ,
185   ta
186   /^([^\"'/]|\"([^\\\"]|[\\].)*\"|'([^\\']|[\\].)*'|[/][^\"'/*]|[/]\"([^\\\"]|[\\].)*\"|[/]'([^\\']|[\\].)*')*[/][*]/{
187     s,^(([^\"'/]|\"([^\\\"]|[\\].)*\"|'([^\\']|[\\].)*'|[/][^\"'/*]|[/]\"([^\\\"]|[\\].)*\"|[/]'([^\\']|[\\].)*')*)/[*].*,\\1 ,
188     tu
189     :u
190     n
191     s,^([^*]|[*][^/*])*[*][*]*/,,
192     tv
193     s,^.*\$,,
194     bu
195     :v
196   }
197   :e
198 }"
199
200 # Check that 'sed' supports the kind of regular expressions used in
201 # sed_remove_comments. The use of \| meaning alternation of basic regular
202 # expressions is a GNU extension.
203 sed_test='s,^\(\(a\|X\)*\)//.*,\1,'
204 sed_result=`echo 'aaa//bcd' | sed -e "$sed_test"`
205 test "$sed_result" = 'aaa' \
206   || func_fatal_error "The 'sed' program is not GNU sed. Try installing GNU sed."
207
208 # func_check_impl_syntax file
209 # Check the syntax of the source implementation file.
210 # Output:
211 #   - classname         name of the class being defined (without 'struct')
212 #   - superclassname    name of the superclass, or empty for a root class
213 #   - impl_decl_lineno  line number of the class name declaration ('struct')
214 #   - impl_beg_lineno   line number of the start of the class declaration ('{')
215 #   - impl_end_lineno   line number of the end of the class declaration ('}')
216 #   - fields            field declarations, including preprocessor directives
217 func_check_impl_syntax ()
218 {
219   file="$1"
220   sed -e "$sed_remove_comments" < "$file" | grep '^fields:' > /dev/null || {
221     func_fatal_error "$file does not contain 'fields:'"
222   }
223   test `sed -e "$sed_remove_comments" < "$file" | grep -c '^fields:'` = 1 || {
224     func_fatal_error "$file contains more than one 'fields:'"
225   }
226   fields_lineno=`sed -e "$sed_remove_comments" < "$file" | grep -n '^fields:' | sed -e 's,:.*,,'`
227   sed_before_fields="$fields_lineno"',$d'
228   impl_decl_lineno=`sed -e "$sed_remove_comments" < "$file" | sed -e "$sed_before_fields" | grep -n '^struct[   ]' | tail -n 1 | sed -e 's,:.*,,'`
229   test -n "$impl_decl_lineno" || {
230     func_fatal_error "$file: class declaration not found"
231   }
232   class_line=`sed -e "$sed_remove_comments" < "$file" | sed -n -e "$impl_decl_lineno"'p'`
233   sed_extract_classname='s,^struct[     ][      ]*\([A-Za-z_0-9]*\).*,\1,p'
234   classname=`echo "$class_line" | sed -n -e "$sed_extract_classname"`
235   test -n "$classname" || {
236     func_fatal_error "$0: $file: class name not recognized at line $impl_decl_lineno"
237   }
238   superclassname=
239   if echo "$class_line" | grep ':' > /dev/null; then
240     sed_extract_superclassname='s,^.*:[         ]*struct[       ][      ]*\([A-Za-z_0-9]*\).*,\1,p'
241     superclassname=`echo "$class_line" | sed -n -e "$sed_extract_superclassname"`
242     test -n "$superclassname" || {
243       func_fatal_error "$file: superclass name not recognized at line $impl_decl_lineno"
244     }
245   fi
246   impl_beg_lineno=`sed -e "$sed_remove_comments" < "$file" | sed -e "$sed_before_fields" | grep -n '^{' | tail -n 1 | sed -e 's,:.*,,'`
247   { test -n "$impl_beg_lineno" && test "$impl_decl_lineno" -lt "$impl_beg_lineno"; } || {
248     func_fatal_error "$file: opening brace of class declaration not found after line $impl_decl_lineno"
249   }
250   sed_after_fields='1,'"$fields_lineno"'d'
251   impl_end_lineno=`sed -e "$sed_remove_comments" < "$file" | sed -e "$sed_after_fields" | grep -n '^}' | sed -e '1q' | sed -e 's,:.*,,'`
252   test -n "$impl_end_lineno" || {
253     func_fatal_error "$file: closing brace of class declaration not found after line $fields_lineno"
254   }
255   impl_end_lineno=`expr $fields_lineno + $impl_end_lineno`
256   sed_extract_fields="$impl_end_lineno"',$d;1,'"$fields_lineno"'d'
257   fields=`sed -e "$sed_remove_comments" < "$file" | sed -e "$sed_extract_fields"`
258 }
259
260 # func_check_header_syntax file
261 # Check the syntax of a header file.
262 # Output:
263 #   - classname         name of the class being defined (without 'struct')
264 #   - superclassname    name of the superclass, or empty for a root class
265 #   - class_decl_lineno line number of the class name declaration ('struct')
266 #   - class_beg_lineno  line number of the start of the class declaration ('{')
267 #   - class_end_lineno  line number of the end of the class declaration ('}')
268 #   - methods           newline-separated list of method declarations
269 func_check_header_syntax ()
270 {
271   file="$1"
272   sed -e "$sed_remove_comments" < "$file" | grep '^methods:' > /dev/null || {
273     func_fatal_error "$file does not contain 'methods:'"
274   }
275   test `sed -e "$sed_remove_comments" < "$file" | grep -c '^methods:'` = 1 || {
276     func_fatal_error "$file contains more than one 'methods:'"
277   }
278   methods_lineno=`sed -e "$sed_remove_comments" < "$file" | grep -n '^methods:' | sed -e 's,:.*,,'`
279   sed_before_methods="$methods_lineno"',$d'
280   class_decl_lineno=`sed -e "$sed_remove_comments" < "$file" | sed -e "$sed_before_methods" | grep -n '^struct[         ]' | tail -n 1 | sed -e 's,:.*,,'`
281   test -n "$class_decl_lineno" || {
282     func_fatal_error "$file: class declaration not found"
283   }
284   class_line=`sed -e "$sed_remove_comments" < "$file" | sed -n -e "$class_decl_lineno"'p'`
285   sed_extract_classname='s,^struct[     ][      ]*\([A-Za-z_0-9]*\).*,\1,p'
286   classname=`echo "$class_line" | sed -n -e "$sed_extract_classname"`
287   test -n "$classname" || {
288     func_fatal_error "$0: $file: class name not recognized at line $class_decl_lineno"
289   }
290   superclassname=
291   if echo "$class_line" | grep ':' > /dev/null; then
292     sed_extract_superclassname='s,^.*:[         ]*struct[       ][      ]*\([A-Za-z_0-9]*\).*,\1,p'
293     superclassname=`echo "$class_line" | sed -n -e "$sed_extract_superclassname"`
294     test -n "$superclassname" || {
295       func_fatal_error "$file: superclass name not recognized at line $class_decl_lineno"
296     }
297   fi
298   class_beg_lineno=`sed -e "$sed_remove_comments" < "$file" | sed -e "$sed_before_methods" | grep -n '^{' | tail -n 1 | sed -e 's,:.*,,'`
299   { test -n "$class_beg_lineno" && test "$class_decl_lineno" -lt "$class_beg_lineno"; } || {
300     func_fatal_error "$file: opening brace of class declaration not found after line $class_decl_lineno"
301   }
302   sed_after_methods='1,'"$methods_lineno"'d'
303   class_end_lineno=`sed -e "$sed_remove_comments" < "$file" | sed -e "$sed_after_methods" | grep -n '^}' | sed -e '1q' | sed -e 's,:.*,,'`
304   test -n "$class_end_lineno" || {
305     func_fatal_error "$file: closing brace of class declaration not found after line $methods_lineno"
306   }
307   class_end_lineno=`expr $methods_lineno + $class_end_lineno`
308   sed_extract_methods="$class_end_lineno"',$d;1,'"$methods_lineno"'d'
309   methods=`sed -e "$sed_remove_comments" < "$file" | sed -e "$sed_extract_methods" | tr '\n' ' ' | tr ';' '\n' | sed -e 's,[    ]*$,,'`
310   sed_remove_valid_arg1_lines='/([      ]*'"$classname"'_t[     ]*[A-Za-z_0-9]*[        ]*[,)]/d'
311   sed_extract_method_name='s,^.*[^A-Za-z_0-9]\([A-Za-z_0-9][A-Za-z_0-9]*\)[     ]*(.*$,\1,'
312   methods_with_bad_arg1=`echo "$methods" | sed -e "$sed_remove_empty_lines" -e "$sed_remove_valid_arg1_lines" -e "$sed_extract_method_name"`
313   if test -n "$methods_with_bad_arg1"; then
314     methods_with_bad_arg1=`{ echo "$methods_with_bad_arg1" | sed -e 's/$/, /' | tr -d '\n'; echo; } | sed -e 's/\(, \)*$//'`
315     func_fatal_error "$file: some methods don't have a first argument of type ${classname}_t: $methods_with_bad_arg1"
316   fi
317 }
318
319 func_check_impl_syntax "$source_impl_file"
320 impl_classname="$classname"
321 impl_superclassname="$superclassname"
322
323 func_check_header_syntax "$source_header_file"
324 main_classname="$classname"
325 main_superclassname="$superclassname"
326 main_class_decl_lineno="$class_decl_lineno"
327 main_class_beg_lineno="$class_beg_lineno"
328 main_class_end_lineno="$class_end_lineno"
329 main_methods="$methods"
330 all_superclasses=
331 all_methods="$methods"
332 inherited_methods=
333 last_header_file="$source_header_file"
334 expected_superclassname="$superclassname"
335
336 for file
337 do
338   if test -z "$expected_superclassname"; then
339     func_fatal_error "file $last_header_file does not specify a superclass; superfluous command line argument $file"
340   fi
341   func_check_header_syntax "$file"
342   all_superclasses="$classname $all_superclasses"
343   all_methods="$methods
344 $all_methods"
345   inherited_methods="$methods
346 $inherited_methods"
347   if test "$classname" != "$expected_superclassname"; then
348     func_fatal_error "file $last_header_file specifies superclass '$expected_superclassname', but file $file defines class '$classname'"
349   fi
350   last_header_file="$file"
351   expected_superclassname="$superclassname"
352 done
353
354 if test -n "$expected_superclassname"; then
355   func_fatal_error "$0: file $last_header_file specifies superclass '$expected_superclassname', please specify the header file that defines it as additional command line argument"
356 fi
357
358 if test "$impl_classname" != "$main_classname"; then
359   func_fatal_error "file $source_header_file specifies class '$main_classname', but file $source_impl_file specifies class '$impl_classname'"
360 fi
361 if test "$impl_superclassname" != "$main_superclassname"; then
362   if test -z "$main_superclassname"; then
363     func_fatal_error "file $source_header_file specifies no superclass, but file $source_impl_file specifies a superclass '$impl_superclassname'"
364   fi
365   if test -z "$impl_superclassname"; then
366     func_fatal_error "file $source_header_file specifies a superclass '$main_superclassname', but file $source_impl_file specifies no superclass"
367   fi
368   func_fatal_error "file $source_header_file specifies a superclass '$main_superclassname', but file $source_impl_file specifies a superclass '$impl_superclassname'"
369 fi
370
371 # func_start_creation file
372 # starts the creation of the named file.
373 func_start_creation ()
374 {
375   file="$1"
376   if test -f "$file"; then
377     echo "Updating $file (backup in ${file}~)"
378     mv -f "$file" "${file}~" || func_fatal_error "failed"
379   else
380     echo "Creating $file"
381   fi
382 }
383
384 # func_emit_priv_h newfile
385 # outputs to $newfile the contents of class.priv.h.
386 func_emit_priv_h ()
387 {
388   newfile="$1"
389   {
390     echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'
391     echo
392     if test -n "${main_superclassname}"; then
393       echo "/* Field layout of superclass.  */"
394       echo "#include \"${main_superclassname}.priv.h\""
395       echo
396     fi
397     echo "/* Field layout of ${main_classname} class.  */"
398     echo "struct ${main_classname}_representation"
399     echo "{"
400     if test -n "${main_superclassname}"; then
401       echo "  struct ${main_superclassname}_representation base;"
402     else
403       echo "  const void *vtable;"
404     fi
405     echo "$fields" | sed -e "$sed_remove_empty_lines"
406     echo "};"
407   } > "$newfile"
408 }
409
410 # func_emit_vt_h newfile
411 # outputs to $newfile the contents of class.vt.h.
412 func_emit_vt_h ()
413 {
414   newfile="$1"
415   {
416     echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'
417     echo
418     if test -n "${main_superclassname}"; then
419       echo "/* Virtual function table layout of superclass.  */"
420       echo "#include \"${main_superclassname}.vt.h\""
421       echo
422     fi
423     echo "/* Virtual function table layout of ${main_classname} class.  */"
424     echo "$main_methods" | sed -e "$sed_remove_empty_lines" -e 's/\([^A-Za-z_0-9]\)\([A-Za-z_0-9][A-Za-z_0-9]*\)[       ]*([^,)]*/\1(*\2) (THIS_ARG/' -e 's,$,;,'
425   } > "$newfile"
426 }
427
428 # In C++ mode, we have a precise type checking. But in C mode, we have only
429 # loose type checking: So that rootclass_t and subclass_t are assignment
430 # compatible, we have to define subclass_t as identical to rootclass_t.
431 # Therefore we need an alias name for the representation of any type in the
432 # hierarchy.
433 if test -z "$main_superclassname"; then
434   main_repclassalias="any_${main_classname}_representation"
435 else
436   main_repclassalias="${main_classname}_representation"
437 fi
438
439 sed_extract_method_rettype='s,^\(.*[^A-Za-z_0-9]\)[A-Za-z_0-9][A-Za-z_0-9]*[    ]*(.*$,\1,
440 s,^[    ]*,,
441 s,[     ]*$,,'
442 sed_extract_method_name='s,^.*[^A-Za-z_0-9]\([A-Za-z_0-9][A-Za-z_0-9]*\)[       ]*(.*$,\1,'
443 sed_extract_method_arglist='s,^.*[^A-Za-z_0-9][A-Za-z_0-9][A-Za-z_0-9]*[        ]*([^,)]*\(.*\)).*$,'"${main_classname}_t"' first_arg\1,'
444 sed_extract_method_args='s,^.*[^A-Za-z_0-9]\([A-Za-z_0-9][A-Za-z_0-9]*\)$,\1,'
445
446 # func_emit_source_h newfile newfile_base
447 # outputs to $newfile the contents of source.h.
448 source_header_file_base=`echo "$source_header_file" | sed -e 's,^.*/,,'`
449 func_emit_source_h ()
450 {
451   newfile="$1"
452   newfile_base="$2"
453   # Use DLL_VARIABLE if and only if the main classname is among the names
454   # specified with --dllexport options.
455   dllexport_for_variables=
456   for name in $dllexports; do
457     if test "${main_classname}" = "${name}"; then
458       dllexport_for_variables=" DLL_VARIABLE"
459       break
460     fi
461   done
462   {
463     echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'
464     echo
465     echo "#line 1 \"${source_header_file_base}\""
466     cat "$source_header_file" | sed -e "${main_class_decl_lineno}"',$d'
467     echo "#line "`expr 3 + ${main_class_decl_lineno} + 1`" \"$newfile_base\""
468     echo "struct ${main_repclassalias};"
469     echo "/* ${main_classname}_t is defined as a pointer to struct ${main_repclassalias}."
470     echo "   In C++ mode, we use a smart pointer class."
471     echo "   In C mode, we have no other choice than a typedef to the root class type.  */"
472     echo "#if IS_CPLUSPLUS"
473     echo "struct ${main_classname}_t"
474     echo "{"
475     echo "private:"
476     echo "  struct ${main_repclassalias} *_pointer;"
477     echo "public:"
478     echo "  ${main_classname}_t () : _pointer (NULL) {}"
479     echo "  ${main_classname}_t (struct ${main_repclassalias} *pointer) : _pointer (pointer) {}"
480     echo "  struct ${main_repclassalias} * operator -> () { return _pointer; }"
481     echo "  operator struct ${main_repclassalias} * () { return _pointer; }"
482     atroot=yes
483     for classname in $all_superclasses; do
484       if test -n "$atroot"; then
485         repclassalias="any_${classname}_representation"
486       else
487         repclassalias="${classname}_representation"
488       fi
489       echo "  operator struct ${repclassalias} * () { return (struct ${repclassalias} *) _pointer; }"
490       atroot=
491     done
492     # The 'operator void *' is needed to avoid ambiguous conversion chains.
493     echo "  operator void * () { return _pointer; }"
494     # The 'operator ==' and 'operator !=' are needed to avoid ambiguous comparisons with NULL.
495     echo "  bool operator == (const void *p) { return _pointer == p; }"
496     echo "  bool operator != (const void *p) { return _pointer != p; }"
497     atroot=yes
498     for classname in $all_superclasses; do
499       if test -n "$atroot"; then
500         repclassalias="any_${classname}_representation"
501       else
502         repclassalias="${classname}_representation"
503       fi
504       echo "  operator ${classname}_t () { return (${classname}_t) (struct ${repclassalias} *) _pointer; }"
505       # The 'explicit' constructors allow to downcast.
506       echo "  explicit ${main_classname}_t (${classname}_t x) : _pointer ((struct ${main_repclassalias} *) (void *) x) {}"
507       atroot=
508     done
509     echo "};"
510     echo "#else"
511     if test -n "${main_superclassname}"; then
512       echo "typedef ${main_superclassname}_t ${main_classname}_t;"
513     else
514       echo "typedef struct ${main_repclassalias} * ${main_classname}_t;"
515     fi
516     echo "#endif"
517     echo
518     echo "/* Functions that invoke the methods.  */"
519     echo "$all_methods" | sed -e "$sed_remove_empty_lines" -e 's/\([^A-Za-z_0-9]\)\([A-Za-z_0-9][A-Za-z_0-9]*\)[        ]*([^,)]*/\1'"${main_classname}_"'\2 ('"${main_classname}_t first_arg"'/' -e 's,^,extern ,' -e 's,$,;,'
520     echo
521     # Now come the implementation details.
522     echo "/* Type representing an implementation of ${main_classname}_t.  */"
523     echo "struct ${main_classname}_implementation"
524     echo "{"
525     echo "  const typeinfo_t * const *superclasses;"
526     echo "  size_t superclasses_length;"
527     echo "  size_t instance_size;"
528     echo "#define THIS_ARG ${main_classname}_t first_arg"
529     echo "#include \"${main_classname}.vt.h\""
530     echo "#undef THIS_ARG"
531     echo "};"
532     echo
533     echo "/* Public portion of the object pointed to by a ${main_classname}_t.  */"
534     echo "struct ${main_classname}_representation_header"
535     echo "{"
536     echo "  const struct ${main_classname}_implementation *vtable;"
537     echo "};"
538     echo
539     echo "#if HAVE_INLINE"
540     echo
541     echo "/* Define the functions that invoke the methods as inline accesses to"
542     echo "   the ${main_classname}_implementation."
543     echo "   Use #define to avoid a warning because of extern vs. static.  */"
544     echo
545     echo "$all_methods" | sed -e "$sed_remove_empty_lines" |
546       while read method; do
547         rettype=`echo "$method" | sed -e "$sed_extract_method_rettype"`
548         name=`echo "$method" | sed -e "$sed_extract_method_name"`
549         arglist=`echo "$method" | sed -e "$sed_extract_method_arglist"`
550         if test "$arglist" = "void"; then
551           args=
552         else
553           args=`{ echo "$arglist" | tr ',' '\n' | sed -e "$sed_extract_method_args" | tr '\n' ','; echo; } | sed -e 's/,$//'`
554         fi
555         if test "$rettype" = "void"; then
556           return=
557         else
558           return="return "
559         fi
560         echo "# define ${main_classname}_${name} ${main_classname}_${name}_inline"
561         echo "static inline $rettype"
562         echo "${main_classname}_${name} ($arglist)"
563         echo "{"
564         echo "  const struct ${main_classname}_implementation *vtable ="
565         echo "    ((struct ${main_classname}_representation_header *) (struct ${main_repclassalias} *) first_arg)->vtable;"
566         echo "  ${return}vtable->${name} ($args);"
567         echo "}"
568         echo
569       done
570     echo "#endif"
571     echo
572     echo "extern${dllexport_for_variables} const typeinfo_t ${main_classname}_typeinfo;"
573     if test -n "${main_superclassname}"; then
574       superclasses_array_initializer="${main_superclassname}_SUPERCLASSES"
575     else
576       superclasses_array_initializer="NULL"
577     fi
578     echo "#define ${main_classname}_SUPERCLASSES &${main_classname}_typeinfo, ${superclasses_array_initializer}"
579     if test -n "${main_superclassname}"; then
580       echo "#define ${main_classname}_SUPERCLASSES_LENGTH (1 + ${main_superclassname}_SUPERCLASSES_LENGTH)"
581     else
582       echo "#define ${main_classname}_SUPERCLASSES_LENGTH (1 + 1)"
583     fi
584     echo
585     echo "extern${dllexport_for_variables} const struct ${main_classname}_implementation ${main_classname}_vtable;"
586     echo
587     echo "#line "`expr $main_class_end_lineno + 1`" \"${source_header_file_base}\""
588     cat "$source_header_file" | sed -e "1,${main_class_end_lineno}d"
589   } > "$newfile"
590 }
591
592 # func_emit_source_c newfile newfile_base
593 # outputs to $newfile the contents of source.c.
594 source_impl_file_base=`echo "$source_impl_file" | sed -e 's,^.*/,,'`
595 func_emit_source_c ()
596 {
597   newfile="$1"
598   newfile_base="$2"
599   {
600     echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'
601     echo
602     echo "#line 1 \"${source_impl_file_base}\""
603     cat "$source_impl_file" | sed -e "${impl_decl_lineno}"',$d'
604     echo "#line "`expr 3 + ${impl_decl_lineno} + 1`" \"$newfile_base\""
605     # In C mode, where subclass_t is identical to rootclass_t, we define the
606     # any_rootclass_representation type to the right one for subclass.
607     if test -n "$all_superclasses"; then
608       for classname in $all_superclasses; do
609         rootclassname="$classname"
610         break
611       done
612     else
613       rootclassname="$main_classname"
614     fi
615     echo "#if !IS_CPLUSPLUS"
616     echo "#define ${main_classname}_representation any_${rootclassname}_representation"
617     echo "#endif"
618     echo "#include \"${main_classname}.priv.h\""
619     echo
620     echo "const typeinfo_t ${main_classname}_typeinfo = { \"${main_classname}\" };"
621     echo
622     echo "static const typeinfo_t * const ${main_classname}_superclasses[] ="
623     echo "  { ${main_classname}_SUPERCLASSES };"
624     echo
625     if test -n "${main_superclassname}"; then
626       echo "#define super ${main_superclassname}_vtable"
627       echo
628     fi
629     echo "#line "`expr $impl_end_lineno + 1`" \"${source_impl_file_base}\""
630     cat "$source_impl_file" | sed -e "1,${impl_end_lineno}d" | sed -e "s,${main_classname}::,${main_classname}__,g"
631     echo
632     lineno=`wc -l < "$newfile"`
633     echo "#line "`expr $lineno + 2`" \"$newfile_base\""
634     # Define trivial stubs for methods that are not defined or overridden.
635     inherited_method_names=`echo "$inherited_methods" | sed -e "$sed_remove_empty_lines" | sed -e "$sed_extract_method_name"`
636     echo "$all_methods" | sed -e "$sed_remove_empty_lines" |
637       while read method; do
638         rettype=`echo "$method" | sed -e "$sed_extract_method_rettype"`
639         name=`echo "$method" | sed -e "$sed_extract_method_name"`
640         arglist=`echo "$method" | sed -e "$sed_extract_method_arglist"`
641         if test "$arglist" = "void"; then
642           args=
643         else
644           args=`{ echo "$arglist" | tr ',' '\n' | sed -e "$sed_extract_method_args" | tr '\n' ','; echo; } | sed -e 's/,$//'`
645         fi
646         if test "$rettype" = "void"; then
647           return=
648         else
649           return="return "
650         fi
651         if cat "$source_impl_file" | sed -e "1,${impl_end_lineno}d" | sed -e "$sed_remove_comments" | grep "${main_classname}::${name} *(" > /dev/null; then
652           # The class defines or overrides the method.
653           :
654         else
655           # Add a stub for the method.
656           inherited=
657           for i in $inherited_method_names; do
658             if test "$i" = "$name"; then
659               inherited=yes
660             fi
661           done
662           # First a prototype, to avoid gcc -Wmissing-prototypes warnings.
663           echo "$rettype ${main_classname}__${name} ($arglist);"
664           echo "$rettype"
665           echo "${main_classname}__${name} ($arglist)"
666           echo "{"
667           if test -n "$inherited"; then
668             echo "  ${return}super.${name} ($args);"
669           else
670             echo "  /* Abstract (unimplemented) method called.  */"
671             echo "  abort ();"
672             # Avoid C++ compiler warning about missing return value.
673             echo "  #ifndef __GNUC__"
674             echo "  ${return}${main_classname}__${name} ($args);"
675             echo "  #endif"
676           fi
677           echo "}"
678           echo
679         fi
680       done
681     echo
682     echo "const struct ${main_classname}_implementation ${main_classname}_vtable ="
683     echo "{"
684     echo "  ${main_classname}_superclasses,"
685     echo "  sizeof (${main_classname}_superclasses) / sizeof (${main_classname}_superclasses[0]),"
686     echo "  sizeof (struct ${main_classname}_representation),"
687     echo "$all_methods" | sed -e "$sed_remove_empty_lines" |
688       while read method; do
689         name=`echo "$method" | sed -e "$sed_extract_method_name"`
690         echo "  ${main_classname}__${name},"
691       done
692     echo "};"
693     echo
694     echo "#if !HAVE_INLINE"
695     echo
696     echo "/* Define the functions that invoke the methods.  */"
697     echo
698     echo "$all_methods" | sed -e "$sed_remove_empty_lines" |
699       while read method; do
700         rettype=`echo "$method" | sed -e "$sed_extract_method_rettype"`
701         name=`echo "$method" | sed -e "$sed_extract_method_name"`
702         arglist=`echo "$method" | sed -e "$sed_extract_method_arglist"`
703         if test "$arglist" = "void"; then
704           args=
705         else
706           args=`{ echo "$arglist" | tr ',' '\n' | sed -e "$sed_extract_method_args" | tr '\n' ','; echo; } | sed -e 's/,$//'`
707         fi
708         if test "$rettype" = "void"; then
709           return=
710         else
711           return="return "
712         fi
713         echo "$rettype"
714         echo "${main_classname}_${name} ($arglist)"
715         echo "{"
716         echo "  const struct ${main_classname}_implementation *vtable ="
717         echo "    ((struct ${main_classname}_representation_header *) (struct ${main_repclassalias} *) first_arg)->vtable;"
718         echo "  ${return}vtable->${name} ($args);"
719         echo "}"
720         echo
721       done
722     echo "#endif"
723   } > "$newfile"
724 }
725
726 # Generate the files in the source directory, not in the current directory.
727 # This is needed because they need to be distributed, since not all platforms
728 # have GNU 'sed' preinstalled.
729
730 sed_butbase='s,[^/]*$,,'
731 destdir=`echo "$source_impl_file" | sed -e "$sed_butbase"`
732
733 # Generate the source.h file first. The Makefile.am snippets rely on the
734 # fact that the other generated files have the same or a newer timestamp.
735 #
736 # Also, generate the source.c file last. The Makefile.am snippets don't know
737 # about the other generated files; they assume that when the source.c file
738 # is finished, this command is complete.
739
740 new_source_header_file_base=`echo "$source_header_file_base" | sed -e 's,\.oo\.h$,.h,'`
741 new_source_header_file="${destdir}$new_source_header_file_base"
742 func_start_creation "$new_source_header_file"
743 func_emit_source_h "$new_source_header_file" "$new_source_header_file_base" \
744   || func_fatal_error "failed"
745
746 new_priv_header_file="${destdir}${main_classname}.priv.h"
747 func_start_creation "$new_priv_header_file"
748 func_emit_priv_h "$new_priv_header_file" \
749   || func_fatal_error "failed"
750
751 new_vt_header_file="${destdir}${main_classname}.vt.h"
752 func_start_creation "$new_vt_header_file"
753 func_emit_vt_h "$new_vt_header_file" \
754   || func_fatal_error "failed"
755
756 new_source_impl_file_base=`echo "$source_impl_file_base" | sed -e 's,\.oo\.c$,.c,'`
757 new_source_impl_file="${destdir}$new_source_impl_file_base"
758 func_start_creation "$new_source_impl_file"
759 func_emit_source_c "$new_source_impl_file" "$new_source_impl_file_base" \
760   || func_fatal_error "failed"