2018年3月29日 星期四

[懷舊] 向 cfront 致敬, 使用 cfront 來編譯 c++ 程式

華麗的 c++ 與華麗的娃衣
cfront 是幹麻的? c++ 程式員應該不陌生, 他是把 c++ 程式轉成 c, 再用 c 編譯器編譯出最後執行檔的轉譯程式。知道的 c++ 開發者應該很多, 但看過、甚至執行過 cfront 的人應該就很少了。

我一直都在找 cfront 的 source code, 希望可以編譯/執行起來看看, 這樣可以很清楚的知道, virtual function, 繼承的 class, template 到底是怎麼轉成 c code 的, cfront 不支援 exception, 因為這功能複雜到超過 cfront 的能力了。

Cfront
Cfront 4.0 was abandoned in 1993 after a failed attempt to add exception support.[1] The C++ language had grown beyond its capabilities

Comeau C/C++ 也可以做到類似的事情, 不過要錢, 沒免費版可以試用。

這個 https://github.com/seyko2/cfront-3 就是 cfront source code 了, 我想在 linux 下編譯, 之前嘗試過一次, 失敗了, 這次有新版再來挑戰一次, 向 bjarne stroustrup 博士致敬, 感謝他發明出 c++ 這麼複雜的語言, 整死開發 c++ 編譯器的開發人員, 當然還有學習 c++ 的程式員。

我修改過的版本在 https://github.com/descent/cfront-3, 切到 can_build_in_linux branch 即可, 你得先會用 git 才行, 好吧! git checkout can_build_in_linux 就可以了。

Makefile
 1 #Makefile for the CC translator
 2 # BSD 4.2 or later should first run bsd.sed in the scratch directory
 3 # and set CCFLAGS=-DBSD
 4 # also set BSD=1
 5 
 6 CCFLAGS=-Os
 7 scratchCC ?= gcc
 8 
 9 BSD=
10 PATH:=$(CURDIR):$(PATH)
11 
12 #For first make (bootstrap):
13 # make scratch  #on system V, BSD 4.1 or earlier
14 #Otherwise:
15 # make
16 #
17 
18 CC = CC
19 
20 all: libC.a munch cfront
21  :
22 
23 libC.a: always
24  cd lib/mk; $(MAKE) CC=$(CC) CCFLAGS="$(CCFLAGS)" BSD=$(BSD)
25  mv lib/mk/libC.a .
26 
27 munch: _munch/munch.c
28  cc -o munch _munch/munch.c
29 
30 cfront: always
31  cd src; $(MAKE) CXX=$(CC) CCFLAGS="$(CCFLAGS)"
32  mv src/cfront cfront
33  
34 scratch: always
35  cd scratch; $(MAKE) CC=$(scratchCC) BSD=$(BSD) CCFLAGS="$(CCFLAGS)"
36 
37 #This target will populate the scratch directories with good-old-c
38 #files.  This is used to port to another machine.
39 
40 fillscratch:
41  make -C src szal.result y.tab.C yystype.h
42  cp src/_stdio.c scratch/src/
43  cd scratch/src; $(CC) -I../../src         -I../../incl -Fc -..c ../../src/*.C;
44  cd scratch/lib; $(CC) -I../../lib/complex -I../../incl -Fc -..c ../../lib/new/*.C
45  cd scratch/lib; $(CC) -I../../lib/complex -I../../incl -Fc -..c ../../lib/static/*.C
46  cp _munch/*.c scratch/mnch/
47 
48 always: 

Makefile L20
all: libC.a munch cfront

總共有 3 個部份要編譯, libC.a, munch, cfront 我分 3 次手動編譯, 為了避免奇怪的錯誤, 請按以下次序編譯。

[cfront]
編譯 cfront 會用到 yacc, can_build_in_linux branch 除了修改程式碼與編譯參數, 還有 yacc 需要改為使用 byacc (Berkeley YACC, 修改 Makefile), 使用 apt-get 來安裝 byacc。

apt-get install byacc

用 bison 會有以下錯誤訊息:

bison.err
1 gram.y:2340.31-32: error: $$ for the midrule at $3 of ‘statement’ has no declared type
2         |  ID COLON { $$ = $1; stmt_seen=1; } caselab_stmt
3                                ^^
4 gram.y:2344.34-35: error: $$ for the midrule at $3 of ‘statement’ has no declared type
5         |  TNAME COLON { $$ = new name($<pn>1->string); stmt_seen=1; } caselab_stmt
6                                   ^^

編譯指令:
cd src
make CC=gcc CCFLAGS="-Os -fpermissive -I../incl-master/incl-linux32/"

很奇怪, 在 gcc 9 之下, 不能使用 -Os, 會有 list 1 的錯誤。

list 1 gcc9 error
1 "t.h", line 22: internal <<AT&T C++ Language System <3.0.3> 05/05/94>> error: bus error (or something nasty like that)

看到以下錯誤免著驚, 這是藥氣等待行, cfront 其實已經編譯出來了。

g++ -o cfront Bits.o alloc.o block.o dcl.o dcl2.o dcl3.o dcl4.o del.o discrim.o error.o expand.o expr.o expr2.o expr3.o find.o hash.o lalex.o lex.o main.o norm.o norm2.o print.o print2.o repr.o simpl.o simpl2.o size.o table.o template.o tree_copy.o tree_walk.o typ.o typ2.o y.tab.o _stdio.o
Makefile:23: recipe for target 'cfront' failed
make: [cfront] Error 1 (ignored)
cp cfront ..

cfront 編好了。

[munch]
使用 cfront 編譯時, 需要用到的一個叫 munch 的工具程式。
gcc -o munch _munch/munch.c
這麼簡單, 不需要說明, 這是 .c 不用出動 cfront。

[libC.a]
cd lib/mk
make CC=gcc CCFLAGS="-Os -I../../incl-master/incl-linux32/"

不建議用 gcc 編譯 libC.a。 建議用 cfront 編譯, 不過先要編出 cfront 才行, CC3 就會使用 cfront 來編譯。後面會提到怎麼使用 cfront 編譯出一個可以執行的檔案, 這邊的 libC.a 就需要用 cfront 來編譯, 否則會有奇怪的 link 錯誤。

編出 cfront 之後 (需要複製到 cfront-3 目錄下), 在 cfront-3 目錄下打 make libC.a 即可。

建議使用 cfront 編譯 libC, 避免出現奇怪的錯誤 (因為這樣, 出現很多靈異現象讓我找了老半天)。

cd pt
make CC=gcc

pt 目錄有一些工具程式是編譯用到 string class 的時候會用到的。
ref: cfront-3/demo/string/
string class 我沒成功編譯出來。

也可以用 cfront 編譯 cfront 自己, 不過先要編出 cfront 才行, CC3 就會使用 cfront 來編譯, 不過有些問題, 得手動修改, 我懶的改, 沒成功用 cfront 編譯 cfront 自己。

終於 build 出來了, 執行一下, 感動阿!

run cfront
1 descent@debian64:cfront-3$ ./cfront
2 # 1 ""
3
4 /* <<AT&T C++ Language System <3.0.3> 05/05/94>> */
5 char __cfront_version_303_xxxxxxxx;

用 cfont 編譯 demo/hello/hello.C

demo/hello/hello.C
1 #include <stream.h>
2 
3 main()
4 {
5     cout << "Hello, World!\n";
6 }

有點難度, 步驟如下:
cp hello.C incl-master/incl-linux32
gcc -I. -E hello.C > hh.c
../../cfront < hh.c > h3.c

有沒很感動, 輸出一個 c 的 c++ 程式, bjarne 有你的。

h3.c
  1 # 1 ""
  2 
  3 /* <<AT&T C++ Language System <3.0.3> 05/05/94>> */
  4 char __cfront_version_303_xxxxxxxx;
  5 
  6 #pragma lib "ape/libap.a"
  7 
  8 #pragma lib "c++/libC.a"
  9 
 10 # 1 ""
 11 char *__vec_new ();
 12 
 13 # 1 ""
 14 char __vec_delete ();
 15 typedef int (*__vptp)();
 16 struct __mptr {short d; short i; __vptp f; };
 17 
 18 # 1 ""
 19 extern struct __mptr* __ptbl_vec___[];
 20 
 21 # 1 ""
 22 
 23 # 49 "./iostream.h"
 24 typedef long streampos ;
 25 typedef long streamoff ;
 26 enum __Q2_3ios8io_state { goodbit__Q2_3ios8io_state = 0, eofbit__Q2_3ios8io_state = 1, failbit__Q2_3ios8io_state = 2, badbit__Q2_3ios8io_state = 4, hardfail__Q2_3ios8io_state = 128} ;
 27 enum __Q2_3ios9open_mode { in__Q2_3ios9open_mode = 1, out__Q2_3ios9open_mode = 2, ate__Q2_3ios9open_mode = 4, app__Q2_3ios9open_mode = 8, trunc__Q2_3ios9open_mode = 16, nocreate__Q2_3ios9open_mode = 32, noreplace__Q2_3ios9open_mode = 64} ;
 28 enum __Q2_3ios8seek_dir { beg__Q2_3ios8seek_dir = 0, cur__Q2_3ios8seek_dir = 1, end__Q2_3ios8seek_dir = 2} ;
 29 enum __Q2_3ios4__E1 { skipws__Q2_3ios4__E1 = 1, left__Q2_3ios4__E1 = 2, right__Q2_3ios4__E1 = 4, internal__Q2_3ios4__E1 = 8, dec__Q2_3ios4__E1 = 16, oct__Q2_3ios4__E1 = 32, hex__Q2_3ios4__E1 = 64, showbase__Q2_3ios4__E1 = 128, showpoint__Q2_3ios4__E1 = 256, uppercase__Q2_3ios4__E1 = 512, showpos__Q2_3ios4__E1 = 1024, scientific__Q2_3ios4__E1 = 2048, fixed__Q2_3ios4__E1 = 4096, unitbuf__Q2_3ios4__E1 = 8192,
 30 # 54 "./iostream.h"
 31 stdio__Q2_3ios4__E1 = 16384} ;
 32 enum __Q2_3ios4__E2 { skipping__Q2_3ios4__E2 = 512, tied__Q2_3ios4__E2 = 1024} ;
 33 struct ios { /* sizeof ios == 88 */
 34 
 35 # 153 "./iostream.h"
 36 int nuser__3ios ;
 37 
 38 # 155 "./iostream.h"
 39 union ios_user_union *x_user__3ios ;
 40 
 41 # 162 "./iostream.h"
 42 struct streambuf *bp__3ios ;
 43 
 44 # 168 "./iostream.h"
 45 int state__3ios ;
 46 int ispecial__3ios ;
 47 int ospecial__3ios ;
 48 int isfx_special__3ios ;
 49 int osfx_special__3ios ;
 50 int delbuf__3ios ;
 51 struct ostream *x_tie__3ios ;
 52 long x_flags__3ios ;
 53 short x_precision__3ios ;
 54 char x_fill__3ios ;
 55 short x_width__3ios ;
 56 
 57 # 186 "./iostream.h"
 58 int assign_private__3ios ;
 59 
 60 # 193 "./iostream.h"
 61 struct __mptr *__vptr__3ios ;
 62 };
 63 
 64 # 84 "./iostream.h"
 65 extern long basefield__3ios ;
 66 
 67 # 86 "./iostream.h"
 68 extern long adjustfield__3ios ;
 69 
 70 # 88 "./iostream.h"
 71 extern long floatfield__3ios ;
 72 
 73 # 150 "./iostream.h"
 74 extern long nextbit__3ios ;
 75 extern long nextword__3ios ;
 76 
 77 # 180 "./iostream.h"
 78 extern char (*stdioflush__3ios )();
 79 
 80 # 195 "./iostream.h"
 81 struct streambuf { /* sizeof streambuf == 80 */
 82 short alloc__9streambuf ;
 83 short x_unbuf__9streambuf ;
 84 char *x_base__9streambuf ;
 85 char *x_pbase__9streambuf ;
 86 char *x_pptr__9streambuf ;
 87 char *x_epptr__9streambuf ;
 88 char *x_gptr__9streambuf ;
 89 char *x_egptr__9streambuf ;
 90 char *x_eback__9streambuf ;
 91 int x_blen__9streambuf ;
 92 
 93 # 370 "./iostream.h"
 94 struct __mptr *__vptr__9streambuf ;
 95 };
 96 
 97 # 1 ""
 98 extern char __dl__FPv ();
 99 
100 # 246 "./iostream.h"
101 
102 # 255 "./iostream.h"
103 int doallocate__9streambufFv ();
104 
105 # 258 "./iostream.h"
106 int underflow__9streambufFv ();
107 
108 # 369 "./iostream.h"
109 int x_snextc__9streambufFv ();
110 
111 # 259 "./iostream.h"
112 int pbackfail__9streambufFi ();
113 
114 # 257 "./iostream.h"
115 int overflow__9streambufFi ();
116 
117 # 24 "./string.h"
118 extern char *memcpy ();
119 
120 # 229 "./iostream.h"
121 
122 # 265 "./iostream.h"
123 int xsputn__9streambufFPCci ();
124 
125 # 234 "./iostream.h"
126 
127 # 266 "./iostream.h"
128 int xsgetn__9streambufFPci ();
129 
130 # 372 "./iostream.h"
131 struct istream { /* sizeof istream == 112 */
132 
133 # 493 "./iostream.h"
134 int x_gcount__7istream ;
135 
136 # 503 "./iostream.h"
137 struct __mptr *__vptr__7istream ;
138 struct ios *Pios;
139 struct ios Oios;
140 };
141 
142 # 489 "./iostream.h"
143 int do_ipfx__7istreamFi ();
144 
145 # 298 "./iostream.h"
146 
147 # 302 "./iostream.h"
148 
149 # 418 "./iostream.h"
150 struct istream *rs_complicated__7istreamFRUc ();
151 
152 # 298 "./iostream.h"
153 
154 # 302 "./iostream.h"
155 
156 # 419 "./iostream.h"
157 struct istream *rs_complicated__7istreamFRc ();
158 
159 # 429 "./iostream.h"
160 struct istream *get__7istreamFPcic ();
161 
162 # 298 "./iostream.h"
163 
164 # 292 "./iostream.h"
165 
166 # 436 "./iostream.h"
167 struct istream *get_complicated__7istreamFRUc ();
168 
169 # 298 "./iostream.h"
170 
171 # 292 "./iostream.h"
172 
173 # 437 "./iostream.h"
174 struct istream *get_complicated__7istreamFRc ();
175 
176 # 377 "./iostream.h"
177 
178 # 292 "./iostream.h"
179 
180 # 163 "./iostream.h"
181 
182 # 377 "./iostream.h"
183 
184 # 281 "./iostream.h"
185 
186 # 480 "./iostream.h"
187 struct istream *read__7istreamFPci ();
188 
189 # 260 "./iostream.h"
190 int sync__9streambufFv ();
191 
192 # 505 "./iostream.h"
193 struct ostream { /* sizeof ostream == 104 */
194 
195 # 610 "./iostream.h"
196 struct __mptr *__vptr__7ostream ;
197 struct ios *Pios;
198 struct ios Oios;
199 };
200 
201 # 601 "./iostream.h"
202 int do_opfx__7ostreamFv ();
203 char do_osfx__7ostreamFv ();
204 
205 # 538 "./iostream.h"
206 struct ostream *complicated_put__7ostreamFc ();
207 
208 # 324 "./iostream.h"
209 
210 # 163 "./iostream.h"
211 
212 # 568 "./iostream.h"
213 struct ostream *ls_complicated__7ostreamFc ();
214 
215 # 324 "./iostream.h"
216 
217 # 163 "./iostream.h"
218 
219 # 569 "./iostream.h"
220 struct ostream *ls_complicated__7ostreamFUc ();
221 
222 # 324 "./iostream.h"
223 
224 # 163 "./iostream.h"
225 
226 # 572 "./iostream.h"
227 struct ostream *__ls__7ostreamFi ();
228 
229 # 329 "./iostream.h"
230 
231 # 163 "./iostream.h"
232 
233 # 589 "./iostream.h"
234 
235 # 612 "./iostream.h"
236 struct iostream { /* sizeof iostream == 128 */
237 
238 # 493 "./iostream.h"
239 int x_gcount__7istream ;
240 
241 # 503 "./iostream.h"
242 struct __mptr *__vptr__7istream ;
243 struct ios *Pios;
244 struct ostream Oostream;
245 };
246 
247 # 620 "./iostream.h"
248 struct istream_withassign { /* sizeof istream_withassign == 112 */
249 
250 # 493 "./iostream.h"
251 int x_gcount__7istream ;
252 
253 # 503 "./iostream.h"
254 struct __mptr *__vptr__7istream ;
255 struct ios *Pios;
256 struct ios Oios;
257 };
258 
259 # 644 "./iostream.h"
260 extern struct istream_withassign cin ;
261 
262 # 628 "./iostream.h"
263 struct ostream_withassign { /* sizeof ostream_withassign == 104 */
264 
265 # 610 "./iostream.h"
266 struct __mptr *__vptr__7ostream ;
267 struct ios *Pios;
268 struct ios Oios;
269 };
270 
271 # 645 "./iostream.h"
272 extern struct ostream_withassign cout ;
273 extern struct ostream_withassign cerr ;
274 extern struct ostream_withassign clog ;
275 
276 # 657 "./iostream.h"
277 struct Iostream_init { /* sizeof Iostream_init == 1 */
278 
279 # 657 "./iostream.h"
280 char __W23__13Iostream_init ;
281 };
282 
283 # 658 "./iostream.h"
284 extern int stdstatus__13Iostream_init ;
285 extern int initcount__13Iostream_init ;
286 
287 # 663 "./iostream.h"
288 char __dt__13Iostream_initFv ();
289 
290 # 662 "./iostream.h"
291 struct Iostream_init *__ct__13Iostream_initFv ();
292 
293 # 664 "./iostream.h"
294 static struct Iostream_init iostream_init ;
295 
296 #pragma lib "ape/libap.a"
297 
298 #pragma lib "c++/libC.a"
299 
300 #pragma lib "ape/libap.a"
301 
302 #pragma lib "c++/libC.a"
303 
304 # 20 "./generic.h"
305 typedef int (*GPT )();
306 
307 # 112 "./iomanip.h"
308 struct smanip_int { /* sizeof smanip_int == 16 */
309 
310 # 112 "./iomanip.h"
311 struct ios *(*fct__10smanip_int )();
312 
313 # 112 "./iomanip.h"
314 int arg__10smanip_int ;
315 };
316 
317 # 1 ""
318 extern char *__nw__FUl ();
319 
320 # 112 "./iomanip.h"
321 struct sapply_int { /* sizeof sapply_int == 8 */
322 
323 # 112 "./iomanip.h"
324 struct ios *(*fct__10sapply_int )();
325 };
326 
327 # 112 "./iomanip.h"
328 struct imanip_int { /* sizeof imanip_int == 16 */
329 
330 # 112 "./iomanip.h"
331 struct istream *(*fct__10imanip_int )();
332 
333 # 112 "./iomanip.h"
334 int arg__10imanip_int ;
335 };
336 
337 # 112 "./iomanip.h"
338 struct iapply_int { /* sizeof iapply_int == 8 */
339 
340 # 112 "./iomanip.h"
341 struct istream *(*fct__10iapply_int )();
342 };
343 
344 # 112 "./iomanip.h"
345 struct omanip_int { /* sizeof omanip_int == 16 */
346 
347 # 112 "./iomanip.h"
348 struct ostream *(*fct__10omanip_int )();
349 
350 # 112 "./iomanip.h"
351 int arg__10omanip_int ;
352 };
353 
354 # 112 "./iomanip.h"
355 struct oapply_int { /* sizeof oapply_int == 8 */
356 
357 # 112 "./iomanip.h"
358 struct ostream *(*fct__10oapply_int )();
359 };
360 
361 # 112 "./iomanip.h"
362 struct iomanip_int { /* sizeof iomanip_int == 16 */
363 
364 # 112 "./iomanip.h"
365 struct iostream *(*fct__11iomanip_int )();
366 
367 # 112 "./iomanip.h"
368 int arg__11iomanip_int ;
369 };
370 
371 # 112 "./iomanip.h"
372 struct ioapply_int { /* sizeof ioapply_int == 8 */
373 
374 # 112 "./iomanip.h"
375 struct iostream *(*fct__11ioapply_int )();
376 };
377 
378 # 112 "./iomanip.h"
379 
380 # 113 "./iomanip.h"
381 struct smanip_long { /* sizeof smanip_long == 16 */
382 
383 # 113 "./iomanip.h"
384 struct ios *(*fct__11smanip_long )();
385 
386 # 113 "./iomanip.h"
387 long arg__11smanip_long ;
388 };
389 
390 # 113 "./iomanip.h"
391 struct sapply_long { /* sizeof sapply_long == 8 */
392 
393 # 113 "./iomanip.h"
394 struct ios *(*fct__11sapply_long )();
395 };
396 
397 # 113 "./iomanip.h"
398 struct imanip_long { /* sizeof imanip_long == 16 */
399 
400 # 113 "./iomanip.h"
401 struct istream *(*fct__11imanip_long )();
402 
403 # 113 "./iomanip.h"
404 long arg__11imanip_long ;
405 };
406 
407 # 113 "./iomanip.h"
408 struct iapply_long { /* sizeof iapply_long == 8 */
409 
410 # 113 "./iomanip.h"
411 struct istream *(*fct__11iapply_long )();
412 };
413 
414 # 113 "./iomanip.h"
415 struct omanip_long { /* sizeof omanip_long == 16 */
416 
417 # 113 "./iomanip.h"
418 struct ostream *(*fct__11omanip_long )();
419 
420 # 113 "./iomanip.h"
421 long arg__11omanip_long ;
422 };
423 
424 # 113 "./iomanip.h"
425 struct oapply_long { /* sizeof oapply_long == 8 */
426 
427 # 113 "./iomanip.h"
428 struct ostream *(*fct__11oapply_long )();
429 };
430 
431 # 113 "./iomanip.h"
432 struct iomanip_long { /* sizeof iomanip_long == 16 */
433 
434 # 113 "./iomanip.h"
435 struct iostream *(*fct__12iomanip_long )();
436 
437 # 113 "./iomanip.h"
438 long arg__12iomanip_long ;
439 };
440 
441 # 113 "./iomanip.h"
442 struct ioapply_long { /* sizeof ioapply_long == 8 */
443 
444 # 113 "./iomanip.h"
445 struct iostream *(*fct__12ioapply_long )();
446 };
447 
448 # 113 "./iomanip.h"
449 
450 # 10 "./stdio.h"
451 typedef char *va_list ;
452 
453 # 118 "./stdio.h"
454 extern char *sys_errlist [];
455 extern int sys_nerr ;
456 extern unsigned char *_bufendtab [];
457 
458 # 22 "./stdiostream.h"
459 struct stdiobuf { /* sizeof stdiobuf == 96 */
460 
461 # 196 "./iostream.h"
462 short alloc__9streambuf ;
463 short x_unbuf__9streambuf ;
464 char *x_base__9streambuf ;
465 char *x_pbase__9streambuf ;
466 char *x_pptr__9streambuf ;
467 char *x_epptr__9streambuf ;
468 char *x_gptr__9streambuf ;
469 char *x_egptr__9streambuf ;
470 char *x_eback__9streambuf ;
471 int x_blen__9streambuf ;
472 
473 # 370 "./iostream.h"
474 struct __mptr *__vptr__9streambuf ;
475 
476 # 36 "./stdiostream.h"
477 struct _iobuf *fp__8stdiobuf ;
478 int last_op__8stdiobuf ;
479 char buf__8stdiobuf [2];
480 };
481 
482 # 21 "./fstream.h"
483 struct filebuf { /* sizeof filebuf == 120 */
484 
485 # 196 "./iostream.h"
486 short alloc__9streambuf ;
487 short x_unbuf__9streambuf ;
488 char *x_base__9streambuf ;
489 char *x_pbase__9streambuf ;
490 char *x_pptr__9streambuf ;
491 char *x_epptr__9streambuf ;
492 char *x_gptr__9streambuf ;
493 char *x_egptr__9streambuf ;
494 char *x_eback__9streambuf ;
495 int x_blen__9streambuf ;
496 
497 # 370 "./iostream.h"
498 struct __mptr *__vptr__9streambuf ;
499 
500 # 45 "./fstream.h"
501 int xfd__7filebuf ;
502 int mode__7filebuf ;
503 char opened__7filebuf ;
504 streampos last_seek__7filebuf ;
505 char *in_start__7filebuf ;
506 
507 # 51 "./fstream.h"
508 char lahead__7filebuf [2];
509 };
510 
511 # 23 "./fstream.h"
512 extern int openprot__7filebuf ;
513 
514 # 54 "./fstream.h"
515 struct fstreambase { /* sizeof fstreambase == 224 */
516 
517 # 72 "./fstream.h"
518 struct filebuf buf__11fstreambase ;
519 
520 # 75 "./fstream.h"
521 struct __mptr *__vptr__11fstreambase ;
522 struct ios *Pios;
523 struct ios Oios;
524 };
525 
526 # 87 "./fstream.h"
527 
528 # 70 "./fstream.h"
529 
530 # 141 "./iostream.h"
531 
532 # 70 "./fstream.h"
533 
534 # 77 "./fstream.h"
535 struct ifstream { /* sizeof ifstream == 248 */
536 
537 # 72 "./fstream.h"
538 struct filebuf buf__11fstreambase ;
539 
540 # 75 "./fstream.h"
541 struct __mptr *__vptr__11fstreambase ;
542 struct ios *Pios;
543 struct istream Oistream;
544 };
545 
546 # 102 "./fstream.h"
547 
548 # 70 "./fstream.h"
549 
550 # 141 "./iostream.h"
551 
552 # 70 "./fstream.h"
553 
554 # 92 "./fstream.h"
555 struct ofstream { /* sizeof ofstream == 240 */
556 
557 # 72 "./fstream.h"
558 struct filebuf buf__11fstreambase ;
559 
560 # 75 "./fstream.h"
561 struct __mptr *__vptr__11fstreambase ;
562 struct ios *Pios;
563 struct ostream Oostream;
564 };
565 
566 # 117 "./fstream.h"
567 
568 # 70 "./fstream.h"
569 
570 # 141 "./iostream.h"
571 
572 # 70 "./fstream.h"
573 
574 # 53 "./stream.h"
575 
576 # 54 "./stream.h"
577 
578 # 55 "./stream.h"
579 
580 # 56 "./stream.h"
581 
582 # 57 "./stream.h"
583 
584 # 58 "./stream.h"
585 
586 # 59 "./stream.h"
587 
588 # 60 "./stream.h"
589 
590 # 62 "./stream.h"
591 typedef int state_value ;
592 
593 # 571 "./iostream.h"
594 struct ostream *__ls__7ostreamFPCc ();
595 
596 # 3 "hello.C"
597 int main (){ _main(); 
598 # 4 "hello.C"
599 { 
600 # 5 "hello.C"
601 __ls__7ostreamFPCc ( (struct ostream *)(& cout ), (char *)"Hello, World!\n") ;
602 }
603 } 
604 # 6 "hello.C"
605 char __sti___main_ ()
606 # 664 "./iostream.h"
607 { __ct__13Iostream_initFv ( & iostream_init ) ;
608 
609 # 664 "./iostream.h"
610 }
611 
612 # 6 "hello.C"
613 char __std___main_ ()
614 # 664 "./iostream.h"
615 { __dt__13Iostream_initFv ( & iostream_init , 2) ;
616 
617 # 664 "./iostream.h"
618 }
619 
620 # 23 "./fstream.h"
621 int openprot__7filebuf ;
622 
623 # 56 "./iostream.h"
624 
625 # 659 "./iostream.h"
626 int initcount__13Iostream_init ;
627 
628 # 658 "./iostream.h"
629 int stdstatus__13Iostream_init ;
630 
631 # 180 "./iostream.h"
632 char (*stdioflush__3ios )();
633 
634 # 151 "./iostream.h"
635 long nextword__3ios ;
636 
637 # 150 "./iostream.h"
638 long nextbit__3ios ;
639 
640 # 88 "./iostream.h"
641 long floatfield__3ios ;
642 
643 # 86 "./iostream.h"
644 long adjustfield__3ios ;
645 
646 # 84 "./iostream.h"
647 long basefield__3ios ;
648 
649 # 6 "hello.C"
650 
651 /* the end */

只有這樣還不能滿足吧, 希望可以讓這個 c 檔案透過 gcc 編譯出可執行檔案, 這就會需要那個 libC.a 了, cout 在 libC.a 中。

上面那個是我自己亂試的, 後來我參考了 cfront-3/demo/hello/hello.sh, 知道整個使用 cfront 的編譯步驟。

cfront-3/demo/hello/hello.sh
 1 #!/bin/sh
 2
 3 # manual steps to compile a program
 4 # http://lists.nongnu.org/archive/html/tinycc-devel/2014-12/binCQHJXV7ywM.bin
 5 #
 6 # The CC script now work.
 7 # Anyway, here is how to compile a C++ file manually
 8
 9
10 D=../..
11
12 if [ ! -x ${D}/cfront ]; then
13     echo "error: cfront compiler not found"
14     exit
15 fi
16
17 cpp -I${D}/incl hello.C > hello.i                  # run preprocessor
18 ${D}/cfront +a1 +L +fhello.C < hello.i > hello..c       # run cfront
19 cc hello..c ${D}/libC.a -o hello.tmp                  # compile and link plain C
20
21 # For static con/destructors, the nm/munch thingy is needed
22
23 nm hello.tmp | ${D}/munch > hello.cdts..c  # run mn against linked binary and filter
24 cc hello..c hello.cdts..c ${D}/libC.a -o hello        # compile and link again
25
26 ./hello

我們來看看怎麼編譯在平常不過的 hello world c++ 程式。

hello.C
1 #include <stream.h>
2
3 main()
4 {
5     cout << "Hello, World!\n";
6 }

在 cfront-3 目錄中執行:
cpp -Iincl-master/incl-linux32/ hello.C > hello.i # 處理 header files
./cfront +a1 +L +fhello.C < hello.i > hello..c # 將 cpp 檔 (.C) 轉成 .c 檔
gcc hello..c ./libC.a -o hello.tmp # 不知道
nm hello.tmp | ./munch > hello.cdts..c # 不知道
gcc hello..c hello.cdts..c ./libC.a -o hello # 輸出可執行檔
./hello # 執行

看到印出來的 Hello, World 真是感動。

後來我測試了, template function, class template 都沒有問題。

用 cfront 編譯 cfront 時, alloc.C 遇到的問題:
CC3 L608
eval 'gcc -Du3b -U__GNUC__ -D__cfront__ -D__cplusplus=1 -D__signed__= -D__null=0 -E' ' -I../incl-master/incl-linux32/ -D__CFRONT_ANSI_OPT'  '-Dc_plusplus=1' '-D__cplusplus=1' '' ' -I/media/work/git/cfront-3/incl' 'alloc.C' \>/media/work/git/cfront-3/tmpdir/CC.25638/cpptmp

用 llvm 也可以作到 c++ 轉 c code, 參考 Can I use LLVM to convert C++ code to C code? 不過要 3.1 版才能用, 我的系統最低是 3.6。

不過 llvm 用的方式是先轉成 .bc 再將 .bc 轉成 c, 其實和 cfront 不太一樣。

ref:
[LLVMdev] How to enable cbe as a supported target?

至於很常用到的 vector, 這個版本付的 vector 用法和 std::vector 的用法很不同:

demo/generic/Vector.C
vectordeclare(int)
vectordeclare(float)

vectorimplement(int)
vectorimplement(float)
vector(int)     iv(VectorSize);

看起來很類似 macro 的用法, 而不是 class template 的用法, 後來將我那個 myvec.h 修改一下, 可以用在 cfront。

v.C
 1 #include <stream.h>
 2 #include "myvec.h"
 3 
 4 main()
 5 {
 6   vector<int> v;
 7   v.push_back(1);
 8   v.push_back(2);
 9   cout << v[0] << endl;
10   cout << v[1] << endl;
11 }

是可以用的。

ref:
另外一個 cfront 版本
release 1.0:
http://www.softwarepreservation.org/projects/c_plus_plus/cfront/release_1.0/src/cfront.tar.gz/view

沒有留言:

張貼留言

使用 google 的 reCAPTCHA 驗證碼, 總算可以輕鬆留言了。

我實在受不了 spam 了, 又不想讓大家的眼睛花掉, 只好放棄匿名留言。這是沒辦法中的辦法了。留言的朋友需要有 google 帳號。