nexmon – Blame information for rev 1

Subversion Repositories:
Rev:
Rev Author Line No. Line
1 office 1 #!/bin/sh
2 # Minimal Object-Oriented style PreProcessor.
3  
4 # Copyright (C) 2006-2008, 2015-2016 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 '\015\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 '\015\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"