Initial revision
[AROS-Contrib.git] / development / compilers / freepascal / compiler / pmodules.pas
blob19c3456e07d829ae27102cb3c92321e29a341c24
2 $Id$
3 Copyright (c) 1998-2000 by Florian Klaempfl
5 Handles the parsing and loading of the modules (ppufiles)
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 2 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, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 ****************************************************************************
23 unit pmodules;
24 { close old_current_ppu on system that are
25 short on file handles like DOS system PM }
26 {$ifdef GO32V1}
27 {$define SHORT_ON_FILE_HANDLES}
28 {$endif GO32V1}
29 {$ifdef GO32V2}
30 {$define SHORT_ON_FILE_HANDLES}
31 {$endif GO32V2}
33 {$define New_GDB}
35 interface
37 procedure proc_unit;
38 procedure proc_program(islibrary : boolean);
41 implementation
43 uses
44 globtype,version,systems,tokens,
45 cobjects,comphook,compiler,
46 globals,verbose,files,
47 symconst,symtable,aasm,types,
48 {$ifdef newcg}
49 cgbase,
50 {$else newcg}
51 hcodegen,
52 {$ifdef i386}
53 cgai386,
54 {$endif i386}
55 {$endif newcg}
56 link,assemble,import,export,gendef,ppu,comprsrc,
57 cresstr,cpubase,cpuasm,
58 {$ifdef GDB}
59 gdb,
60 {$endif GDB}
61 scanner,pbase,psystem,pdecl,psub,parser;
63 procedure create_objectfile;
64 begin
65 { create the .s file and assemble it }
66 GenerateAsm(false);
68 { Also create a smartlinked version ? }
69 if (cs_create_smart in aktmoduleswitches) then
70 begin
71 { regenerate the importssection for win32 }
72 if assigned(importssection) and
73 (target_info.target=target_i386_win32) then
74 begin
75 importssection^.clear;
76 importlib^.generatesmartlib;
77 end;
79 GenerateAsm(true);
80 if target_asm.needar then
81 Linker^.MakeStaticLibrary;
82 end;
84 { resource files }
85 CompileResourceFiles;
86 end;
89 procedure insertobjectfile;
90 { Insert the used object file for this unit in the used list for this unit }
91 begin
92 current_module^.linkunitofiles.insert(current_module^.objfilename^,link_static);
93 current_module^.flags:=current_module^.flags or uf_static_linked;
95 if (cs_create_smart in aktmoduleswitches) then
96 begin
97 current_module^.linkunitstaticlibs.insert(current_module^.staticlibfilename^,link_smart);
98 current_module^.flags:=current_module^.flags or uf_smart_linked;
99 end;
100 end;
103 procedure insertsegment;
105 procedure fixseg(p:paasmoutput;sec:tsection);
106 begin
107 p^.insert(new(pai_section,init(sec)));
108 if (cs_create_smart in aktmoduleswitches) then
109 p^.insert(new(pai_cut,init));
110 p^.concat(new(pai_section,init(sec_none)));
111 end;
113 begin
114 { Insert Ident of the compiler }
115 if (not (cs_create_smart in aktmoduleswitches))
116 {$ifndef EXTDEBUG}
117 and (not current_module^.is_unit)
118 {$endif}
119 then
120 begin
121 datasegment^.insert(new(pai_align,init(4)));
122 datasegment^.insert(new(pai_string,init('FPC '+full_version_string+
123 ' ['+date_string+'] for '+target_cpu_string+' - '+target_info.short_name)));
124 end;
125 { finish codesegment }
126 codesegment^.concat(new(pai_align,init(16)));
127 { Insert start and end of sections }
128 fixseg(codesegment,sec_code);
129 fixseg(datasegment,sec_data);
130 fixseg(bsssegment,sec_bss);
131 { we should use .rdata section for these two no ? }
132 { .rdata is a read only data section (PM) }
133 fixseg(rttilist,sec_data);
134 fixseg(consts,sec_data);
135 if assigned(resourcestringlist) then
136 fixseg(resourcestringlist,sec_data);
137 {$ifdef GDB}
138 if assigned(debuglist) then
139 begin
140 debuglist^.insert(new(pai_symbol,initname('gcc2_compiled',0)));
141 debuglist^.insert(new(pai_symbol,initname('fpc_compiled',0)));
142 fixseg(debuglist,sec_code);
143 end;
144 {$endif GDB}
145 end;
148 Procedure InsertResourceTablesTable;
150 hp : pused_unit;
151 ResourceStringTables : taasmoutput;
152 count : longint;
153 begin
154 ResourceStringTables.init;
155 count:=0;
156 hp:=pused_unit(usedunits.first);
157 while assigned(hp) do
158 begin
159 If (hp^.u^.flags and uf_has_resources)=uf_has_resources then
160 begin
161 ResourceStringTables.concat(new(pai_const_symbol,initname(hp^.u^.modulename^+'_RESOURCESTRINGLIST')));
162 inc(count);
163 end;
164 hp:=Pused_unit(hp^.next);
165 end;
166 { Add program resources, if any }
167 If ResourceStringList<>Nil then
168 begin
169 ResourceStringTables.concat(new(pai_const_symbol,initname(Current_Module^.modulename^+'_RESOURCESTRINGLIST')));
170 Inc(Count);
171 end;
172 { TableCount }
173 { doesn't work because of bug in the compiler !! (JM)
174 With ResourceStringTables do}
175 begin
176 ResourceStringTables.insert(new(pai_const,init_32bit(count)));
177 ResourceStringTables.insert(new(pai_symbol,initname_global('FPC_RESOURCESTRINGTABLES',0)));
178 ResourceStringTables.concat(new(pai_symbol_end,initname('FPC_RESOURCESTRINGTABLES')));
179 end;
180 { insert in data segment }
181 if (cs_create_smart in aktmoduleswitches) then
182 datasegment^.concat(new(pai_cut,init));
183 datasegment^.concatlist(@ResourceStringTables);
184 ResourceStringTables.done;
185 end;
188 procedure InsertInitFinalTable;
190 hp : pused_unit;
191 unitinits : taasmoutput;
192 count : longint;
193 begin
194 unitinits.init;
195 count:=0;
196 hp:=pused_unit(usedunits.first);
197 while assigned(hp) do
198 begin
199 { call the unit init code and make it external }
200 if (hp^.u^.flags and (uf_init or uf_finalize))<>0 then
201 begin
202 if (hp^.u^.flags and uf_init)<>0 then
203 begin
204 unitinits.concat(new(pai_const_symbol,initname('INIT$$'+hp^.u^.modulename^)));
206 else
207 unitinits.concat(new(pai_const,init_32bit(0)));
208 if (hp^.u^.flags and uf_finalize)<>0 then
209 begin
210 unitinits.concat(new(pai_const_symbol,initname('FINALIZE$$'+hp^.u^.modulename^)));
212 else
213 unitinits.concat(new(pai_const,init_32bit(0)));
214 inc(count);
215 end;
216 hp:=Pused_unit(hp^.next);
217 end;
218 if current_module^.islibrary then
219 if (current_module^.flags and uf_finalize)<>0 then
220 begin
221 { INIT code is done by PASCALMAIN calling }
222 unitinits.concat(new(pai_const,init_32bit(0)));
223 unitinits.concat(new(pai_const_symbol,initname('FINALIZE$$'+current_module^.modulename^)));
224 inc(count);
225 end;
226 { TableCount,InitCount }
227 unitinits.insert(new(pai_const,init_32bit(0)));
228 unitinits.insert(new(pai_const,init_32bit(count)));
229 unitinits.insert(new(pai_symbol,initname_global('INITFINAL',0)));
230 unitinits.concat(new(pai_symbol_end,initname('INITFINAL')));
231 { insert in data segment }
232 if (cs_create_smart in aktmoduleswitches) then
233 datasegment^.concat(new(pai_cut,init));
234 datasegment^.concatlist(@unitinits);
235 unitinits.done;
236 end;
239 procedure insertheap;
240 begin
241 if (cs_create_smart in aktmoduleswitches) then
242 begin
243 bsssegment^.concat(new(pai_cut,init));
244 datasegment^.concat(new(pai_cut,init));
245 end;
246 { On the Macintosh Classic M68k Architecture
247 The Heap variable is simply a POINTER to the
248 real HEAP. The HEAP must be set up by the RTL
249 and must store the pointer in this value.
250 On OS/2 the heap is also intialized by the RTL. We do
251 not output a pointer }
252 case target_info.target of
253 {$ifdef i386}
254 target_i386_OS2:
256 {$endif i386}
257 {$ifdef alpha}
258 target_alpha_linux:
260 {$endif alpha}
261 {$ifdef powerpc}
262 target_powerpc_linux:
264 {$endif powerpc}
265 {$ifdef m68k}
266 target_m68k_Mac:
267 bsssegment^.concat(new(pai_datablock,init_global('HEAP',4)));
268 target_m68k_PalmOS:
270 {$endif m68k}
271 else
272 bsssegment^.concat(new(pai_datablock,init_global('HEAP',heapsize)));
273 end;
274 {$ifdef m68k}
275 if target_info.target<>target_m68k_PalmOS then
276 begin
277 datasegment^.concat(new(pai_symbol,initname_global('HEAP_SIZE',0)));
278 datasegment^.concat(new(pai_const,init_32bit(heapsize)));
279 end;
280 {$else m68k}
281 datasegment^.concat(new(pai_symbol,initname_global('HEAPSIZE',4)));
282 datasegment^.concat(new(pai_const,init_32bit(heapsize)));
283 {$endif m68k}
284 end;
287 procedure inserttargetspecific;
288 begin
289 case target_info.target of
290 {$ifdef alpha}
291 target_alpha_linux:
293 {$endif alpha}
294 {$ifdef powerpc}
295 target_powerpc_linux:
297 {$endif powerpc}
298 {$ifdef i386}
299 target_i386_GO32V2 :
300 begin
301 { stacksize can be specified }
302 datasegment^.concat(new(pai_symbol,initname_global('__stklen',4)));
303 datasegment^.concat(new(pai_const,init_32bit(stacksize)));
304 end;
305 {$endif i386}
306 {$ifdef m68k}
307 target_m68k_Atari :
308 begin
309 { stacksize can be specified }
310 datasegment^.concat(new(pai_symbol,initname_global('__stklen',4)));
311 datasegment^.concat(new(pai_const,init_32bit(stacksize)));
312 end;
313 {$endif m68k}
314 end;
315 end;
318 function loadunit(const s : string;compile_system:boolean) : pmodule;forward;
321 procedure load_usedunits(compile_system:boolean);
323 pu : pused_unit;
324 loaded_unit : pmodule;
325 load_refs : boolean;
326 nextmapentry : longint;
327 begin
328 load_refs:=true;
329 { init the map }
330 new(current_module^.map);
331 fillchar(current_module^.map^,sizeof(tunitmap),#0);
332 {$ifdef NEWMAP}
333 current_module^.map^[0]:=current_module;
334 {$endif NEWMAP}
335 nextmapentry:=1;
336 { load the used units from interface }
337 current_module^.in_implementation:=false;
338 pu:=pused_unit(current_module^.used_units.first);
339 while assigned(pu) do
340 begin
341 if (not pu^.loaded) and (pu^.in_interface) then
342 begin
343 loaded_unit:=loadunit(pu^.name^,false);
344 if current_module^.compiled then
345 exit;
346 { register unit in used units }
347 pu^.u:=loaded_unit;
348 pu^.loaded:=true;
349 { doubles are not important for that list PM }
350 pu^.u^.dependent_units.concat(new(pdependent_unit,init(current_module)));
351 { need to recompile the current unit ? }
352 if loaded_unit^.crc<>pu^.checksum then
353 begin
354 Message2(unit_u_recompile_crc_change,current_module^.modulename^,pu^.name^);
355 current_module^.recompile_reason:=rr_crcchanged;
356 current_module^.do_compile:=true;
357 dispose(current_module^.map);
358 current_module^.map:=nil;
359 exit;
360 end;
361 { setup the map entry for deref }
362 {$ifndef NEWMAP}
363 current_module^.map^[nextmapentry]:=loaded_unit^.globalsymtable;
364 {$else NEWMAP}
365 current_module^.map^[nextmapentry]:=loaded_unit;
366 {$endif NEWMAP}
367 inc(nextmapentry);
368 if nextmapentry>maxunits then
369 Message(unit_f_too_much_units);
370 end;
371 pu:=pused_unit(pu^.next);
372 end;
373 { ok, now load the unit }
374 current_module^.globalsymtable:=new(punitsymtable,loadasunit);
375 { now only read the implementation part }
376 current_module^.in_implementation:=true;
377 { load the used units from implementation }
378 pu:=pused_unit(current_module^.used_units.first);
379 while assigned(pu) do
380 begin
381 if (not pu^.loaded) and (not pu^.in_interface) then
382 begin
383 loaded_unit:=loadunit(pu^.name^,false);
384 if current_module^.compiled then
385 exit;
386 { register unit in used units }
387 pu^.u:=loaded_unit;
388 pu^.loaded:=true;
389 { need to recompile the current unit ? }
390 if (loaded_unit^.interface_crc<>pu^.interface_checksum) {and
391 not(current_module^.in_second_compile) } then
392 begin
393 Message2(unit_u_recompile_crc_change,current_module^.modulename^,pu^.name^+' {impl}');
394 current_module^.recompile_reason:=rr_crcchanged;
395 current_module^.do_compile:=true;
396 dispose(current_module^.map);
397 current_module^.map:=nil;
398 exit;
399 end;
400 { setup the map entry for deref }
401 {$ifndef NEWMAP}
402 current_module^.map^[nextmapentry]:=loaded_unit^.globalsymtable;
403 {$else NEWMAP}
404 current_module^.map^[nextmapentry]:=loaded_unit;
405 {$endif NEWMAP}
406 inc(nextmapentry);
407 if nextmapentry>maxunits then
408 Message(unit_f_too_much_units);
409 end;
410 pu:=pused_unit(pu^.next);
411 end;
412 { load browser info if stored }
413 if ((current_module^.flags and uf_has_browser)<>0) and load_refs then
414 punitsymtable(current_module^.globalsymtable)^.load_symtable_refs;
415 { remove the map, it's not needed anymore }
416 dispose(current_module^.map);
417 current_module^.map:=nil;
418 end;
421 function loadunit(const s : string;compile_system:boolean) : pmodule;
422 const
423 ImplIntf : array[boolean] of string[15]=('interface','implementation');
425 st : punitsymtable;
426 second_time : boolean;
427 old_current_ppu : pppufile;
428 old_current_module,hp,hp2 : pmodule;
429 name : string;{ necessary because current_module^.mainsource^ is reset in compile !! }
430 scanner : pscannerfile;
432 procedure loadppufile;
433 begin
434 { load interface section }
435 if not current_module^.do_compile then
436 load_interface;
437 { only load units when we don't recompile }
438 if not current_module^.do_compile then
439 load_usedunits(compile_system);
440 { recompile if set }
441 if current_module^.do_compile then
442 begin
443 { we don't need the ppufile anymore }
444 if assigned(current_module^.ppufile) then
445 begin
446 dispose(current_module^.ppufile,done);
447 current_module^.ppufile:=nil;
448 current_ppu:=nil;
449 end;
450 { recompile the unit or give a fatal error if sources not available }
451 if not(current_module^.sources_avail) and
452 not(current_module^.sources_checked) then
453 if (not current_module^.search_unit(current_module^.modulename^,true))
454 and (length(current_module^.modulename^)>8) then
455 current_module^.search_unit(copy(current_module^.modulename^,1,8),true);
456 if not(current_module^.sources_avail) then
457 begin
458 hp:=current_module;
459 current_module:=old_current_module;
460 if hp^.recompile_reason=rr_noppu then
461 Message1(unit_f_cant_find_ppu,hp^.modulename^)
462 else
463 Message1(unit_f_cant_compile_unit,hp^.modulename^);
464 current_module:=hp;
466 else
467 begin
468 if current_module^.in_compile then
469 begin
470 current_module^.in_second_compile:=true;
471 Message1(parser_d_compiling_second_time,current_module^.modulename^);
472 end;
473 current_scanner^.tempcloseinputfile;
474 name:=current_module^.mainsource^;
475 if assigned(scanner) then
476 scanner^.invalid:=true;
477 compile(name,compile_system);
478 current_module^.in_second_compile:=false;
479 if (not current_scanner^.invalid) then
480 current_scanner^.tempopeninputfile;
481 end;
483 else
484 begin
485 { only reassemble ? }
486 if (current_module^.do_assemble) then
487 OnlyAsm;
488 end;
489 if assigned(current_module^.ppufile) then
490 begin
491 dispose(current_module^.ppufile,done);
492 current_module^.ppufile:=nil;
493 current_ppu:=nil;
494 end;
495 end;
498 dummy : pmodule;
500 begin
501 old_current_module:=current_module;
502 old_current_ppu:=current_ppu;
503 { Info }
504 Message3(unit_u_load_unit,current_module^.modulename^,ImplIntf[current_module^.in_implementation],s);
505 { unit not found }
506 st:=nil;
507 dummy:=nil;
508 { search all loaded units }
509 hp:=pmodule(loaded_units.first);
510 while assigned(hp) do
511 begin
512 if hp^.modulename^=s then
513 begin
514 { forced to reload ? }
515 if hp^.do_reload then
516 begin
517 hp^.do_reload:=false;
518 break;
519 end;
520 { the unit is already registered }
521 { and this means that the unit }
522 { is already compiled }
523 { else there is a cyclic unit use }
524 if assigned(hp^.globalsymtable) then
525 st:=punitsymtable(hp^.globalsymtable)
526 else
527 begin
528 { both units in interface ? }
529 if (not current_module^.in_implementation) and (not hp^.in_implementation) then
530 begin
531 { check for a cycle }
532 hp2:=current_module^.loaded_from;
533 while assigned(hp2) and (hp2<>hp) do
534 begin
535 if hp2^.in_implementation then
536 hp2:=nil
537 else
538 hp2:=hp2^.loaded_from;
539 end;
540 if assigned(hp2) then
541 Message2(unit_f_circular_unit_reference,current_module^.modulename^,hp^.modulename^);
542 end;
543 end;
544 break;
546 else if copy(hp^.modulename^,1,8)=s then
547 dummy:=hp;
548 { the next unit }
549 hp:=pmodule(hp^.next);
550 end;
551 if assigned(dummy) and not assigned(hp) then
552 Message2(unit_w_unit_name_error,s,dummy^.modulename^);
553 { the unit is not in the symtable stack }
554 if (not assigned(st)) then
555 begin
556 if assigned(hp) then
557 begin
558 { remove the old unit }
559 loaded_units.remove(hp);
560 scanner:=hp^.scanner;
561 hp^.reset;
562 hp^.scanner:=scanner;
563 { try to reopen ppu }
564 hp^.search_unit(s,false);
565 { try to load the unit a second time first }
566 current_module:=hp;
567 current_module^.in_second_load:=true;
568 Message1(unit_u_second_load_unit,current_module^.modulename^);
569 second_time:=true;
571 else
572 { generates a new unit info record }
573 begin
574 current_module:=new(pmodule,init(s,true));
575 scanner:=nil;
576 second_time:=false;
577 end;
578 current_ppu:=current_module^.ppufile;
579 { close old_current_ppu on system that are
580 short on file handles like DOS PM }
581 {$ifdef SHORT_ON_FILE_HANDLES}
582 if assigned(old_current_ppu) then
583 old_current_ppu^.tempclose;
584 {$endif SHORT_ON_FILE_HANDLES}
585 { now we can register the unit }
586 current_module^.loaded_from:=old_current_module;
587 loaded_units.insert(current_module);
588 { now realy load the ppu }
589 loadppufile;
590 { set compiled flag }
591 current_module^.compiled:=true;
592 { load return pointer }
593 hp:=current_module;
594 { for a second_time recompile reload all dependent units,
595 for a first time compile register the unit _once_ }
596 if second_time then
597 begin
598 { now reload all dependent units }
599 hp2:=pmodule(loaded_units.first);
600 while assigned(hp2) do
601 begin
602 if hp2^.do_reload then
603 dummy:=loadunit(hp2^.modulename^,false);
604 hp2:=pmodule(hp2^.next);
605 end;
607 else
608 usedunits.concat(new(pused_unit,init(current_module,true)));
609 end;
610 { set the old module }
611 {$ifdef SHORT_ON_FILE_HANDLES}
612 if assigned(old_current_ppu) then
613 old_current_ppu^.tempopen;
614 {$endif SHORT_ON_FILE_HANDLES}
615 current_ppu:=old_current_ppu;
616 current_module:=old_current_module;
617 loadunit:=hp;
618 end;
621 procedure loaddefaultunits;
623 hp : pmodule;
624 unitsym : punitsym;
625 begin
626 { are we compiling the system unit? }
627 if (cs_compilesystem in aktmoduleswitches) then
628 begin
629 { create system defines }
630 createconstdefs;
631 { we don't need to reset anything, it's already done in parser.pas }
632 exit;
633 end;
634 { insert the system unit, it is allways the first }
635 hp:=loadunit(upper(target_info.system_unit),true);
636 systemunit:=hp^.globalsymtable;
637 { it's always the first unit }
638 systemunit^.next:=nil;
639 symtablestack:=systemunit;
640 { add to the used units }
641 current_module^.used_units.concat(new(pused_unit,init(hp,true)));
642 unitsym:=new(punitsym,init('SYSTEM',systemunit));
643 inc(unitsym^.refs);
644 refsymtable^.insert(unitsym);
645 { read default constant definitions }
646 make_ref:=false;
647 readconstdefs;
648 { if POWER is defined in the RTL then use it for starstar overloading }
649 {$ifdef DONOTCHAINOPERATORS}
650 getsym('POWER',false);
651 {$endif DONOTCHAINOPERATORS}
652 make_ref:=true;
653 {$ifdef DONOTCHAINOPERATORS}
654 { Code now in chainoperators PM }
655 if assigned(srsym) and (srsym^.typ=procsym) and (overloaded_operators[_STARSTAR]=nil) then
656 overloaded_operators[_STARSTAR]:=pprocsym(srsym);
657 {$endif DONOTCHAINOPERATORS}
658 { Objpas unit? }
659 if m_objpas in aktmodeswitches then
660 begin
661 hp:=loadunit('OBJPAS',false);
662 psymtable(hp^.globalsymtable)^.next:=symtablestack;
663 symtablestack:=hp^.globalsymtable;
664 { add to the used units }
665 current_module^.used_units.concat(new(pused_unit,init(hp,true)));
666 unitsym:=new(punitsym,init('OBJPAS',hp^.globalsymtable));
667 inc(unitsym^.refs);
668 refsymtable^.insert(unitsym);
669 end;
670 { Profile unit? Needed for go32v2 only }
671 if (cs_profile in aktmoduleswitches) and (target_info.target=target_i386_go32v2) then
672 begin
673 hp:=loadunit('PROFILE',false);
674 psymtable(hp^.globalsymtable)^.next:=symtablestack;
675 symtablestack:=hp^.globalsymtable;
676 { add to the used units }
677 current_module^.used_units.concat(new(pused_unit,init(hp,true)));
678 unitsym:=new(punitsym,init('PROFILE',hp^.globalsymtable));
679 inc(unitsym^.refs);
680 refsymtable^.insert(unitsym);
681 end;
682 { Units only required for main module }
683 if not(current_module^.is_unit) then
684 begin
685 { Heaptrc unit }
686 if (cs_gdb_heaptrc in aktglobalswitches) then
687 begin
688 hp:=loadunit('HEAPTRC',false);
689 psymtable(hp^.globalsymtable)^.next:=symtablestack;
690 symtablestack:=hp^.globalsymtable;
691 { add to the used units }
692 current_module^.used_units.concat(new(pused_unit,init(hp,true)));
693 unitsym:=new(punitsym,init('HEAPTRC',hp^.globalsymtable));
694 inc(unitsym^.refs);
695 refsymtable^.insert(unitsym);
696 end;
697 { Lineinfo unit }
698 if (cs_gdb_lineinfo in aktglobalswitches) then
699 begin
700 hp:=loadunit('LINEINFO',false);
701 psymtable(hp^.globalsymtable)^.next:=symtablestack;
702 symtablestack:=hp^.globalsymtable;
703 { add to the used units }
704 current_module^.used_units.concat(new(pused_unit,init(hp,true)));
705 unitsym:=new(punitsym,init('LINEINFO',hp^.globalsymtable));
706 inc(unitsym^.refs);
707 refsymtable^.insert(unitsym);
708 end;
709 end;
710 { save default symtablestack }
711 defaultsymtablestack:=symtablestack;
712 end;
715 procedure loadunits;
717 s : stringid;
719 hp : pused_unit;
720 hp2 : pmodule;
721 hp3 : psymtable;
722 oldprocsym:Pprocsym;
723 unitsym : punitsym;
724 begin
725 oldprocsym:=aktprocsym;
726 consume(_USES);
727 {$ifdef DEBUG}
728 test_symtablestack;
729 {$endif DEBUG}
730 repeat
731 s:=pattern;
732 consume(_ID);
733 { Give a warning if objpas is loaded }
734 if s='OBJPAS' then
735 Message(parser_w_no_objpas_use_mode);
736 { check if the unit is already used }
737 pu:=pused_unit(current_module^.used_units.first);
738 while assigned(pu) do
739 begin
740 if (pu^.name^=s) then
741 break;
742 pu:=pused_unit(pu^.next);
743 end;
744 { avoid uses of itself }
745 if not assigned(pu) and (s<>current_module^.modulename^) then
746 begin
747 { load the unit }
748 hp2:=loadunit(s,false);
749 { the current module uses the unit hp2 }
750 current_module^.used_units.concat(new(pused_unit,init(hp2,not current_module^.in_implementation)));
751 pused_unit(current_module^.used_units.last)^.in_uses:=true;
752 if current_module^.compiled then
753 exit;
754 unitsym:=new(punitsym,init(s,hp2^.globalsymtable));
755 { never claim about unused unit if
756 there is init or finalize code PM }
757 if (hp2^.flags and (uf_init or uf_finalize))<>0 then
758 inc(unitsym^.refs);
759 refsymtable^.insert(unitsym);
761 else
762 Message1(sym_e_duplicate_id,s);
763 if token=_COMMA then
764 begin
765 pattern:='';
766 consume(_COMMA);
768 else
769 break;
770 until false;
771 consume(_SEMICOLON);
773 { set the symtable to systemunit so it gets reorderd correctly }
774 symtablestack:=defaultsymtablestack;
776 { now insert the units in the symtablestack }
777 hp:=pused_unit(current_module^.used_units.first);
778 while assigned(hp) do
779 begin
780 {$IfDef GDB}
781 if (cs_debuginfo in aktmoduleswitches) and
782 (cs_gdb_dbx in aktglobalswitches) and
783 not hp^.is_stab_written then
784 begin
785 punitsymtable(hp^.u^.globalsymtable)^.concattypestabto(debuglist);
786 hp^.is_stab_written:=true;
787 hp^.unitid:=psymtable(hp^.u^.globalsymtable)^.unitid;
788 end;
789 {$EndIf GDB}
790 if hp^.in_uses then
791 begin
792 hp3:=symtablestack;
793 while assigned(hp3) do
794 begin
795 { insert units only once ! }
796 if hp^.u^.globalsymtable=hp3 then
797 break;
798 hp3:=hp3^.next;
799 { unit isn't inserted }
800 if hp3=nil then
801 begin
802 psymtable(hp^.u^.globalsymtable)^.next:=symtablestack;
803 symtablestack:=psymtable(hp^.u^.globalsymtable);
804 {$ifdef CHAINPROCSYMS}
805 symtablestack^.chainprocsyms;
806 {$endif CHAINPROCSYMS}
807 {$ifdef DEBUG}
808 test_symtablestack;
809 {$endif DEBUG}
810 end;
811 end;
812 end;
813 hp:=pused_unit(hp^.next);
814 end;
815 aktprocsym:=oldprocsym;
816 end;
819 procedure write_gdb_info;
820 {$IfDef GDB}
822 hp : pused_unit;
823 begin
824 if not (cs_debuginfo in aktmoduleswitches) then
825 exit;
826 if (cs_gdb_dbx in aktglobalswitches) then
827 begin
828 debuglist^.concat(new(pai_asm_comment,init(strpnew('EINCL of global '+
829 punitsymtable(current_module^.globalsymtable)^.name^+' has index '+
830 tostr(punitsymtable(current_module^.globalsymtable)^.unitid)))));
831 debuglist^.concat(new(pai_stabs,init(strpnew('"'+
832 punitsymtable(current_module^.globalsymtable)^.name^+'",'+
833 tostr(N_EINCL)+',0,0,0'))));
834 punitsymtable(current_module^.globalsymtable)^.dbx_count_ok:={true}false;
835 dbx_counter:=punitsymtable(current_module^.globalsymtable)^.prev_dbx_counter;
836 do_count_dbx:=false;
837 end;
839 { now insert the units in the symtablestack }
840 hp:=pused_unit(current_module^.used_units.first);
841 while assigned(hp) do
842 begin
843 if (cs_debuginfo in aktmoduleswitches) and
844 not hp^.is_stab_written then
845 begin
846 punitsymtable(hp^.u^.globalsymtable)^.concattypestabto(debuglist);
847 hp^.is_stab_written:=true;
848 hp^.unitid:=psymtable(hp^.u^.globalsymtable)^.unitid;
849 end;
850 hp:=pused_unit(hp^.next);
851 end;
852 if current_module^.in_implementation and
853 assigned(current_module^.localsymtable) then
854 begin
855 { all types }
856 punitsymtable(current_module^.localsymtable)^.concattypestabto(debuglist);
857 { and all local symbols}
858 punitsymtable(current_module^.localsymtable)^.concatstabto(debuglist);
860 else if assigned(current_module^.globalsymtable) then
861 begin
862 { all types }
863 punitsymtable(current_module^.globalsymtable)^.concattypestabto(debuglist);
864 { and all local symbols}
865 punitsymtable(current_module^.globalsymtable)^.concatstabto(debuglist);
866 end;
867 end;
868 {$Else GDB}
869 begin
870 end;
871 {$EndIf GDB}
874 procedure parse_implementation_uses(symt:Psymtable);
875 begin
876 if token=_USES then
877 begin
878 symt^.symtabletype:=unitsymtable;
879 loadunits;
880 symt^.symtabletype:=globalsymtable;
881 {$ifdef DEBUG}
882 test_symtablestack;
883 {$endif DEBUG}
884 end;
885 end;
888 procedure setupglobalswitches;
890 procedure def_symbol(const s:string);
892 mac : pmacrosym;
893 begin
894 mac:=new(pmacrosym,init(s));
895 mac^.defined:=true;
896 Message1(parser_m_macro_defined,mac^.name);
897 macros^.insert(mac);
898 end;
900 begin
901 { can't have local browser when no global browser }
902 if (cs_local_browser in aktmoduleswitches) and
903 not(cs_browser in aktmoduleswitches) then
904 exclude(aktmoduleswitches,cs_local_browser);
906 { define a symbol in delphi,objfpc,tp,gpc mode }
907 if (m_delphi in aktmodeswitches) then
908 def_symbol('FPC_DELPHI')
909 else
910 if (m_tp in aktmodeswitches) then
911 def_symbol('FPC_TP')
912 else
913 if (m_objfpc in aktmodeswitches) then
914 def_symbol('FPC_OBJFPC')
915 else
916 if (m_gpc in aktmodeswitches) then
917 def_symbol('FPC_GPC');
918 end;
921 procedure gen_main_procsym(const name:string;options:tproctypeoption;st:psymtable);
923 stt : psymtable;
924 begin
925 {Generate a procsym for main}
926 make_ref:=false;
927 aktprocsym:=new(Pprocsym,init(name));
928 { main are allways used }
929 inc(aktprocsym^.refs);
930 {Try to insert in in static symtable ! }
931 stt:=symtablestack;
932 symtablestack:=st;
933 aktprocsym^.definition:=new(Pprocdef,init);
934 symtablestack:=stt;
935 aktprocsym^.definition^.proctypeoption:=options;
936 aktprocsym^.definition^.setmangledname(target_os.cprefix+name);
937 aktprocsym^.definition^.forwarddef:=false;
938 make_ref:=true;
939 { The localst is a local symtable. Change it into the static
940 symtable }
941 dispose(aktprocsym^.definition^.localst,done);
942 aktprocsym^.definition^.localst:=st;
943 { and insert the procsym in symtable }
944 st^.insert(aktprocsym);
945 { set some informations about the main program }
946 with procinfo^ do
947 begin
948 returntype.setdef(voiddef);
949 _class:=nil;
950 para_offset:=8;
951 framepointer:=frame_pointer;
952 flags:=0;
953 end;
954 end;
957 procedure proc_unit;
959 function is_assembler_generated:boolean;
960 begin
961 is_assembler_generated:=(Errorcount=0) and
962 not(
963 codesegment^.empty and
964 datasegment^.empty and
965 bsssegment^.empty and
966 ((importssection=nil) or importssection^.empty) and
967 ((resourcesection=nil) or resourcesection^.empty) and
968 ((resourcestringlist=nil) or resourcestringlist^.empty)
970 end;
973 main_file: pinputfile;
974 {$ifdef fixLeaksOnError}
975 names : Pstringcontainer;
976 {$else fixLeaksOnError}
977 names : Tstringcontainer;
978 {$endif fixLeaksOnError}
979 st : psymtable;
980 unitst : punitsymtable;
981 {$ifdef GDB}
982 pu : pused_unit;
983 {$endif GDB}
984 {$ifndef Dont_use_double_checksum}
985 store_crc,store_interface_crc : longint;
986 {$endif}
987 s1,s2 : ^string; {Saves stack space}
988 force_init_final : boolean;
990 begin
991 consume(_UNIT);
992 if Compile_Level=1 then
993 IsExe:=false;
995 if token=_ID then
996 begin
997 { create filenames and unit name }
998 main_file := current_scanner^.inputfile;
999 while assigned(main_file^.next) do
1000 main_file := main_file^.next;
1002 current_module^.SetFileName(main_file^.path^+main_file^.name^,true);
1004 stringdispose(current_module^.modulename);
1005 current_module^.modulename:=stringdup(upper(pattern));
1006 { check for system unit }
1007 new(s1);
1008 new(s2);
1009 s1^:=upper(target_info.system_unit);
1010 s2^:=upper(SplitName(main_file^.name^));
1011 if (cs_compilesystem in aktmoduleswitches) then
1012 begin
1013 if ((length(current_module^.modulename^)>8) or
1014 ((current_module^.modulename^<>s1^) and
1015 (current_module^.modulename^<>'SYSTEM')) or
1016 (current_module^.modulename^<>s2^)) then
1017 Message1(unit_e_illegal_unit_name,current_module^.modulename^);
1019 else
1020 begin
1021 if (cs_check_unit_name in aktglobalswitches) and
1022 not((current_module^.modulename^=s2^) or
1023 ((length(current_module^.modulename^)>8) and
1024 (copy(current_module^.modulename^,1,8)=s2^))) then
1025 Message1(unit_e_illegal_unit_name,current_module^.modulename^);
1026 if (current_module^.modulename^=s1^) then
1027 Message(unit_w_switch_us_missed);
1028 end;
1029 dispose(s2);
1030 dispose(s1);
1031 end;
1033 consume(_ID);
1034 consume(_SEMICOLON);
1035 consume(_INTERFACE);
1036 { global switches are read, so further changes aren't allowed }
1037 current_module^.in_global:=false;
1039 { handle the global switches }
1040 setupglobalswitches;
1042 Message1(unit_u_start_parse_interface,current_module^.modulename^);
1044 { update status }
1045 status.currentmodule:=current_module^.modulename^;
1047 { maybe turn off m_objpas if we are compiling objpas }
1048 if (current_module^.modulename^='OBJPAS') then
1049 aktmodeswitches:=aktmodeswitches-[m_objpas];
1051 { this should be placed after uses !!}
1052 {$ifndef UseNiceNames}
1053 procprefix:='_'+current_module^.modulename^+'$$';
1054 {$else UseNiceNames}
1055 procprefix:='_'+tostr(length(current_module^.modulename^))+lowercase(current_module^.modulename^)+'_';
1056 {$endif UseNiceNames}
1058 parse_only:=true;
1060 { generate now the global symboltable }
1061 st:=new(punitsymtable,init(globalsymtable,current_module^.modulename^));
1062 refsymtable:=st;
1063 unitst:=punitsymtable(st);
1064 { define first as local to overcome dependency conflicts }
1065 current_module^.localsymtable:=st;
1067 { the unit name must be usable as a unit specifier }
1068 { inside the unit itself (PM) }
1069 { this also forbids to have another symbol }
1070 { with the same name as the unit }
1071 refsymtable^.insert(new(punitsym,init(current_module^.modulename^,unitst)));
1073 { a unit compiled at command line must be inside the loaded_unit list }
1074 if (compile_level=1) then
1075 loaded_units.insert(current_module);
1077 { load default units, like the system unit }
1078 loaddefaultunits;
1080 { reset }
1081 make_ref:=true;
1082 lexlevel:=0;
1084 { insert qualifier for the system unit (allows system.writeln) }
1085 if not(cs_compilesystem in aktmoduleswitches) then
1086 begin
1087 if token=_USES then
1088 begin
1089 unitst^.symtabletype:=unitsymtable;
1090 loadunits;
1091 { has it been compiled at a higher level ?}
1092 if current_module^.compiled then
1093 begin
1094 { this unit symtable is obsolete }
1095 { dispose(unitst,done);
1096 disposed as localsymtable !! }
1097 RestoreUnitSyms;
1098 exit;
1099 end;
1100 unitst^.symtabletype:=globalsymtable;
1101 end;
1102 { ... but insert the symbol table later }
1103 st^.next:=symtablestack;
1104 symtablestack:=st;
1106 else
1107 { while compiling a system unit, some types are directly inserted }
1108 begin
1109 st^.next:=symtablestack;
1110 symtablestack:=st;
1111 insert_intern_types(st);
1112 end;
1114 { now we know the place to insert the constants }
1115 constsymtable:=symtablestack;
1117 { move the global symtab from the temporary local to global }
1118 current_module^.globalsymtable:=current_module^.localsymtable;
1119 current_module^.localsymtable:=nil;
1121 reset_global_defs;
1123 { number all units, so we know if a unit is used by this unit or
1124 needs to be added implicitly }
1125 numberunits;
1127 { ... parse the declarations }
1128 Message1(parser_u_parsing_interface,current_module^.modulename^);
1129 read_interface_declarations;
1131 { leave when we got an error }
1132 if (Errorcount>0) and not status.skip_error then
1133 begin
1134 Message1(unit_f_errors_in_unit,tostr(Errorcount));
1135 status.skip_error:=true;
1136 exit;
1137 end;
1138 {else in inteface its somatimes necessary even if unused
1139 st^.allunitsused; }
1141 {$ifdef New_GDB}
1142 write_gdb_info;
1143 {$endIf Def New_GDB}
1145 {$ifndef Dont_use_double_checksum}
1146 if not(cs_compilesystem in aktmoduleswitches) then
1147 if (Errorcount=0) then
1148 writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack),true);
1149 {$endif Test_Double_checksum}
1151 { Parse the implementation section }
1152 consume(_IMPLEMENTATION);
1153 current_module^.in_implementation:=true;
1154 Message1(unit_u_start_parse_implementation,current_module^.modulename^);
1156 parse_only:=false;
1158 { generates static symbol table }
1159 st:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
1160 current_module^.localsymtable:=st;
1162 { remove the globalsymtable from the symtable stack }
1163 { to reinsert it after loading the implementation units }
1164 symtablestack:=unitst^.next;
1166 { we don't want implementation units symbols in unitsymtable !! PM }
1167 refsymtable:=st;
1169 { Read the implementation units }
1170 parse_implementation_uses(unitst);
1172 if current_module^.compiled then
1173 begin
1174 RestoreUnitSyms;
1175 exit;
1176 end;
1178 { reset ranges/stabs in exported definitions }
1179 reset_global_defs;
1181 { All units are read, now give them a number }
1182 numberunits;
1184 { now we can change refsymtable }
1185 refsymtable:=st;
1187 { but reinsert the global symtable as lasts }
1188 unitst^.next:=symtablestack;
1189 symtablestack:=unitst;
1191 {$ifndef DONOTCHAINOPERATORS}
1192 symtablestack^.chainoperators;
1193 {$endif DONOTCHAINOPERATORS}
1195 {$ifdef DEBUG}
1196 test_symtablestack;
1197 {$endif DEBUG}
1198 constsymtable:=symtablestack;
1200 {$ifdef Splitheap}
1201 if testsplit then
1202 begin
1203 Split_Heap;
1204 allow_special:=true;
1205 Switch_to_temp_heap;
1206 end;
1207 { it will report all crossings }
1208 allow_special:=false;
1209 {$endif Splitheap}
1211 Message1(parser_u_parsing_implementation,current_module^.modulename^);
1213 { Compile the unit }
1214 codegen_newprocedure;
1215 gen_main_procsym(current_module^.modulename^+'_init',potype_unitinit,st);
1216 {$ifdef fixLeaksOnError}
1217 new(names,init);
1218 strContStack.push(names);
1219 names^.insert('INIT$$'+current_module^.modulename^);
1220 names^.insert(target_os.cprefix+current_module^.modulename^+'_init');
1221 compile_proc_body(names^,true,false);
1222 if names <> PstringContainer(strContStack.pop) then
1223 writeln('Problem with strContStack in pmodules (1)');
1224 dispose(names,done);
1225 {$else fixLeaksOnError}
1226 names.init;
1227 names.insert('INIT$$'+current_module^.modulename^);
1228 names.insert(target_os.cprefix+current_module^.modulename^+'_init');
1229 compile_proc_body(names,true,false);
1230 names.done;
1231 {$endif fixLeaksOnError}
1232 codegen_doneprocedure;
1234 { avoid self recursive destructor call !! PM }
1235 aktprocsym^.definition^.localst:=nil;
1237 { if the unit contains ansi/widestrings, initialization and
1238 finalization code must be forced }
1239 force_init_final:=needs_init_final(current_module^.globalsymtable)
1240 or needs_init_final(current_module^.localsymtable);
1242 { should we force unit initialization? }
1243 { this is a hack, but how can it be done better ? }
1244 if force_init_final and ((current_module^.flags and uf_init)=0) then
1245 begin
1246 current_module^.flags:=current_module^.flags or uf_init;
1247 { now we can insert a cut }
1248 if (cs_create_smart in aktmoduleswitches) then
1249 codesegment^.concat(new(pai_cut,init));
1250 genimplicitunitinit(codesegment);
1251 end;
1252 { finalize? }
1253 if token=_FINALIZATION then
1254 begin
1255 { set module options }
1256 current_module^.flags:=current_module^.flags or uf_finalize;
1258 { Compile the finalize }
1259 codegen_newprocedure;
1260 gen_main_procsym(current_module^.modulename^+'_finalize',potype_unitfinalize,st);
1261 {$ifdef fixLeaksOnError}
1262 new(names,init);
1263 strContStack.push(names);
1264 names^.insert('FINALIZE$$'+current_module^.modulename^);
1265 names^.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
1266 compile_proc_body(names^,true,false);
1267 if names <> PstringContainer(strContStack.pop) then
1268 writeln('Problem with strContStack in pmodules (2)');
1269 dispose(names,done);
1270 {$else fixLeaksOnError}
1271 names.init;
1272 names.insert('FINALIZE$$'+current_module^.modulename^);
1273 names.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
1274 compile_proc_body(names,true,false);
1275 names.done;
1276 {$endif fixLeaksOnError}
1277 codegen_doneprocedure;
1279 else if force_init_final then
1280 begin
1281 current_module^.flags:=current_module^.flags or uf_finalize;
1282 { now we can insert a cut }
1283 if (cs_create_smart in aktmoduleswitches) then
1284 codesegment^.concat(new(pai_cut,init));
1285 genimplicitunitfinal(codesegment);
1286 end;
1288 { the last char should always be a point }
1289 consume(_POINT);
1291 If ResourceStrings^.ResStrCount>0 then
1292 begin
1293 ResourceStrings^.CreateResourceStringList;
1294 current_module^.flags:=current_module^.flags or uf_has_resources;
1295 { only write if no errors found }
1296 if (Errorcount=0) then
1297 ResourceStrings^.WriteResourceFile(Current_module^.ModuleName^);
1298 end;
1300 { avoid self recursive destructor call !! PM }
1301 aktprocsym^.definition^.localst:=nil;
1302 { absence does not matter here !! }
1303 aktprocsym^.definition^.forwarddef:=false;
1304 { test static symtable }
1305 if (Errorcount=0) then
1306 begin
1307 st^.allsymbolsused;
1308 st^.allunitsused;
1309 st^.allprivatesused;
1310 end;
1312 { size of the static data }
1313 datasize:=st^.datasize;
1315 {$ifdef GDB}
1316 { add all used definitions even for implementation}
1317 if (cs_debuginfo in aktmoduleswitches) then
1318 begin
1319 {$IfnDef New_GDB}
1320 if assigned(current_module^.globalsymtable) then
1321 begin
1322 { all types }
1323 punitsymtable(current_module^.globalsymtable)^.concattypestabto(debuglist);
1324 { and all local symbols}
1325 punitsymtable(current_module^.globalsymtable)^.concatstabto(debuglist);
1326 end;
1327 { all local types }
1328 punitsymtable(st)^.concattypestabto(debuglist);
1329 { and all local symbols}
1330 st^.concatstabto(debuglist);
1331 {$else New_GDB}
1332 write_gdb_info;
1333 {$endIf Def New_GDB}
1334 end;
1335 {$endif GDB}
1337 reset_global_defs;
1339 { tests, if all (interface) forwards are resolved }
1340 if (Errorcount=0) then
1341 begin
1342 symtablestack^.check_forwards;
1343 symtablestack^.allprivatesused;
1344 end;
1346 { now we have a correct unit, change the symtable type }
1347 current_module^.in_implementation:=false;
1348 symtablestack^.symtabletype:=unitsymtable;
1349 {$ifdef GDB}
1350 punitsymtable(symtablestack)^.is_stab_written:=false;
1351 {$endif GDB}
1353 { leave when we got an error }
1354 if (Errorcount>0) and not status.skip_error then
1355 begin
1356 Message1(unit_f_errors_in_unit,tostr(Errorcount));
1357 status.skip_error:=true;
1358 closecurrentppu;
1359 exit;
1360 end;
1362 { generate imports }
1363 if current_module^.uses_imports then
1364 importlib^.generatelib;
1366 { insert own objectfile, or say that it's in a library
1367 (no check for an .o when loading) }
1368 if is_assembler_generated then
1369 insertobjectfile
1370 else
1371 current_module^.flags:=current_module^.flags or uf_no_link;
1373 if cs_local_browser in aktmoduleswitches then
1374 current_module^.localsymtable:=refsymtable;
1375 { Write out the ppufile }
1376 {$ifndef Dont_use_double_checksum}
1377 store_interface_crc:=current_module^.interface_crc;
1378 store_crc:=current_module^.crc;
1379 {$endif Test_Double_checksum}
1380 if (Errorcount=0) then
1381 writeunitas(current_module^.ppufilename^,punitsymtable(symtablestack),false);
1383 {$ifndef Dont_use_double_checksum}
1384 if not(cs_compilesystem in aktmoduleswitches) then
1385 if store_interface_crc<>current_module^.interface_crc then
1386 Comment(V_Warning,current_module^.ppufilename^+' Interface CRC changed '+
1387 tostr(store_crc)+'<>'+tostr(current_module^.interface_crc));
1388 {$ifdef EXTDEBUG}
1389 if not(cs_compilesystem in aktmoduleswitches) then
1390 if (store_crc<>current_module^.crc) and simplify_ppu then
1391 Comment(V_Warning,current_module^.ppufilename^+' implementation CRC changed '+
1392 tostr(store_crc)+'<>'+tostr(current_module^.interface_crc));
1393 {$endif EXTDEBUG}
1394 {$endif ndef Dont_use_Double_checksum}
1395 { must be done only after local symtable ref stores !! }
1396 closecurrentppu;
1397 {$ifdef GDB}
1398 pu:=pused_unit(usedunits.first);
1399 while assigned(pu) do
1400 begin
1401 if assigned(pu^.u^.globalsymtable) then
1402 punitsymtable(pu^.u^.globalsymtable)^.is_stab_written:=false;
1403 pu:=pused_unit(pu^.next);
1404 end;
1405 {$endif GDB}
1407 { remove static symtable (=refsymtable) here to save some mem }
1408 if not (cs_local_browser in aktmoduleswitches) then
1409 begin
1410 dispose(st,done);
1411 current_module^.localsymtable:=nil;
1412 end;
1415 RestoreUnitSyms;
1417 if is_assembler_generated then
1418 begin
1419 { finish asmlist by adding segment starts }
1420 insertsegment;
1421 { assemble }
1422 create_objectfile;
1423 end;
1425 { leave when we got an error }
1426 if (Errorcount>0) and not status.skip_error then
1427 begin
1428 Message1(unit_f_errors_in_unit,tostr(Errorcount));
1429 status.skip_error:=true;
1430 exit;
1431 end;
1432 end;
1435 procedure proc_program(islibrary : boolean);
1437 main_file: pinputfile;
1438 st : psymtable;
1439 hp : pmodule;
1440 {$ifdef fixLeaksOnError}
1441 names : Pstringcontainer;
1442 {$else fixLeaksOnError}
1443 names : Tstringcontainer;
1444 {$endif fixLeaksOnError}
1445 begin
1446 DLLsource:=islibrary;
1447 Compiler.IsLibrary:=IsLibrary;
1448 IsExe:=true;
1449 parse_only:=false;
1450 { relocation works only without stabs under win32 !! PM }
1451 { internal assembler uses rva for stabs info
1452 so it should work with relocated DLLs }
1453 if RelocSection and
1454 (target_info.target=target_i386_win32) and
1455 (target_info.assem<>as_i386_pecoff) then
1456 begin
1457 aktglobalswitches:=aktglobalswitches+[cs_link_strip];
1458 { Warning stabs info does not work with reloc section !! }
1459 if cs_debuginfo in aktmoduleswitches then
1460 begin
1461 Message1(parser_w_parser_reloc_no_debug,current_module^.mainsource^);
1462 Message(parser_w_parser_win32_debug_needs_WN);
1463 aktmoduleswitches:=aktmoduleswitches-[cs_debuginfo];
1464 end;
1465 end;
1467 { get correct output names }
1468 main_file := current_scanner^.inputfile;
1469 while assigned(main_file^.next) do
1470 main_file := main_file^.next;
1472 current_module^.SetFileName(main_file^.path^+main_file^.name^,true);
1474 if islibrary then
1475 begin
1476 consume(_LIBRARY);
1477 stringdispose(current_module^.modulename);
1478 current_module^.modulename:=stringdup(pattern);
1479 current_module^.islibrary:=true;
1480 exportlib^.preparelib(pattern);
1481 consume(_ID);
1482 consume(_SEMICOLON);
1484 else
1485 { is there an program head ? }
1486 if token=_PROGRAM then
1487 begin
1488 consume(_PROGRAM);
1489 stringdispose(current_module^.modulename);
1490 current_module^.modulename:=stringdup(pattern);
1491 if (target_info.target=target_i386_WIN32) then
1492 exportlib^.preparelib(pattern);
1493 consume(_ID);
1494 if token=_LKLAMMER then
1495 begin
1496 consume(_LKLAMMER);
1497 idlist;
1498 consume(_RKLAMMER);
1499 end;
1500 consume(_SEMICOLON);
1502 else if (target_info.target=target_i386_WIN32) then
1503 exportlib^.preparelib(current_module^.modulename^);
1505 { global switches are read, so further changes aren't allowed }
1506 current_module^.in_global:=false;
1508 { setup things using the global switches }
1509 setupglobalswitches;
1511 { set implementation flag }
1512 current_module^.in_implementation:=true;
1514 { insert after the unit symbol tables the static symbol table }
1515 { of the program }
1516 st:=new(punitsymtable,init(staticsymtable,current_module^.modulename^));
1517 current_module^.localsymtable:=st;
1518 symtablestack:=st;
1519 refsymtable:=st;
1521 { necessary for browser }
1522 loaded_units.insert(current_module);
1524 { load standard units (system,objpas,profile unit) }
1525 loaddefaultunits;
1527 { reset }
1528 lexlevel:=0;
1530 {Load the units used by the program we compile.}
1531 if token=_USES then
1532 loadunits;
1534 {$ifndef DONOTCHAINOPERATORS}
1535 symtablestack^.chainoperators;
1536 {$endif DONOTCHAINOPERATORS}
1538 { reset ranges/stabs in exported definitions }
1539 reset_global_defs;
1541 { All units are read, now give them a number }
1542 numberunits;
1544 {Insert the name of the main program into the symbol table.}
1545 if current_module^.modulename^<>'' then
1546 {st^.insert(new(pprogramsym,init(current_module^.modulename^)));}
1547 st^.insert(new(punitsym,init(current_module^.modulename^,punitsymtable(st))));
1549 { ...is also constsymtable, this is the symtable where }
1550 { the elements of enumeration types are inserted }
1551 constsymtable:=st;
1553 Message1(parser_u_parsing_implementation,current_module^.mainsource^);
1555 { reset }
1556 procprefix:='';
1558 {The program intialization needs an alias, so it can be called
1559 from the bootstrap code.}
1560 codegen_newprocedure;
1561 gen_main_procsym('main',potype_proginit,st);
1562 {$ifdef fixLeaksOnError}
1563 new(names,init);
1564 strContStack.push(names);
1565 names^.insert('program_init');
1566 names^.insert('PASCALMAIN');
1567 names^.insert(target_os.cprefix+'main');
1568 {$ifdef m68k}
1569 if target_info.target=target_m68k_PalmOS then
1570 names^.insert('PilotMain');
1571 {$endif m68k}
1572 compile_proc_body(names^,true,false);
1573 if names <> PstringContainer(strContStack.pop) then
1574 writeln('Problem with strContStack in pmodules (1)');
1575 dispose(names,done);
1576 {$else fixLeaksOnError}
1577 names.init;
1578 names.insert('program_init');
1579 names.insert('PASCALMAIN');
1580 names.insert(target_os.cprefix+'main');
1581 {$ifdef m68k}
1582 if target_info.target=target_m68k_PalmOS then
1583 names.insert('PilotMain');
1584 {$endif m68k}
1585 compile_proc_body(names,true,false);
1586 names.done;
1587 {$endif fixLeaksOnError}
1589 { avoid self recursive destructor call !! PM }
1590 aktprocsym^.definition^.localst:=nil;
1592 { consider these symbols as global ones }
1593 { for browser }
1594 current_module^.globalsymtable:=current_module^.localsymtable;
1595 current_module^.localsymtable:=nil;
1597 If ResourceStrings^.ResStrCount>0 then
1598 begin
1599 ResourceStrings^.CreateResourceStringList;
1600 { only write if no errors found }
1601 if (Errorcount=0) then
1602 ResourceStrings^.WriteResourceFile(Current_module^.ModuleName^);
1603 end;
1605 codegen_doneprocedure;
1607 { finalize? }
1608 if token=_FINALIZATION then
1609 begin
1610 { set module options }
1611 current_module^.flags:=current_module^.flags or uf_finalize;
1613 { Compile the finalize }
1614 codegen_newprocedure;
1615 gen_main_procsym(current_module^.modulename^+'_finalize',potype_unitfinalize,st);
1616 {$ifdef fixLeaksOnError}
1617 new(names,init);
1618 strContStack.push(names);
1619 names^.insert('FINALIZE$$'+current_module^.modulename^);
1620 names^.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
1621 compile_proc_body(names^,true,false);
1622 if names <> PstringContainer(strContStack.pop) then
1623 writeln('Problem with strContStack in pmodules (1)');
1624 dispose(names,done);
1625 {$else fixLeaksOnError}
1626 names.init;
1627 names.insert('FINALIZE$$'+current_module^.modulename^);
1628 names.insert(target_os.cprefix+current_module^.modulename^+'_finalize');
1629 compile_proc_body(names,true,false);
1630 names.done;
1631 {$endif fixLeaksOnError}
1632 codegen_doneprocedure;
1633 end;
1635 { consume the last point }
1636 consume(_POINT);
1638 {$ifdef New_GDB}
1639 write_gdb_info;
1640 {$endIf Def New_GDB}
1641 { leave when we got an error }
1642 if (Errorcount>0) and not status.skip_error then
1643 begin
1644 Message1(unit_f_errors_in_unit,tostr(Errorcount));
1645 status.skip_error:=true;
1646 exit;
1647 end;
1649 { test static symtable }
1650 if (Errorcount=0) then
1651 begin
1652 st^.allsymbolsused;
1653 st^.allunitsused;
1654 st^.allprivatesused;
1655 end;
1657 { generate imports }
1658 if current_module^.uses_imports then
1659 importlib^.generatelib;
1661 if islibrary or
1662 (target_info.target=target_i386_WIN32) then
1663 exportlib^.generatelib;
1666 { insert heap }
1667 insertResourceTablesTable;
1668 insertinitfinaltable;
1669 insertheap;
1670 inserttargetspecific;
1672 datasize:=symtablestack^.datasize;
1674 { finish asmlist by adding segment starts }
1675 insertsegment;
1677 { insert own objectfile }
1678 insertobjectfile;
1680 { assemble and link }
1681 create_objectfile;
1683 { leave when we got an error }
1684 if (Errorcount>0) and not status.skip_error then
1685 begin
1686 Message1(unit_f_errors_in_unit,tostr(Errorcount));
1687 status.skip_error:=true;
1688 exit;
1689 end;
1691 { create the executable when we are at level 1 }
1692 if (compile_level=1) then
1693 begin
1694 { insert all .o files from all loaded units }
1695 hp:=pmodule(loaded_units.first);
1696 while assigned(hp) do
1697 begin
1698 Linker^.AddModuleFiles(hp);
1699 hp:=pmodule(hp^.next);
1700 end;
1701 { write .def file }
1702 if (cs_link_deffile in aktglobalswitches) then
1703 deffile.writefile;
1704 { finally we can create a executable }
1705 if (not current_module^.is_unit) then
1706 begin
1707 if DLLSource then
1708 Linker^.MakeSharedLibrary
1709 else
1710 Linker^.MakeExecutable;
1711 end;
1712 end;
1713 end;
1715 end.
1717 $Log$
1718 Revision 1.1 2002/02/19 08:22:46 sasu
1719 Initial revision
1721 Revision 1.1.2.8 2000/11/19 00:20:13 pierre
1722 + set Compiler.IsLibrary
1724 Revision 1.1.2.7 2000/10/18 14:53:33 pierre
1725 * add fpc_compiled assembler local symbol
1727 Revision 1.1.2.6 2000/10/15 07:49:01 peter
1728 * Also allow system as name for the system unit, required for
1729 bootstrapping the 1.1 branch
1731 Revision 1.1.2.5 2000/09/30 16:06:33 peter
1732 * show filepos when unit can't be found
1734 Revision 1.1.2.4 2000/09/24 21:36:26 peter
1735 + setcompilemode() routine
1737 Revision 1.1.2.3 2000/08/25 08:44:25 jonas
1738 * fixed bug with include files at the very beginning of .pp/.pas files
1739 (wrong name used for generating exe/checking unit name)
1741 Revision 1.1.2.2 2000/08/21 08:09:47 pierre
1742 * fix stabs problems
1744 Revision 1.1.2.1 2000/08/18 12:48:57 pierre
1745 * generate type stabs at correct location for main file
1747 Revision 1.1 2000/07/13 06:29:54 michael
1748 + Initial import
1750 Revision 1.197 2000/06/15 18:10:11 peter
1751 * first look for ppu in cwd and outputpath and after that for source
1752 in cwd
1753 * fixpath() for not linux makes path now lowercase so comparing paths
1754 with different cases (sometimes a drive letter could be
1755 uppercased) gives the expected results
1756 * sources_checked flag if there was already a full search for sources
1757 which aren't found, so another scan isn't done when checking for the
1758 sources only when recompile is needed
1760 Revision 1.196 2000/06/01 19:09:57 peter
1761 * made resourcestrings OOP so it's easier to handle it per module
1763 Revision 1.195 2000/05/11 09:40:11 pierre
1764 * some DBX changes but it still does not work !
1766 Revision 1.194 2000/05/08 13:18:09 peter
1767 * fixed setting of output names with includefile
1769 Revision 1.193 2000/05/04 20:43:33 peter
1770 * don't write rst files if errors found
1772 Revision 1.192 2000/05/03 14:39:51 pierre
1773 * Use RestoreUnitsSyms to avoid wrong hints about unused units
1774 * Avoid hints about unsused units if thet have a init or finalize code
1776 Revision 1.191 2000/04/27 11:35:03 pierre
1777 * power to ** operator fixed
1779 Revision 1.190 2000/04/26 08:54:18 pierre
1780 * More changes for operator bug
1781 Order_overloaded method removed because it conflicted with
1782 new implementation where the defs are ordered
1783 according to the unit loading order !
1785 Revision 1.189 2000/04/25 23:55:30 pierre
1786 + Hint about unused unit
1787 * Testop bug fixed !!
1788 Now the operators are only applied if the unit is explicitly loaded
1790 Revision 1.188 2000/04/14 08:15:05 pierre
1791 * close ppu file if errors
1793 Revision 1.187 2000/04/02 10:18:18 florian
1794 * bug 701 fixed: ansistrings in interface and implementation part of the units
1795 are now finalized correctly even if there are no explicit initialization/
1796 finalization statements
1798 Revision 1.186 2000/03/01 15:36:11 florian
1799 * some new stuff for the new cg
1801 Revision 1.185 2000/02/09 13:22:57 peter
1802 * log truncated
1804 Revision 1.184 2000/02/06 17:20:53 peter
1805 * -gl switch for auto lineinfo including
1807 Revision 1.183 2000/01/16 22:17:12 peter
1808 * renamed call_offset to para_offset
1810 Revision 1.182 2000/01/16 14:15:33 jonas
1811 * changed "with object_type" construct because of bug in the
1812 compiler
1814 Revision 1.181 2000/01/12 10:30:15 peter
1815 * align codesegment at the end after main proc
1817 Revision 1.180 2000/01/11 17:16:05 jonas
1818 * removed a lot of memory leaks when an error is encountered (caused by
1819 procinfo and pstringcontainers). There are still plenty left though :)
1821 Revision 1.179 2000/01/11 09:52:07 peter
1822 * fixed placing of .sl directories
1823 * use -b again for base-file selection
1824 * fixed group writing for linux with smartlinking
1826 Revision 1.178 2000/01/07 01:14:29 peter
1827 * updated copyright to 2000
1829 Revision 1.177 1999/12/20 22:29:26 pierre
1830 * relocation with debug info in rva (only with internal compiler)
1832 Revision 1.176 1999/12/10 10:02:53 peter
1833 * only check relocsection for win32
1835 Revision 1.175 1999/11/30 10:40:44 peter
1836 + ttype, tsymlist
1838 Revision 1.174 1999/11/29 16:24:52 pierre
1839 * bug in previous commit corrected
1841 Revision 1.173 1999/11/29 15:18:27 pierre
1842 + allow exports in win32 executables
1844 Revision 1.172 1999/11/24 11:41:05 pierre
1845 * defaultsymtablestack is now restored after parser.compile
1847 Revision 1.171 1999/11/22 22:21:46 pierre
1848 * Compute correct Exe Filenam
1850 Revision 1.170 1999/11/22 00:23:09 pierre
1851 * also complain about unused functions in program
1853 Revision 1.169 1999/11/20 01:19:10 pierre
1854 * DLL index used for win32 target with DEF file
1855 + DLL initialization/finalization support
1857 Revision 1.168 1999/11/18 23:35:40 pierre
1858 * avoid double warnings
1860 Revision 1.167 1999/11/18 15:34:47 pierre
1861 * Notes/Hints for local syms changed to
1862 Set_varstate function
1864 Revision 1.166 1999/11/17 17:05:02 pierre
1865 * Notes/hints changes
1867 Revision 1.165 1999/11/15 15:03:47 pierre
1868 * Pavel's changes for reloc section in executable
1869 + warning that -g needs -WN under win32