{ Copyright (c) 1998-2002 by Florian Klaempfl This unit does the parsing process This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. **************************************************************************** } unit parser; {$i fpcdefs.inc} interface {$ifdef PREPROCWRITE} procedure preprocess(const filename:string); {$endif PREPROCWRITE} procedure compile(const filename:string); procedure initparser; procedure doneparser; implementation uses {$IFNDEF USE_FAKE_SYSUTILS} sysutils, {$ELSE} fksysutl, {$ENDIF} cutils,cclasses, globtype,version,tokens,systems,globals,verbose,switches, symbase,symtable,symdef,symsym, finput,fmodule,fppu, aasmbase,aasmtai,aasmdata, cgbase, script,gendef, comphook, scanner,scandir, pbase,ptype,psystem,pmodules,psub,ncgrtti,htypechk, cresstr,cpuinfo,procinfo; procedure initparser; begin { we didn't parse a object or class declaration } { and no function header } testcurobject:=0; { Current compiled module/proc } set_current_module(nil); current_module:=nil; current_asmdata:=nil; current_procinfo:=nil; current_objectdef:=nil; loaded_units:=TLinkedList.Create; usedunits:=TLinkedList.Create; unloaded_units:=TLinkedList.Create; { global switches } current_settings.globalswitches:=init_settings.globalswitches; current_settings.sourcecodepage:=init_settings.sourcecodepage; { initialize scanner } InitScanner; InitScannerDirectives; { scanner } c:=#0; pattern:=''; orgpattern:=''; cstringpattern:=''; {$IFDEF DebugScanner} {$ELSE} current_scanner:=nil; {$ENDIF} switchesstatestackpos:=0; { register all nodes and tais } registernodes; registertais; { memory sizes } if stacksize=0 then stacksize:=target_info.stacksize; { RTTI writer } RTTIWriter:=TRTTIWriter.Create; { open assembler response } if cs_link_on_target in current_settings.globalswitches then GenerateAsmRes(outputexedir+ChangeFileExt(inputfilename,'_ppas')) else GenerateAsmRes(outputexedir+'ppas'); { open deffile } DefFile:=TDefFile.Create(outputexedir+ChangeFileExt(inputfilename,target_info.defext)); { list of generated .o files, so the linker can remove them } SmartLinkOFiles:=TCmdStrList.Create; { codegen } if paraprintnodetree<>0 then printnode_reset; { target specific stuff } case target_info.system of system_powerpc_amiga: include(supported_calling_conventions,pocall_syscall); system_powerpc_morphos: include(supported_calling_conventions,pocall_syscall); system_m68k_amiga: include(supported_calling_conventions,pocall_syscall); end; end; procedure doneparser; begin { Reset current compiling info, so destroy routines can't reference the data that might already be destroyed } set_current_module(nil); current_module:=nil; current_procinfo:=nil; current_asmdata:=nil; current_objectdef:=nil; { unload units } if assigned(loaded_units) then begin loaded_units.free; loaded_units:=nil; end; if assigned(usedunits) then begin usedunits.free; usedunits:=nil; end; if assigned(unloaded_units) then begin unloaded_units.free; unloaded_units:=nil; end; { if there was an error in the scanner, the scanner is still assinged } {$IFDEF DebugScanner} if assigned(current_module) then FreeAndNil(current_module.scanner); {$ELSE} if assigned(current_scanner) then begin current_scanner.free; current_scanner:=nil; end; {$ENDIF} { close scanner } DoneScanner; RTTIWriter.free; { close ppas,deffile } asmres.free; deffile.free; { free list of .o files } SmartLinkOFiles.Free; end; {$ifdef PREPROCWRITE} procedure preprocess(const filename:string); var i : longint; begin new(preprocfile,init('pre')); { initialize a module } set_current_module(new(pmodule,init(filename,false))); macrosymtablestack:= initialmacrosymtable; current_module.localmacrosymtable:= tmacrosymtable.create(false); current_module.localmacrosymtable.next:= initialmacrosymtable; macrosymtablestack:= current_module.localmacrosymtable; main_module:=current_module; { startup scanner, and save in current_module } current_scanner:=new(pscannerfile,Init(filename)); current_module.scanner:=current_scanner; { loop until EOF is found } repeat current_scanner^.readtoken(true); preprocfile^.AddSpace; case token of _ID : begin preprocfile^.Add(orgpattern); end; _REALNUMBER, _INTCONST : preprocfile^.Add(pattern); _CSTRING : begin i:=0; while (icurrent_module) then begin loaded_units.remove(hp); hp.free; end; hp:=hp2; end; { free also unneeded units we didn't free before } unloaded_units.Clear; end; dec(compile_level); set_current_module(olddata^.old_current_module); dispose(olddata); end; end; end.