globstat.pas 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242
  1. {
  2. Copyright (c) 2012 by the FPC development team
  3. Contains functionality to save/restore the global compiler state when
  4. switching between the compilation of different units.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit globstat;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. globtype,tokens,globals,
  23. aasmdata,
  24. dbgbase,
  25. symbase,symsym,
  26. fmodule,
  27. scanner,scandir,
  28. procinfo;
  29. type
  30. tglobalstate = class
  31. { scanner }
  32. oldidtoken,
  33. oldtoken : ttoken;
  34. oldtokenpos : tfileposinfo;
  35. old_block_type : tblock_type;
  36. { symtable }
  37. oldsymtablestack,
  38. oldmacrosymtablestack : TSymtablestack;
  39. oldaktprocsym : tprocsym;
  40. { cg }
  41. oldparse_only : boolean;
  42. { akt.. things }
  43. oldcurrent_filepos : tfileposinfo;
  44. old_current_module : tmodule;
  45. oldcurrent_procinfo : tprocinfo;
  46. old_settings : tsettings;
  47. old_switchesstatestack : tswitchesstatestack;
  48. old_switchesstatestackpos : Integer;
  49. old_verbosity : longint;
  50. { only saved/restored if "full" is true }
  51. old_asmdata : tasmdata;
  52. old_debuginfo : tdebuginfo;
  53. old_scanner : tscannerfile;
  54. old_parser_file : string;
  55. constructor create;
  56. destructor destroy; override;
  57. procedure clearscanner;
  58. class procedure remove_scanner_from_states(scanner : tscannerfile); static;
  59. procedure save;
  60. procedure restore;
  61. end;
  62. procedure save_global_state(state:tglobalstate);
  63. procedure restore_global_state(state:tglobalstate);
  64. implementation
  65. uses
  66. switches, verbose, pbase,comphook;
  67. var
  68. states : array of tglobalstate;
  69. statecount : integer = 0;
  70. class procedure tglobalstate.remove_scanner_from_states(scanner : tscannerfile);
  71. var
  72. i : integer;
  73. begin
  74. for I:=0 to statecount-1 do
  75. if (states[i].old_scanner=scanner) then
  76. states[i].clearscanner;
  77. end;
  78. procedure addstate(astate : tglobalstate);
  79. var
  80. l : integer;
  81. begin
  82. l:=length(states);
  83. if l=statecount then
  84. setlength(states,l+10);
  85. states[statecount]:=astate;
  86. inc(statecount);
  87. end;
  88. procedure removestate(astate : tglobalstate);
  89. var
  90. l : integer;
  91. begin
  92. l:=statecount-1;
  93. While (l>=0) and (states[l]<>astate) do
  94. dec(l);
  95. if l<0 then
  96. exit;
  97. if l<>statecount-1 then
  98. states[l]:=states[statecount-1];
  99. states[statecount-1]:=Nil;
  100. Dec(Statecount);
  101. end;
  102. procedure save_global_state(state:tglobalstate);
  103. begin
  104. state.save;
  105. end;
  106. procedure restore_global_state(state:tglobalstate);
  107. begin
  108. state.restore;
  109. end;
  110. procedure tglobalstate.save;
  111. begin
  112. old_current_module:=current_module;
  113. { save symtable state }
  114. oldsymtablestack:=symtablestack;
  115. oldmacrosymtablestack:=macrosymtablestack;
  116. oldcurrent_procinfo:=current_procinfo;
  117. { save scanner state }
  118. oldtoken:=token;
  119. oldidtoken:=idtoken;
  120. old_block_type:=block_type;
  121. oldtokenpos:=current_tokenpos;
  122. {
  123. consuming the semicolon after a uses clause can add to the
  124. pending state if the first directives change warning state.
  125. So we must flush before context switch. See for example:
  126. ppcgen/cgppc.pas
  127. line 144 has a WARN 6018 OFF...
  128. }
  129. flushpendingswitchesstate;
  130. old_switchesstatestack:=switchesstatestack;
  131. old_switchesstatestackpos:=switchesstatestackpos;
  132. { save cg }
  133. oldparse_only:=parse_only;
  134. { save akt... state }
  135. { handle the postponed case first }
  136. oldcurrent_filepos:=current_filepos;
  137. old_settings:=current_settings;
  138. old_verbosity:=status.verbosity;
  139. old_asmdata:=current_asmdata;
  140. old_debuginfo:=current_debuginfo;
  141. old_parser_file:=parser_current_file;
  142. old_scanner:=current_scanner;
  143. end;
  144. procedure tglobalstate.restore;
  145. begin
  146. { restore scanner }
  147. token:=oldtoken;
  148. idtoken:=oldidtoken;
  149. current_tokenpos:=oldtokenpos;
  150. block_type:=old_block_type;
  151. switchesstatestack:=old_switchesstatestack;
  152. switchesstatestackpos:=old_switchesstatestackpos;
  153. { restore cg }
  154. parse_only:=oldparse_only;
  155. { restore symtable state }
  156. symtablestack:=oldsymtablestack;
  157. macrosymtablestack:=oldmacrosymtablestack;
  158. current_procinfo:=oldcurrent_procinfo;
  159. current_filepos:=oldcurrent_filepos;
  160. current_settings:=old_settings;
  161. status.verbosity:=old_verbosity;
  162. { restore message settings which were recorded prior to unit switch }
  163. RestoreLocalVerbosity(current_settings.pmessage);
  164. set_current_module(old_current_module);
  165. // These can be different
  166. current_asmdata:=old_asmdata;
  167. current_debuginfo:=old_debuginfo;
  168. end;
  169. constructor tglobalstate.create;
  170. begin
  171. addstate(self);
  172. save;
  173. end;
  174. destructor tglobalstate.destroy;
  175. begin
  176. removestate(self);
  177. inherited destroy;
  178. end;
  179. procedure tglobalstate.clearscanner;
  180. begin
  181. old_scanner:=nil;
  182. oldidtoken:=NOTOKEN;
  183. oldtoken:=NOTOKEN;
  184. oldtokenpos:=Default(tfileposinfo);
  185. old_block_type:=bt_none;
  186. end;
  187. initialization
  188. onfreescanner:[email protected]_scanner_from_states;
  189. finalization
  190. onfreescanner:=Nil;
  191. end.