nexmon – Blame information for rev 1
?pathlinks?
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" |