2 # Minimal Object-Oriented style PreProcessor.
4 # Copyright (C) 2006-2008, 2015 Free Software Foundation, Inc.
5 # Written by Bruno Haible <bruno@clisp.org>, 2006.
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.
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.
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/>.
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.
25 # Usage: moopp source.oo.c source.oo.h superclass.oo.h ...
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.
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,
44 # Someday this should be rewritten to use a proper tokenizer and parser.
47 # outputs to stdout the --help usage message.
51 Usage: moopp [OPTION]... SOURCE.oo.c SOURCE.oo.h SUPERCLASS.oo.h ...
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.
56 See moo.h for the object-oriented features and the syntax of the input files.
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.
65 Report bugs to <bruno@clisp.org>."
69 # outputs to stdout the --version message.
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"
80 # func_fatal_error message
81 # outputs to stderr a fatal error message, and terminates the program.
84 echo "moopp: *** $1" 1>&2
85 echo "moopp: *** Stop." 1>&2
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
93 while test $# -gt 0; do
95 --dllexport | --dllexpor | --dllexpo | --dllexp | --dllex | --dlle )
98 func_fatal_error "missing argument for --dllexport"
101 -*) func_fatal_error "missing argument for --dllexport" ;;
103 dllexports="$dllexports $1"
106 arg=`echo "X$1" | sed -e 's/^X--dllexport=//'`
107 dllexports="$dllexports $arg"
109 --help | --hel | --he | --h )
112 --version | --versio | --versi | --vers | --ver | --ve | --v )
115 -- ) # Stop option prcessing
118 func_fatal_error "unrecognized option: $option"
125 if test $# -lt 2; then
126 func_fatal_error "Usage: $0 [OPTION]... source.oo.c source.oo.h superclass.oo.h ..."
129 # Check that all files exist.
133 func_fatal_error "file $file does not exist"
137 source_impl_file="$1"
138 source_header_file="$2"
142 case "$source_impl_file" in
144 *) func_fatal_error "invalid class source file name: $source_impl_file" ;;
146 case "$source_header_file" in
148 *) func_fatal_error "invalid class header file name: $source_header_file" ;;
151 # A sed expression that removes empty lines.
152 sed_remove_empty_lines='/^$/d'
154 # A sed expression that removes ANSI C and ISO C99 comments.
155 sed_remove_comments="
159 s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)//.*,\\1,
161 s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)/[*]\\([^*]\\|[*][^/*]\\)*[*][*]*/,\\1 ,
163 /^\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*[/][*]/{
164 s,^\\(\\([^\"'/]\\|\"\\([^\\\"]\\|[\\].\\)*\"\\|'\\([^\\']\\|[\\].\\)*'\\|[/][^\"'/*]\\|[/]\"\\([^\\\"]\\|[\\].\\)*\"\\|[/]'\\([^\\']\\|[\\].\\)*'\\)*\\)/[*].*,\\1 ,
168 s,^\\([^*]\\|[*][^/*]\\)*[*][*]*/,,
176 # The same thing as an extended regular expression, for use with
177 # sed --regexp-extended.
178 sed_remove_comments_ERE="
182 s,^(([^\"'/]|\"([^\\\"]|[\\].)*\"|'([^\\']|[\\].)*'|[/][^\"'/*]|[/]\"([^\\\"]|[\\].)*\"|[/]'([^\\']|[\\].)*')*)//.*,\\1,
184 s,^(([^\"'/]|\"([^\\\"]|[\\].)*\"|'([^\\']|[\\].)*'|[/][^\"'/*]|[/]\"([^\\\"]|[\\].)*\"|[/]'([^\\']|[\\].)*')*)/[*]([^*]|[*][^/*])*[*][*]*/,\\1 ,
186 /^([^\"'/]|\"([^\\\"]|[\\].)*\"|'([^\\']|[\\].)*'|[/][^\"'/*]|[/]\"([^\\\"]|[\\].)*\"|[/]'([^\\']|[\\].)*')*[/][*]/{
187 s,^(([^\"'/]|\"([^\\\"]|[\\].)*\"|'([^\\']|[\\].)*'|[/][^\"'/*]|[/]\"([^\\\"]|[\\].)*\"|[/]'([^\\']|[\\].)*')*)/[*].*,\\1 ,
191 s,^([^*]|[*][^/*])*[*][*]*/,,
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."
208 # func_check_impl_syntax file
209 # Check the syntax of the source implementation file.
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 ()
220 sed -e "$sed_remove_comments" < "$file" | grep '^fields:' > /dev/null || {
221 func_fatal_error "$file does not contain 'fields:'"
223 test `sed -e "$sed_remove_comments" < "$file" | grep -c '^fields:'` = 1 || {
224 func_fatal_error "$file contains more than one 'fields:'"
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"
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"
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"
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"
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"
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"`
260 # func_check_header_syntax file
261 # Check the syntax of a header file.
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 ()
272 sed -e "$sed_remove_comments" < "$file" | grep '^methods:' > /dev/null || {
273 func_fatal_error "$file does not contain 'methods:'"
275 test `sed -e "$sed_remove_comments" < "$file" | grep -c '^methods:'` = 1 || {
276 func_fatal_error "$file contains more than one 'methods:'"
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"
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"
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"
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"
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"
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"
319 func_check_impl_syntax "$source_impl_file"
320 impl_classname="$classname"
321 impl_superclassname="$superclassname"
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"
331 all_methods="$methods"
333 last_header_file="$source_header_file"
334 expected_superclassname="$superclassname"
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"
341 func_check_header_syntax "$file"
342 all_superclasses="$classname $all_superclasses"
343 all_methods="$methods
345 inherited_methods="$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'"
350 last_header_file="$file"
351 expected_superclassname="$superclassname"
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"
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'"
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'"
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"
368 func_fatal_error "file $source_header_file specifies a superclass '$main_superclassname', but file $source_impl_file specifies a superclass '$impl_superclassname'"
371 # func_start_creation file
372 # starts the creation of the named file.
373 func_start_creation ()
376 if test -f "$file"; then
377 echo "Updating $file (backup in ${file}~)"
378 mv -f "$file" "${file}~" || func_fatal_error "failed"
380 echo "Creating $file"
384 # func_emit_priv_h newfile
385 # outputs to $newfile the contents of class.priv.h.
390 echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'
392 if test -n "${main_superclassname}"; then
393 echo "/* Field layout of superclass. */"
394 echo "#include \"${main_superclassname}.priv.h\""
397 echo "/* Field layout of ${main_classname} class. */"
398 echo "struct ${main_classname}_representation"
400 if test -n "${main_superclassname}"; then
401 echo " struct ${main_superclassname}_representation base;"
403 echo " const void *vtable;"
405 echo "$fields" | sed -e "$sed_remove_empty_lines"
410 # func_emit_vt_h newfile
411 # outputs to $newfile the contents of class.vt.h.
416 echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'
418 if test -n "${main_superclassname}"; then
419 echo "/* Virtual function table layout of superclass. */"
420 echo "#include \"${main_superclassname}.vt.h\""
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,$,;,'
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
433 if test -z "$main_superclassname"; then
434 main_repclassalias="any_${main_classname}_representation"
436 main_repclassalias="${main_classname}_representation"
439 sed_extract_method_rettype='s,^\(.*[^A-Za-z_0-9]\)[A-Za-z_0-9][A-Za-z_0-9]*[ ]*(.*$,\1,
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,'
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 ()
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"
463 echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'
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"
476 echo " struct ${main_repclassalias} *_pointer;"
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; }"
483 for classname in $all_superclasses; do
484 if test -n "$atroot"; then
485 repclassalias="any_${classname}_representation"
487 repclassalias="${classname}_representation"
489 echo " operator struct ${repclassalias} * () { return (struct ${repclassalias} *) _pointer; }"
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; }"
498 for classname in $all_superclasses; do
499 if test -n "$atroot"; then
500 repclassalias="any_${classname}_representation"
502 repclassalias="${classname}_representation"
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) {}"
511 if test -n "${main_superclassname}"; then
512 echo "typedef ${main_superclassname}_t ${main_classname}_t;"
514 echo "typedef struct ${main_repclassalias} * ${main_classname}_t;"
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,$,;,'
521 # Now come the implementation details.
522 echo "/* Type representing an implementation of ${main_classname}_t. */"
523 echo "struct ${main_classname}_implementation"
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"
533 echo "/* Public portion of the object pointed to by a ${main_classname}_t. */"
534 echo "struct ${main_classname}_representation_header"
536 echo " const struct ${main_classname}_implementation *vtable;"
539 echo "#if HAVE_INLINE"
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. */"
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
553 args=`{ echo "$arglist" | tr ',' '\n' | sed -e "$sed_extract_method_args" | tr '\n' ','; echo; } | sed -e 's/,$//'`
555 if test "$rettype" = "void"; then
560 echo "# define ${main_classname}_${name} ${main_classname}_${name}_inline"
561 echo "static inline $rettype"
562 echo "${main_classname}_${name} ($arglist)"
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);"
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"
576 superclasses_array_initializer="NULL"
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)"
582 echo "#define ${main_classname}_SUPERCLASSES_LENGTH (1 + 1)"
585 echo "extern${dllexport_for_variables} const struct ${main_classname}_implementation ${main_classname}_vtable;"
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"
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 ()
600 echo '/* DO NOT EDIT! GENERATED AUTOMATICALLY! */'
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"
613 rootclassname="$main_classname"
615 echo "#if !IS_CPLUSPLUS"
616 echo "#define ${main_classname}_representation any_${rootclassname}_representation"
618 echo "#include \"${main_classname}.priv.h\""
620 echo "const typeinfo_t ${main_classname}_typeinfo = { \"${main_classname}\" };"
622 echo "static const typeinfo_t * const ${main_classname}_superclasses[] ="
623 echo " { ${main_classname}_SUPERCLASSES };"
625 if test -n "${main_superclassname}"; then
626 echo "#define super ${main_superclassname}_vtable"
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"
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
644 args=`{ echo "$arglist" | tr ',' '\n' | sed -e "$sed_extract_method_args" | tr '\n' ','; echo; } | sed -e 's/,$//'`
646 if test "$rettype" = "void"; then
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.
655 # Add a stub for the method.
657 for i in $inherited_method_names; do
658 if test "$i" = "$name"; then
662 # First a prototype, to avoid gcc -Wmissing-prototypes warnings.
663 echo "$rettype ${main_classname}__${name} ($arglist);"
665 echo "${main_classname}__${name} ($arglist)"
667 if test -n "$inherited"; then
668 echo " ${return}super.${name} ($args);"
670 echo " /* Abstract (unimplemented) method called. */"
672 # Avoid C++ compiler warning about missing return value.
673 echo " #ifndef __GNUC__"
674 echo " ${return}${main_classname}__${name} ($args);"
682 echo "const struct ${main_classname}_implementation ${main_classname}_vtable ="
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},"
694 echo "#if !HAVE_INLINE"
696 echo "/* Define the functions that invoke the methods. */"
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
706 args=`{ echo "$arglist" | tr ',' '\n' | sed -e "$sed_extract_method_args" | tr '\n' ','; echo; } | sed -e 's/,$//'`
708 if test "$rettype" = "void"; then
714 echo "${main_classname}_${name} ($arglist)"
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);"
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.
730 sed_butbase='s,[^/]*$,,'
731 destdir=`echo "$source_impl_file" | sed -e "$sed_butbase"`
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.
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.
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"
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"
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"
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"