2
0

globstat.pas 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260
  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. oldc : char;
  36. oldpattern,
  37. oldorgpattern : string;
  38. old_block_type : tblock_type;
  39. { symtable }
  40. oldsymtablestack,
  41. oldmacrosymtablestack : TSymtablestack;
  42. oldaktprocsym : tprocsym;
  43. { cg }
  44. oldparse_only : boolean;
  45. { akt.. things }
  46. oldcurrent_filepos : tfileposinfo;
  47. old_current_module : tmodule;
  48. oldcurrent_procinfo : tprocinfo;
  49. old_settings : tsettings;
  50. old_switchesstatestack : tswitchesstatestack;
  51. old_switchesstatestackpos : Integer;
  52. old_verbosity : longint;
  53. { only saved/restored if "full" is true }
  54. old_asmdata : tasmdata;
  55. old_debuginfo : tdebuginfo;
  56. old_scanner : tscannerfile;
  57. old_parser_file : string;
  58. constructor create(savefull : boolean);
  59. destructor destroy; override;
  60. procedure clearscanner;
  61. class procedure remove_scanner_from_states(scanner : tscannerfile); static;
  62. procedure save(full : boolean);
  63. procedure restore(full : boolean);
  64. end;
  65. procedure save_global_state(state:tglobalstate;full:boolean);
  66. procedure restore_global_state(state:tglobalstate;full:boolean);
  67. implementation
  68. uses
  69. switches, verbose, pbase,comphook;
  70. var
  71. states : array of tglobalstate;
  72. statecount : integer = 0;
  73. class procedure tglobalstate.remove_scanner_from_states(scanner : tscannerfile);
  74. var
  75. i : integer;
  76. begin
  77. for I:=0 to statecount-1 do
  78. if (states[i].old_scanner=scanner) then
  79. states[i].clearscanner;
  80. end;
  81. procedure addstate(astate : tglobalstate);
  82. var
  83. l : integer;
  84. begin
  85. l:=length(states);
  86. if l=statecount then
  87. setlength(states,l+10);
  88. states[statecount]:=astate;
  89. inc(statecount);
  90. end;
  91. procedure removestate(astate : tglobalstate);
  92. var
  93. l : integer;
  94. begin
  95. l:=statecount-1;
  96. While (l>=0) and (states[l]<>astate) do
  97. dec(l);
  98. if l<0 then
  99. exit;
  100. if l<>statecount-1 then
  101. states[l]:=states[statecount-1];
  102. states[statecount-1]:=Nil;
  103. Dec(Statecount);
  104. end;
  105. procedure save_global_state(state:tglobalstate;full:boolean);
  106. begin
  107. state.save(full);
  108. end;
  109. procedure restore_global_state(state:tglobalstate;full:boolean);
  110. begin
  111. state.restore(full);
  112. end;
  113. procedure tglobalstate.save(full: boolean);
  114. begin
  115. old_current_module:=current_module;
  116. { save symtable state }
  117. oldsymtablestack:=symtablestack;
  118. oldmacrosymtablestack:=macrosymtablestack;
  119. oldcurrent_procinfo:=current_procinfo;
  120. { save scanner state }
  121. oldc:=c;
  122. oldpattern:=pattern;
  123. oldorgpattern:=orgpattern;
  124. oldtoken:=token;
  125. oldidtoken:=idtoken;
  126. old_block_type:=block_type;
  127. oldtokenpos:=current_tokenpos;
  128. {
  129. consuming the semicolon after a uses clause can add to the
  130. pending state if the first directives change warning state.
  131. So we must flush before context switch. See for example:
  132. ppcgen/cgppc.pas
  133. line 144 has a WARN 6018 OFF...
  134. }
  135. flushpendingswitchesstate;
  136. old_switchesstatestack:=switchesstatestack;
  137. old_switchesstatestackpos:=switchesstatestackpos;
  138. { save cg }
  139. oldparse_only:=parse_only;
  140. { save akt... state }
  141. { handle the postponed case first }
  142. oldcurrent_filepos:=current_filepos;
  143. old_settings:=current_settings;
  144. old_verbosity:=status.verbosity;
  145. if full then
  146. begin
  147. old_asmdata:=current_asmdata;
  148. old_debuginfo:=current_debuginfo;
  149. old_parser_file:=parser_current_file;
  150. old_scanner:=current_scanner;
  151. end;
  152. end;
  153. procedure tglobalstate.restore(full: boolean);
  154. begin
  155. { restore scanner }
  156. c:=oldc;
  157. pattern:=oldpattern;
  158. orgpattern:=oldorgpattern;
  159. token:=oldtoken;
  160. idtoken:=oldidtoken;
  161. current_tokenpos:=oldtokenpos;
  162. block_type:=old_block_type;
  163. switchesstatestack:=old_switchesstatestack;
  164. switchesstatestackpos:=old_switchesstatestackpos;
  165. { restore cg }
  166. parse_only:=oldparse_only;
  167. { restore symtable state }
  168. symtablestack:=oldsymtablestack;
  169. macrosymtablestack:=oldmacrosymtablestack;
  170. current_procinfo:=oldcurrent_procinfo;
  171. current_filepos:=oldcurrent_filepos;
  172. current_settings:=old_settings;
  173. status.verbosity:=old_verbosity;
  174. { restore message settings which were recorded prior to unit switch }
  175. RestoreLocalVerbosity(current_settings.pmessage);
  176. if full then
  177. begin
  178. set_current_module(old_current_module);
  179. // These can be different
  180. current_asmdata:=old_asmdata;
  181. current_debuginfo:=old_debuginfo;
  182. end;
  183. end;
  184. constructor tglobalstate.create(savefull: boolean);
  185. begin
  186. addstate(self);
  187. save(savefull);
  188. end;
  189. destructor tglobalstate.destroy;
  190. begin
  191. removestate(self);
  192. inherited destroy;
  193. end;
  194. procedure tglobalstate.clearscanner;
  195. begin
  196. old_scanner:=nil;
  197. oldidtoken:=NOTOKEN;
  198. oldtoken:=NOTOKEN;
  199. oldtokenpos:=Default(tfileposinfo);
  200. oldc:=#0;
  201. oldpattern:='';
  202. oldorgpattern:='';
  203. old_block_type:=bt_none;
  204. end;
  205. initialization
  206. onfreescanner:[email protected]_scanner_from_states;
  207. finalization
  208. onfreescanner:=Nil;
  209. end.