Obsd.linKernel.txt 74 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583
  1. MODULE Kernel;
  2. (* THIS IS TEXT COPY OF Obsd.linKernel.odc *)
  3. (* DO NOT EDIT *)
  4. (* TODO: Stack overflow is not cought *)
  5. IMPORT SYSTEM, LinDl, LinLibc;
  6. CONST
  7. dllMem = TRUE; (* should be a variable, but for easier memory managment it is always true. *)
  8. strictStackSweep = TRUE;
  9. nameLen* = 256;
  10. littleEndian* = TRUE;
  11. timeResolution* = 1000; (* ticks per second *)
  12. processor* = 10; (* i386 *)
  13. objType* = "ocf"; (* file types *)
  14. symType* = "osf";
  15. docType* = "odc";
  16. (* loader constants *)
  17. done* = 0;
  18. fileNotFound* = 1;
  19. syntaxError* = 2;
  20. objNotFound* = 3;
  21. illegalFPrint* = 4;
  22. cyclicImport* = 5;
  23. noMem* = 6;
  24. commNotFound* = 7;
  25. commSyntaxError* = 8;
  26. moduleNotFound* = 9;
  27. any = 1000000;
  28. CX = 1;
  29. SP = 4; (* register number of stack pointer *)
  30. FP = 5; (* register number of frame pointer *)
  31. ML = 3; (* register which holds the module list at program start *)
  32. N = 128 DIV 16; (* free lists *)
  33. (* kernel flags in module desc *)
  34. init = 16; dyn = 17; dll = 24; iptrs = 30;
  35. (* meta interface consts *)
  36. mConst = 1; mTyp = 2; mVar = 3; mProc = 4; mField = 5;
  37. debug = FALSE;
  38. trapReturn = 1; (* Return value for sigsetjmp given from siglongjmp *)
  39. (* constants for the message boxes *)
  40. mbClose* = -1; mbOk* = 0; mbCancel* =1; mbRetry* = 2; mbIgnore* = 3; mbYes* = 4; mbNo* = 5;
  41. TYPE
  42. Name* = ARRAY nameLen OF SHORTCHAR;
  43. Command* = PROCEDURE;
  44. Module* = POINTER TO RECORD [untagged]
  45. next-: Module;
  46. opts-: SET; (* 0..15: compiler opts, 16..31: kernel flags *)
  47. refcnt-: INTEGER; (* <0: module invalidated *)
  48. compTime-, loadTime-: ARRAY 6 OF SHORTINT;
  49. ext-: INTEGER; (* currently not used *)
  50. term-: Command; (* terminator *)
  51. nofimps-, nofptrs-: INTEGER;
  52. csize-, dsize-, rsize-: INTEGER;
  53. code-, data-, refs-: INTEGER;
  54. procBase-, varBase-: INTEGER; (* meta base addresses *)
  55. names-: POINTER TO ARRAY [untagged] OF SHORTCHAR; (* names[0] = 0X *)
  56. ptrs-: POINTER TO ARRAY [untagged] OF INTEGER;
  57. imports-: POINTER TO ARRAY [untagged] OF Module;
  58. export-: Directory; (* exported objects (name sorted) *)
  59. name-: Name
  60. END;
  61. Type* = POINTER TO RECORD [untagged]
  62. (* record: ptr to method n at offset - 4 * (n+1) *)
  63. size-: INTEGER; (* record: size, array: #elem, dyn array: 0, proc: sigfp *)
  64. mod-: Module;
  65. id-: INTEGER; (* name idx * 256 + lev * 16 + attr * 4 + form *)
  66. base-: ARRAY 16 OF Type;
  67. fields-: Directory; (* new fields (declaration order) *)
  68. ptroffs-: ARRAY any OF INTEGER (* array of any length *)
  69. END;
  70. Object* = POINTER TO ObjDesc;
  71. ObjDesc* = RECORD [untagged]
  72. fprint-: INTEGER;
  73. offs-: INTEGER; (* pvfprint for record types *)
  74. id-: INTEGER; (* name idx * 256 + vis * 16 + mode *)
  75. struct-: Type (* id of basic type or pointer to typedesc *)
  76. END;
  77. Directory* = POINTER TO RECORD [untagged]
  78. num-: INTEGER; (* number of entries *)
  79. obj-: ARRAY any OF ObjDesc (* array of any length *)
  80. END;
  81. Signature* = POINTER TO RECORD [untagged]
  82. retStruct-: Type; (* id of basic type or pointer to typedesc or 0 *)
  83. num-: INTEGER; (* number of parameters *)
  84. par-: ARRAY any OF RECORD [untagged] (* parameters *)
  85. id-: INTEGER; (* name idx * 256 + kind *)
  86. struct-: Type (* id of basic type or pointer to typedesc *)
  87. END
  88. END;
  89. Handler* = PROCEDURE;
  90. Reducer* = POINTER TO ABSTRACT RECORD
  91. next: Reducer
  92. END;
  93. Identifier* = ABSTRACT RECORD
  94. typ*: INTEGER;
  95. obj-: ANYPTR
  96. END;
  97. TrapCleaner* = POINTER TO ABSTRACT RECORD
  98. next: TrapCleaner
  99. END;
  100. TryHandler* = PROCEDURE (a, b, c: INTEGER);
  101. (* meta extension suport *)
  102. ItemExt* = POINTER TO ABSTRACT RECORD END;
  103. ItemAttr* = RECORD
  104. obj*, vis*, typ*, adr*: INTEGER;
  105. mod*: Module;
  106. desc*: Type;
  107. ptr*: SYSTEM.PTR;
  108. ext*: ItemExt
  109. END;
  110. Hook* = POINTER TO ABSTRACT RECORD END;
  111. LoaderHook* = POINTER TO ABSTRACT RECORD (Hook)
  112. res*: INTEGER;
  113. importing*, imported*, object*: ARRAY 256 OF CHAR
  114. END;
  115. GuiHook* = POINTER TO ABSTRACT RECORD (Hook) END; (* Implemented by HostGnome *)
  116. Block = POINTER TO RECORD [untagged]
  117. tag: Type;
  118. last: INTEGER; (* arrays: last element *)
  119. actual: INTEGER; (* arrays: used during mark phase *)
  120. first: INTEGER (* arrays: first element *)
  121. END;
  122. FreeBlock = POINTER TO FreeDesc;
  123. FreeDesc = RECORD [untagged]
  124. tag: Type; (* f.tag = ADR(f.size) *)
  125. size: INTEGER;
  126. next: FreeBlock
  127. END;
  128. Cluster = POINTER TO RECORD [untagged]
  129. size: INTEGER; (* total size *)
  130. next: Cluster;
  131. max: INTEGER
  132. (* start of first block *)
  133. END;
  134. FList = POINTER TO RECORD
  135. next: FList;
  136. blk: Block;
  137. iptr, aiptr: BOOLEAN
  138. END;
  139. CList = POINTER TO RECORD
  140. next: CList;
  141. do: Command;
  142. trapped: BOOLEAN
  143. END;
  144. PtrType = RECORD v: SYSTEM.PTR END; (* used for array of pointer *)
  145. Char8Type = RECORD v: SHORTCHAR END;
  146. Char16Type = RECORD v: CHAR END;
  147. Int8Type = RECORD v: BYTE END;
  148. Int16Type = RECORD v: SHORTINT END;
  149. Int32Type = RECORD v: INTEGER END;
  150. Int64Type = RECORD v: LONGINT END;
  151. BoolType = RECORD v: BOOLEAN END;
  152. SetType = RECORD v: SET END;
  153. Real32Type = RECORD v: SHORTREAL END;
  154. Real64Type = RECORD v: REAL END;
  155. ProcType = RECORD v: PROCEDURE END;
  156. UPtrType = RECORD v: INTEGER END;
  157. StrPtr = POINTER TO ARRAY [untagged] OF SHORTCHAR;
  158. (*
  159. IntPtrType = RECORD p: COM.IUnknown END; (* used for array of interface pointer *)
  160. IntPtr = POINTER TO RECORD [untagged] p: COM.IUnknown END;
  161. ExcpFramePtr = POINTER TO RECORD (KERNEL32.ExcpFrm)
  162. par: INTEGER
  163. END;
  164. Interface = POINTER TO RECORD (* COMPILER DEPENDENT *)
  165. vtab: INTEGER;
  166. ref: INTEGER; (* must correspond to Block.actual *)
  167. unk: COM.IUnknown
  168. END;
  169. *)
  170. (* Linux specific boot loader info. Record must be identical to struct in the loader. *)
  171. BootInfo* = POINTER TO RECORD [untagged]
  172. modList: Module;
  173. argc-: INTEGER;
  174. argv-: LinLibc.StrArray
  175. END;
  176. VAR
  177. baseStack: INTEGER; (* modList, root, and baseStack must be together for remote debugging *)
  178. root: Cluster; (* cluster list *)
  179. modList-: Module; (* root of module list *)
  180. trapCount-: INTEGER;
  181. err-, pc-, sp-, fp-, stack-, val-: INTEGER;
  182. comSig-: INTEGER; (* command signature *)
  183. free: ARRAY N OF FreeBlock; (* free list *)
  184. sentinelBlock: FreeDesc;
  185. sentinel: FreeBlock;
  186. candidates: ARRAY 1024 OF INTEGER;
  187. nofcand: INTEGER;
  188. allocated: INTEGER; (* bytes allocated on BlackBox heap *)
  189. total: INTEGER; (* current total size of BlackBox heap *)
  190. used: INTEGER; (* bytes allocated on system heap *)
  191. finalizers: FList;
  192. hotFinalizers: FList;
  193. cleaners: CList;
  194. reducers: Reducer;
  195. trapStack: TrapCleaner;
  196. actual: Module; (* valid during module initialization *)
  197. res: INTEGER; (* auxiliary global variables used for trap handling *)
  198. old: SET;
  199. trapViewer, trapChecker: Handler;
  200. trapped, guarded, secondTrap: BOOLEAN;
  201. interrupted: BOOLEAN;
  202. static, inDll, terminating: BOOLEAN;
  203. retAd: INTEGER;
  204. restart: Command;
  205. (*
  206. heap: LinLibc.PtrVoid; (*heap: KERNEL32.Handle;*)
  207. excpPtr: KERNEL32.ExcpFrmPtr;
  208. mainThread: KERNEL32.Handle;
  209. *)
  210. told, shift: INTEGER; (* used in Time() *)
  211. loader: LoaderHook;
  212. loadres: INTEGER;
  213. wouldFinalize: BOOLEAN;
  214. watcher*: PROCEDURE (event: INTEGER); (* for debug *)
  215. loopContext: LinLibc.sigjmp_buf; (* trap return context, if no Kernel.Try has been used. *)
  216. currentTryContext: POINTER TO LinLibc.sigjmp_buf; (* trap return context, if Kernel.Try has been used. *)
  217. guiHook: GuiHook;
  218. cmdLine-: ARRAY 1024 OF CHAR;
  219. (* !!! This variable has to be the last variable in the list. !!! *)
  220. bootInfo-: BootInfo;
  221. (* code procedures for exception handling *)
  222. PROCEDURE [1] PushFP 055H;
  223. PROCEDURE [1] PopFP 05DH;
  224. PROCEDURE [1] PushBX 053H;
  225. PROCEDURE [1] PopBX 05BH;
  226. PROCEDURE [1] PushSI 056H;
  227. PROCEDURE [1] PopSI 05EH;
  228. PROCEDURE [1] PushDI 057H;
  229. PROCEDURE [1] PopDI 05FH;
  230. PROCEDURE [1] LdSP8 08DH, 065H, 0F8H;
  231. PROCEDURE [1] Return0 (ret: INTEGER) 0C3H;
  232. PROCEDURE [1] ReturnCX (ret: INTEGER) 05AH, 001H, 0CCH, 0FFH, 0E2H; (* POP DX; ADD SP,CX; JP DX *)
  233. PROCEDURE [1] FPageWord (offs: INTEGER): INTEGER 64H, 8BH, 0H; (* MOV EAX,FS:[EAX] *)
  234. (* code procedures for fpu *)
  235. PROCEDURE [1] FINIT 0DBH, 0E3H;
  236. PROCEDURE [1] FLDCW 0D9H, 06DH, 0FCH; (* -4, FP *)
  237. PROCEDURE [1] FSTCW 0D9H, 07DH, 0FCH; (* -4, FP *)
  238. (* code procedure for memory erase *)
  239. PROCEDURE [code] Erase (adr, words: INTEGER)
  240. 089H, 0C7H, (* MOV EDI, EAX *)
  241. 031H, 0C0H, (* XOR EAX, EAX *)
  242. 059H, (* POP ECX *)
  243. 0F2H, 0ABH; (* REP STOS *)
  244. (* code procedure for stack allocate *)
  245. PROCEDURE [code] ALLOC (* argument in CX *)
  246. (*
  247. PUSH EAX
  248. ADD ECX,-5
  249. JNS L0
  250. XOR ECX,ECX
  251. L0: AND ECX,-4 (n-8+3)/4*4
  252. MOV EAX,ECX
  253. AND EAX,4095
  254. SUB ESP,EAX
  255. MOV EAX,ECX
  256. SHR EAX,12
  257. JEQ L2
  258. L1: PUSH 0
  259. SUB ESP,4092
  260. DEC EAX
  261. JNE L1
  262. L2: ADD ECX,8
  263. MOV EAX,[ESP,ECX,-4]
  264. PUSH EAX
  265. MOV EAX,[ESP,ECX,-4]
  266. SHR ECX,2
  267. RET
  268. *);
  269. (* code procedures for COM support *)
  270. PROCEDURE [code] ADDREF
  271. (*
  272. MOV ECX,[ESP,4]
  273. INC [ECX,4]
  274. MOV EAX,[ECX,8]
  275. OR EAX,EAX
  276. JE L1
  277. PUSH EAX
  278. MOV EAX,[EAX]
  279. CALL [EAX,4]
  280. MOV ECX,[ESP,4]
  281. L1: MOV EAX,[ECX,4]
  282. RET 4
  283. *)
  284. 08BH, 04CH, 024H, 004H,
  285. 0FFH, 041H, 004H,
  286. 08BH, 041H, 008H,
  287. 009H, 0C0H,
  288. 074H, 00AH,
  289. 050H,
  290. 08BH, 000H,
  291. 0FFH, 050H, 004H,
  292. 08BH, 04CH, 024H, 004H,
  293. 08BH, 041H, 004H,
  294. 0C2H, 004H, 000H;
  295. PROCEDURE [code] RELEASE
  296. (*
  297. MOV ECX,[ESP,4]
  298. MOV EAX,[ECX,8]
  299. OR EAX,EAX
  300. JE L1
  301. PUSH EAX
  302. MOV EAX,[EAX]
  303. CALL [EAX,8]
  304. MOV ECX,[ESP,4]
  305. L1: DEC [ECX,4]
  306. MOV EAX,[ECX,4]
  307. RET 4
  308. *)
  309. 08BH, 04CH, 024H, 004H,
  310. 08BH, 041H, 008H,
  311. 009H, 0C0H,
  312. 074H, 00AH,
  313. 050H,
  314. 08BH, 000H,
  315. 0FFH, 050H, 008H,
  316. 08BH, 04CH, 024H, 004H,
  317. 0FFH, 049H, 004H,
  318. 08BH, 041H, 004H,
  319. 0C2H, 004H, 000H;
  320. PROCEDURE [code] CALLREL
  321. (*
  322. MOV EAX,[ESP,4]
  323. CMP [EAX,4],1
  324. JNE L1
  325. PUSH ESI
  326. PUSH EDI
  327. PUSH EAX
  328. MOV EAX,[EAX,-4]
  329. CALL [EAX,-8]
  330. POP EDI
  331. POP ESI
  332. L1:
  333. *)
  334. 08BH, 044H, 024H, 004H,
  335. 083H, 078H, 004H, 001H,
  336. 075H, 00BH,
  337. 056H,
  338. 057H,
  339. 050H,
  340. 08BH, 040H, 0FCH,
  341. 0FFH, 050H, 0F8H,
  342. 05FH,
  343. 05EH;
  344. PROCEDURE (VAR id: Identifier) Identified* (): BOOLEAN, NEW, ABSTRACT;
  345. PROCEDURE (r: Reducer) Reduce* (full: BOOLEAN), NEW, ABSTRACT;
  346. PROCEDURE (c: TrapCleaner) Cleanup*, NEW, EMPTY;
  347. (* meta extension suport *)
  348. PROCEDURE (e: ItemExt) Lookup* (name: ARRAY OF CHAR; VAR i: ANYREC), NEW, ABSTRACT;
  349. PROCEDURE (e: ItemExt) Index* (index: INTEGER; VAR elem: ANYREC), NEW, ABSTRACT;
  350. PROCEDURE (e: ItemExt) Deref* (VAR ref: ANYREC), NEW, ABSTRACT;
  351. PROCEDURE (e: ItemExt) Valid* (): BOOLEAN, NEW, ABSTRACT;
  352. PROCEDURE (e: ItemExt) Size* (): INTEGER, NEW, ABSTRACT;
  353. PROCEDURE (e: ItemExt) BaseTyp* (): INTEGER, NEW, ABSTRACT;
  354. PROCEDURE (e: ItemExt) Len* (): INTEGER, NEW, ABSTRACT;
  355. PROCEDURE (e: ItemExt) Call* (OUT ok: BOOLEAN), NEW, ABSTRACT;
  356. PROCEDURE (e: ItemExt) BoolVal* (): BOOLEAN, NEW, ABSTRACT;
  357. PROCEDURE (e: ItemExt) PutBoolVal* (x: BOOLEAN), NEW, ABSTRACT;
  358. PROCEDURE (e: ItemExt) CharVal* (): CHAR, NEW, ABSTRACT;
  359. PROCEDURE (e: ItemExt) PutCharVal* (x: CHAR), NEW, ABSTRACT;
  360. PROCEDURE (e: ItemExt) IntVal* (): INTEGER, NEW, ABSTRACT;
  361. PROCEDURE (e: ItemExt) PutIntVal* (x: INTEGER), NEW, ABSTRACT;
  362. PROCEDURE (e: ItemExt) LongVal* (): LONGINT, NEW, ABSTRACT;
  363. PROCEDURE (e: ItemExt) PutLongVal* (x: LONGINT), NEW, ABSTRACT;
  364. PROCEDURE (e: ItemExt) RealVal* (): REAL, NEW, ABSTRACT;
  365. PROCEDURE (e: ItemExt) PutRealVal* (x: REAL), NEW, ABSTRACT;
  366. PROCEDURE (e: ItemExt) SetVal* (): SET, NEW, ABSTRACT;
  367. PROCEDURE (e: ItemExt) PutSetVal* (x: SET), NEW, ABSTRACT;
  368. PROCEDURE (e: ItemExt) PtrVal* (): ANYPTR, NEW, ABSTRACT;
  369. PROCEDURE (e: ItemExt) PutPtrVal* (x: ANYPTR), NEW, ABSTRACT;
  370. PROCEDURE (e: ItemExt) GetSStringVal* (
  371. OUT x: ARRAY OF SHORTCHAR; OUT ok: BOOLEAN), NEW, ABSTRACT;
  372. PROCEDURE (e: ItemExt) PutSStringVal* (
  373. IN x: ARRAY OF SHORTCHAR; OUT ok: BOOLEAN), NEW, ABSTRACT;
  374. PROCEDURE (e: ItemExt) GetStringVal* (OUT x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT;
  375. PROCEDURE (e: ItemExt) PutStringVal* (IN x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT;
  376. (* -------------------- miscellaneous tools -------------------- *)
  377. PROCEDURE Msg (IN str: ARRAY OF CHAR);
  378. VAR ss: ARRAY 1024 OF SHORTCHAR; res, l: INTEGER;
  379. BEGIN
  380. ss := SHORT(str);
  381. l := LEN(ss$);
  382. ss[l] := 0AX; ss[l + 1] := 0X;
  383. res := LinLibc.printf(ss);
  384. END Msg;
  385. PROCEDURE Int (x: LONGINT);
  386. VAR j, k: INTEGER; ch: CHAR; a, s: ARRAY 32 OF CHAR;
  387. BEGIN
  388. IF x # MIN(LONGINT) THEN
  389. IF x < 0 THEN s[0] := "-"; k := 1; x := -x ELSE k := 0 END;
  390. j := 0; REPEAT a[j] := CHR(x MOD 10 + ORD("0")); x := x DIV 10; INC(j) UNTIL x = 0
  391. ELSE
  392. a := "8085774586302733229"; s[0] := "-"; k := 1;
  393. j := 0; WHILE a[j] # 0X DO INC(j) END
  394. END;
  395. ASSERT(k + j < LEN(s), 20);
  396. REPEAT DEC(j); ch := a[j]; s[k] := ch; INC(k) UNTIL j = 0;
  397. s[k] := 0X;
  398. Msg(s);
  399. END Int;
  400. PROCEDURE (h: GuiHook) MessageBox* (
  401. title, msg: ARRAY OF CHAR; buttons: SET): INTEGER, NEW, ABSTRACT;
  402. PROCEDURE (h: GuiHook) Beep*, NEW, ABSTRACT;
  403. (* Is extended by HostGnome to show dialogs. If no dialog is present or
  404. if the dialog is not closed by using one button, then "mbClose" is returned *)
  405. PROCEDURE MessageBox* (title, msg: ARRAY OF CHAR; buttons: SET): INTEGER;
  406. VAR res: INTEGER;
  407. BEGIN
  408. IF guiHook # NIL THEN
  409. res := guiHook.MessageBox(title, msg, buttons)
  410. ELSE
  411. Msg(" ");
  412. Msg("****");
  413. Msg("* " + title);
  414. Msg("* " + msg);
  415. Msg("****");
  416. res := mbClose;
  417. END;
  418. RETURN res
  419. END MessageBox;
  420. PROCEDURE SetGuiHook* (hook: GuiHook);
  421. BEGIN
  422. guiHook := hook
  423. END SetGuiHook;
  424. PROCEDURE SplitName* (name: ARRAY OF CHAR; VAR head, tail: ARRAY OF CHAR);
  425. (* portable *)
  426. VAR i, j: INTEGER; ch, lch: CHAR;
  427. BEGIN
  428. i := 0; ch := name[0];
  429. REPEAT
  430. head[i] := ch; lch := ch; INC(i); ch := name[i]
  431. UNTIL (ch = 0X)
  432. OR ((ch >= "A") & (ch <= "Z") OR (ch >= "À") & (ch # "×") & (ch <= "Þ"))
  433. & ((lch < "A") OR (lch > "Z") & (lch < "À") OR (lch = "×") OR (lch > "Þ"));
  434. head[i] := 0X; j := 0;
  435. WHILE ch # 0X DO tail[j] := ch; INC(i); INC(j); ch := name[i] END;
  436. tail[j] := 0X;
  437. IF tail = "" THEN tail := head$; head := "" END
  438. END SplitName;
  439. PROCEDURE MakeFileName* (VAR name: ARRAY OF CHAR; type: ARRAY OF CHAR);
  440. VAR i, j: INTEGER; ext: ARRAY 8 OF CHAR; ch: CHAR;
  441. BEGIN
  442. i := 0;
  443. WHILE (name[i] # 0X) & (name[i] # ".") DO INC(i) END;
  444. IF name[i] = "." THEN
  445. IF name[i + 1] = 0X THEN name[i] := 0X END
  446. ELSIF i < LEN(name) - 4 THEN
  447. IF type = "" THEN ext := docType ELSE ext := type$ END;
  448. name[i] := "."; INC(i); j := 0; ch := ext[0];
  449. WHILE ch # 0X DO
  450. IF (ch >= "A") & (ch <= "Z") THEN
  451. ch := CHR(ORD(ch) + ORD("a") - ORD("A"))
  452. END;
  453. name[i] := ch; INC(i); INC(j); ch := ext[j]
  454. END;
  455. name[i] := 0X
  456. END
  457. END MakeFileName;
  458. PROCEDURE Time* (): LONGINT;
  459. VAR t: INTEGER;
  460. BEGIN
  461. (* A. V. Shiryaev *)
  462. (* processor time to milliseconds *)
  463. (* incorrect (integers overflows on multiplication) *)
  464. (* t := (1000 * LinLibc.clock()) DIV LinLibc.CLOCKS_PER_SEC; *)
  465. (* ok *)
  466. ASSERT(LinLibc.CLOCKS_PER_SEC = 100);
  467. t := 10 * LinLibc.clock();
  468. IF t < told THEN INC(shift) END;
  469. told := t;
  470. RETURN shift * 100000000L + t
  471. END Time;
  472. PROCEDURE Beep* ();
  473. VAR ss: ARRAY 2 OF SHORTCHAR;
  474. BEGIN
  475. IF guiHook # NIL THEN
  476. guiHook.Beep
  477. ELSE
  478. ss[0] := 007X; ss[1] := 0X;
  479. res := LinLibc.printf(ss); res := LinLibc.fflush(LinLibc.NULL)
  480. END
  481. END Beep;
  482. PROCEDURE SearchProcVar* (var: INTEGER; VAR m: Module; VAR adr: INTEGER);
  483. BEGIN
  484. adr := var; m := NIL;
  485. IF var # 0 THEN
  486. m := modList;
  487. WHILE (m # NIL) & ((var < m.code) OR (var >= m.code + m.csize)) DO m := m.next END;
  488. IF m # NIL THEN DEC(adr, m.code) END
  489. END
  490. END SearchProcVar;
  491. (* -------------------- system memory management --------------------- *)
  492. PROCEDURE GrowHeapMem (size: INTEGER; VAR c: Cluster);
  493. (* grow to at least size bytes, typically at least 256 kbytes are allocated *)
  494. CONST N = 262144;
  495. VAR adr, s: INTEGER;
  496. BEGIN
  497. ASSERT(size >= c.size, 100);
  498. IF size <= c.max THEN
  499. s := (size + (N - 1)) DIV N * N;
  500. (*
  501. adr := KERNEL32.VirtualAlloc(SYSTEM.VAL(INTEGER, c), s, {12}, {6}); (* commit; exec, read, write *)
  502. *)
  503. adr := LinLibc.calloc(1, s);
  504. IF adr # 0 THEN
  505. INC(used, s - c.size); INC(total, s - c.size); c.size := s
  506. END
  507. END
  508. (* post: (c.size unchanged) OR (c.size >= size) *)
  509. END GrowHeapMem;
  510. PROCEDURE AllocHeapMem (size: INTEGER; VAR c: Cluster);
  511. (* allocate at least size bytes, typically at least 256 kbytes are allocated *)
  512. CONST M = 1536 * 100000H; (* 1.5 GByte *)
  513. CONST N = 65536; (* cluster size for dll *)
  514. VAR adr, s: INTEGER;
  515. BEGIN
  516. IF dllMem THEN
  517. INC(size, 16);
  518. ASSERT(size > 0, 100); adr := 0;
  519. (*
  520. IF size < N THEN adr := KERNEL32.HeapAlloc(heap, {0}, N) END;
  521. IF adr = 0 THEN adr := KERNEL32.HeapAlloc(heap, {0}, size) END;
  522. *)
  523. IF size < N THEN adr := LinLibc.calloc(1, N) END;
  524. IF adr = 0 THEN adr := LinLibc.calloc(1, size)
  525. ELSE size := N
  526. END;
  527. IF adr = 0 THEN c := NIL
  528. ELSE
  529. c := SYSTEM.VAL(Cluster, ((adr + 15) DIV 16) * 16); c.max := adr;
  530. (*
  531. c.size := KERNEL32.HeapSize(heap, {0}, adr) - (SYSTEM.VAL(INTEGER, c) - adr);
  532. *)
  533. c.size := size - (SYSTEM.VAL(INTEGER, c) - adr);
  534. INC(used, c.size); INC(total, c.size)
  535. END;
  536. ELSE
  537. adr := 0; s := M;
  538. REPEAT
  539. (*
  540. adr := KERNEL32.VirtualAlloc(01000000H, s, {13}, {6}); (* reserve; exec, read, write *)
  541. *)
  542. IF adr = 0 THEN
  543. (*
  544. adr := KERNEL32.VirtualAlloc(0, s, {13}, {6}) (* reserve; exec, read, write *)
  545. *)
  546. END;
  547. s := s DIV 2
  548. UNTIL adr # 0;
  549. IF adr = 0 THEN c := NIL
  550. ELSE
  551. (*
  552. adr := KERNEL32.VirtualAlloc(adr, 1024, {12}, {6}); (* commit; exec, read, write *)
  553. *)
  554. c := SYSTEM.VAL(Cluster, adr);
  555. c.max := s * 2; c.size := 0; c.next := NIL;
  556. GrowHeapMem(size, c);
  557. IF c.size < size THEN c := NIL END
  558. END
  559. END
  560. (* post: (c = NIL) OR (c MOD 16 = 0) & (c.size >= size) *)
  561. END AllocHeapMem;
  562. PROCEDURE FreeHeapMem (c: Cluster);
  563. VAR res: INTEGER;
  564. BEGIN
  565. DEC(used, c.size); DEC(total, c.size);
  566. IF dllMem THEN
  567. (*
  568. res := KERNEL32.HeapFree(heap, {0}, c.max)
  569. *)
  570. LinLibc.free(c.max)
  571. END
  572. END FreeHeapMem;
  573. PROCEDURE HeapFull (size: INTEGER): BOOLEAN;
  574. (*
  575. VAR ms: KERNEL32.MemStatus;
  576. *)
  577. BEGIN
  578. RETURN used + size > 4000000 (* TODO: Do this right!!! Well, maybe not, since it isn't used for dllMem *)
  579. (*
  580. ms.size := SIZE(KERNEL32.MemStatus);
  581. ms.memLoad := -1;
  582. KERNEL32.GlobalMemoryStatus(ms);
  583. IF ms.memLoad >= 0 THEN
  584. RETURN used + size > ms.totPhys
  585. ELSE (* old win32s *)
  586. RETURN used + size > 4000000
  587. END
  588. *)
  589. END HeapFull;
  590. PROCEDURE AllocModMem* (descSize, modSize: INTEGER; VAR descAdr, modAdr: INTEGER);
  591. VAR res: INTEGER;
  592. BEGIN
  593. (*
  594. descAdr := KERNEL32.VirtualAlloc(0, descSize, {12, 13}, {6}); (* reserve & commit; exec, read, write *)
  595. IF descAdr # 0 THEN
  596. modAdr := KERNEL32.VirtualAlloc(0, modSize, {12, 13}, {6}); (* reserve & commit; exec, read, write *)
  597. IF modAdr # 0 THEN INC(used, descSize + modSize)
  598. ELSE res := KERNEL32.VirtualFree(descAdr, 0, {15}); descAdr := 0
  599. END
  600. ELSE modAdr := 0
  601. END
  602. *)
  603. descAdr := LinLibc.calloc(1, descSize);
  604. IF descAdr # LinLibc.NULL THEN
  605. modAdr := LinLibc.calloc(1, modSize);
  606. IF modAdr # LinLibc.NULL THEN INC(used, descSize + modSize)
  607. ELSE LinLibc.free(descAdr); descAdr := 0
  608. END
  609. ELSE modAdr := 0
  610. END
  611. END AllocModMem;
  612. PROCEDURE DeallocModMem* (descSize, modSize, descAdr, modAdr: INTEGER);
  613. VAR res: INTEGER;
  614. BEGIN
  615. DEC(used, descSize + modSize);
  616. (*
  617. res := KERNEL32.VirtualFree(descAdr, 0, {15}); (* release *)
  618. res := KERNEL32.VirtualFree(modAdr, 0, {15}) (* release *)
  619. *)
  620. LinLibc.free(descAdr);
  621. LinLibc.free(modAdr)
  622. END DeallocModMem;
  623. PROCEDURE InvalModMem (modSize, modAdr: INTEGER);
  624. VAR res: INTEGER;
  625. BEGIN
  626. DEC(used, modSize);
  627. (*
  628. res := KERNEL32.VirtualFree(modAdr, modSize, {14}) (* decommit *)
  629. *)
  630. LinLibc.free(modAdr)
  631. END InvalModMem;
  632. PROCEDURE IsReadable* (from, to: INTEGER): BOOLEAN;
  633. (* check wether memory between from (incl.) and to (excl.) may be read *)
  634. BEGIN
  635. (*
  636. RETURN KERNEL32.IsBadReadPtr(from, to - from) = 0
  637. *)
  638. RETURN TRUE (* TODO: Do this correct!!! *)
  639. END IsReadable;
  640. (* --------------------- COM reference counting -------------------- *)
  641. PROCEDURE [noframe] AddRef* (p: INTEGER): INTEGER; (* COMPILER DEPENDENT *)
  642. BEGIN
  643. ADDREF
  644. (*
  645. INC(p.ref);
  646. IF p.unk # NIL THEN p.unk.AddRef() END;
  647. RETURN p.ref
  648. *)
  649. END AddRef;
  650. PROCEDURE [noframe] Release* (p: INTEGER): INTEGER; (* COMPILER DEPENDENT *)
  651. BEGIN
  652. RELEASE
  653. (*
  654. IF p.unk # NIL THEN p.unk.Release() END;
  655. DEC(p.ref);
  656. RETURN p.ref
  657. *)
  658. END Release;
  659. PROCEDURE [noframe] Release2* (p: INTEGER): INTEGER; (* COMPILER DEPENDENT *)
  660. BEGIN
  661. CALLREL;
  662. RELEASE
  663. (*
  664. IF p.ref = 1 THEN p.RELEASE END;
  665. IF p.unk # NIL THEN p.unk.Release() END;
  666. DEC(p.ref);
  667. RETURN p.ref
  668. *)
  669. END Release2;
  670. (*
  671. PROCEDURE RecFinalizer (obj: ANYPTR);
  672. VAR i: INTEGER; type: Type; p: IntPtr;
  673. BEGIN
  674. SYSTEM.GET(SYSTEM.VAL(INTEGER, obj) - 4, type);
  675. i := 0;
  676. WHILE type.ptroffs[i] >= 0 DO INC(i) END;
  677. INC(i);
  678. WHILE type.ptroffs[i] >= 0 DO
  679. p := SYSTEM.VAL(IntPtr, SYSTEM.VAL(INTEGER, obj) + type.ptroffs[i]); INC(i);
  680. p.p := NIL (* calls p.p.Release *)
  681. END
  682. END RecFinalizer;
  683. *)
  684. (*
  685. PROCEDURE ArrFinalizer (obj: SYSTEM.PTR);
  686. VAR last, adr, i, j: INTEGER; type: Type; p: IntPtr;
  687. BEGIN
  688. SYSTEM.GET(SYSTEM.VAL(INTEGER, obj) - 4, type);
  689. type := SYSTEM.VAL(Type, SYSTEM.VAL(INTEGER, type) - 2); (* remove array flag *)
  690. SYSTEM.GET(SYSTEM.VAL(INTEGER, obj), last);
  691. SYSTEM.GET(SYSTEM.VAL(INTEGER, obj) + 8, adr);
  692. j := 0;
  693. WHILE type.ptroffs[j] >= 0 DO INC(j) END;
  694. INC(j);
  695. WHILE adr <= last DO
  696. i := j;
  697. WHILE type.ptroffs[i] >= 0 DO
  698. p := SYSTEM.VAL(IntPtr, adr + type.ptroffs[i]); INC(i);
  699. p.p := NIL (* calls p.p.Release *)
  700. END;
  701. INC(adr, type.size)
  702. END
  703. END ArrFinalizer;
  704. *)
  705. (*
  706. PROCEDURE ReleaseIPtrs (mod: Module);
  707. VAR i: INTEGER; p: IntPtr;
  708. BEGIN
  709. IF iptrs IN mod.opts THEN
  710. EXCL(mod.opts, iptrs);
  711. i := mod.nofptrs;
  712. WHILE mod.ptrs[i] # -1 DO
  713. p := SYSTEM.VAL(IntPtr, mod.varBase + mod.ptrs[i]); INC(i);
  714. p.p := NIL (* calls p.p.Release *)
  715. END
  716. END
  717. END ReleaseIPtrs;
  718. *)
  719. (* --------------------- NEW implementation (portable) -------------------- *)
  720. PROCEDURE^ NewBlock (size: INTEGER): Block;
  721. PROCEDURE NewRec* (typ: INTEGER): INTEGER; (* implementation of NEW(ptr) *)
  722. VAR size: INTEGER; b: Block; tag: Type; l: FList;
  723. BEGIN
  724. IF ODD(typ) THEN (* record contains interface pointers *)
  725. tag := SYSTEM.VAL(Type, typ - 1);
  726. b := NewBlock(tag.size);
  727. IF b = NIL THEN RETURN 0 END;
  728. b.tag := tag;
  729. l := SYSTEM.VAL(FList, NewRec(SYSTEM.TYP(FList))); (* NEW(l) *)
  730. l.blk := b; l.iptr := TRUE; l.next := finalizers; finalizers := l;
  731. RETURN SYSTEM.ADR(b.last)
  732. ELSE
  733. tag := SYSTEM.VAL(Type, typ);
  734. b := NewBlock(tag.size);
  735. IF b = NIL THEN RETURN 0 END;
  736. b.tag := tag; SYSTEM.GET(typ - 4, size);
  737. IF size # 0 THEN (* record uses a finalizer *)
  738. l := SYSTEM.VAL(FList, NewRec(SYSTEM.TYP(FList))); (* NEW(l) *)
  739. l.blk := b; l.next := finalizers; finalizers := l
  740. END;
  741. RETURN SYSTEM.ADR(b.last)
  742. END
  743. END NewRec;
  744. PROCEDURE NewArr* (eltyp, nofelem, nofdim: INTEGER): INTEGER; (* impl. of NEW(ptr, dim0, dim1, ...) *)
  745. VAR b: Block; size, headSize: INTEGER; t: Type; fin: BOOLEAN; l: FList;
  746. BEGIN
  747. headSize := 4 * nofdim + 12; fin := FALSE;
  748. CASE eltyp OF
  749. (*
  750. | -1: eltyp := SYSTEM.ADR(IntPtrType); fin := TRUE
  751. *)
  752. | 0: eltyp := SYSTEM.ADR(PtrType)
  753. | 1: eltyp := SYSTEM.ADR(Char8Type)
  754. | 2: eltyp := SYSTEM.ADR(Int16Type)
  755. | 3: eltyp := SYSTEM.ADR(Int8Type)
  756. | 4: eltyp := SYSTEM.ADR(Int32Type)
  757. | 5: eltyp := SYSTEM.ADR(BoolType)
  758. | 6: eltyp := SYSTEM.ADR(SetType)
  759. | 7: eltyp := SYSTEM.ADR(Real32Type)
  760. | 8: eltyp := SYSTEM.ADR(Real64Type)
  761. | 9: eltyp := SYSTEM.ADR(Char16Type)
  762. | 10: eltyp := SYSTEM.ADR(Int64Type)
  763. | 11: eltyp := SYSTEM.ADR(ProcType)
  764. | 12: eltyp := SYSTEM.ADR(UPtrType)
  765. ELSE (* eltyp is desc *)
  766. IF ODD(eltyp) THEN DEC(eltyp); fin := TRUE END
  767. END;
  768. t := SYSTEM.VAL(Type, eltyp);
  769. size := headSize + nofelem * t.size;
  770. b := NewBlock(size);
  771. IF b = NIL THEN RETURN 0 END;
  772. b.tag := SYSTEM.VAL(Type, eltyp + 2); (* tag + array mark *)
  773. b.last := SYSTEM.ADR(b.last) + size - t.size; (* pointer to last elem *)
  774. b.first := SYSTEM.ADR(b.last) + headSize; (* pointer to first elem *)
  775. IF fin THEN
  776. l := SYSTEM.VAL(FList, NewRec(SYSTEM.TYP(FList))); (* NEW(l) *)
  777. l.blk := b; l.aiptr := TRUE; l.next := finalizers; finalizers := l
  778. END;
  779. RETURN SYSTEM.ADR(b.last)
  780. END NewArr;
  781. (* -------------------- handler installation (portable) --------------------- *)
  782. PROCEDURE ThisFinObj* (VAR id: Identifier): ANYPTR;
  783. VAR l: FList;
  784. BEGIN
  785. ASSERT(id.typ # 0, 100); ASSERT(hotFinalizers = NIL, 101);
  786. l := finalizers;
  787. WHILE l # NIL DO
  788. IF SYSTEM.VAL(INTEGER, l.blk.tag) = id.typ THEN
  789. id.obj := SYSTEM.VAL(ANYPTR, SYSTEM.ADR(l.blk.last));
  790. IF id.Identified() THEN RETURN id.obj END
  791. END;
  792. l := l.next
  793. END;
  794. RETURN NIL
  795. END ThisFinObj;
  796. PROCEDURE InstallReducer* (r: Reducer);
  797. BEGIN
  798. r.next := reducers; reducers := r
  799. END InstallReducer;
  800. PROCEDURE InstallTrapViewer* (h: Handler);
  801. BEGIN
  802. trapViewer := h
  803. END InstallTrapViewer;
  804. PROCEDURE InstallTrapChecker* (h: Handler);
  805. BEGIN
  806. trapChecker := h
  807. END InstallTrapChecker;
  808. PROCEDURE PushTrapCleaner* (c: TrapCleaner);
  809. VAR t: TrapCleaner;
  810. BEGIN
  811. t := trapStack; WHILE (t # NIL) & (t # c) DO t := t.next END;
  812. ASSERT(t = NIL, 20);
  813. c.next := trapStack; trapStack := c
  814. END PushTrapCleaner;
  815. PROCEDURE PopTrapCleaner* (c: TrapCleaner);
  816. VAR t: TrapCleaner;
  817. BEGIN
  818. t := NIL;
  819. WHILE (trapStack # NIL) & (t # c) DO
  820. t := trapStack; trapStack := trapStack.next
  821. END
  822. END PopTrapCleaner;
  823. PROCEDURE InstallCleaner* (p: Command);
  824. VAR c: CList;
  825. BEGIN
  826. c := SYSTEM.VAL(CList, NewRec(SYSTEM.TYP(CList))); (* NEW(c) *)
  827. c.do := p; c.trapped := FALSE; c.next := cleaners; cleaners := c
  828. END InstallCleaner;
  829. PROCEDURE RemoveCleaner* (p: Command);
  830. VAR c0, c: CList;
  831. BEGIN
  832. c := cleaners; c0 := NIL;
  833. WHILE (c # NIL) & (c.do # p) DO c0 := c; c := c.next END;
  834. IF c # NIL THEN
  835. IF c0 = NIL THEN cleaners := cleaners.next ELSE c0.next := c.next END
  836. END
  837. END RemoveCleaner;
  838. PROCEDURE Cleanup*;
  839. VAR c, c0: CList;
  840. BEGIN
  841. c := cleaners; c0 := NIL;
  842. WHILE c # NIL DO
  843. IF ~c.trapped THEN
  844. c.trapped := TRUE; c.do; c.trapped := FALSE; c0 := c
  845. ELSE
  846. IF c0 = NIL THEN cleaners := cleaners.next
  847. ELSE c0.next := c.next
  848. END
  849. END;
  850. c := c.next
  851. END
  852. END Cleanup;
  853. (* -------------------- meta information (portable) --------------------- *)
  854. PROCEDURE (h: LoaderHook) ThisMod* (IN name: ARRAY OF SHORTCHAR): Module, NEW, ABSTRACT;
  855. PROCEDURE SetLoaderHook*(h: LoaderHook);
  856. BEGIN
  857. loader := h
  858. END SetLoaderHook;
  859. PROCEDURE InitModule (mod: Module); (* initialize linked modules *)
  860. VAR body: Command;
  861. res, errno: INTEGER;
  862. BEGIN
  863. IF ~(dyn IN mod.opts) & (mod.next # NIL) & ~(init IN mod.next.opts) THEN InitModule(mod.next) END;
  864. IF ~(init IN mod.opts) THEN
  865. body := SYSTEM.VAL(Command, mod.code);
  866. INCL(mod.opts, init);
  867. actual := mod;
  868. (* A. V. Shiryaev: OpenBSD-specific *)
  869. (*
  870. res := LinLibc.mprotect(
  871. (mod.code DIV LinLibc.PAGE_SIZE) * LinLibc.PAGE_SIZE,
  872. ((mod.csize + mod.code MOD LinLibc.PAGE_SIZE - 1) DIV LinLibc.PAGE_SIZE) * LinLibc.PAGE_SIZE + LinLibc.PAGE_SIZE,
  873. LinLibc.PROT_READ + LinLibc.PROT_WRITE + LinLibc.PROT_EXEC);
  874. *)
  875. res := LinLibc.mprotect(mod.code, mod.csize,
  876. LinLibc.PROT_READ + LinLibc.PROT_WRITE + LinLibc.PROT_EXEC);
  877. IF res = -1 THEN
  878. SYSTEM.GET( LinLibc.__errno_location(), errno );
  879. res := LinLibc.printf("Kernel.InitModule('"); res := LinLibc.printf(mod.name);
  880. res := LinLibc.printf("'): mprotect("); Int(mod.code);
  881. res := LinLibc.printf(", "); Int(mod.csize);
  882. res := LinLibc.printf(", R|W|E) failed: errno = "); Int(errno);
  883. res := LinLibc.printf(0AX);
  884. (* HALT(100) *)
  885. ELSE ASSERT(res = 0)
  886. END;
  887. body();
  888. actual := NIL
  889. END
  890. END InitModule;
  891. PROCEDURE ThisLoadedMod* (IN name: ARRAY OF SHORTCHAR): Module; (* loaded modules only *)
  892. VAR m: Module;
  893. BEGIN
  894. loadres := done;
  895. m := modList;
  896. WHILE (m # NIL) & ((m.name # name) OR (m.refcnt < 0)) DO m := m.next END;
  897. IF (m # NIL) & ~(init IN m.opts) THEN InitModule(m) END;
  898. IF m = NIL THEN loadres := moduleNotFound END;
  899. RETURN m
  900. END ThisLoadedMod;
  901. PROCEDURE ThisMod* (IN name: ARRAY OF CHAR): Module;
  902. VAR n : Name;
  903. BEGIN
  904. n := SHORT(name$);
  905. IF loader # NIL THEN
  906. loader.res := done;
  907. RETURN loader.ThisMod(n)
  908. ELSE
  909. RETURN ThisLoadedMod(n)
  910. END
  911. END ThisMod;
  912. PROCEDURE LoadMod* (IN name: ARRAY OF CHAR);
  913. VAR m: Module;
  914. BEGIN
  915. m := ThisMod(name)
  916. END LoadMod;
  917. PROCEDURE GetLoaderResult* (OUT res: INTEGER; OUT importing, imported, object: ARRAY OF CHAR);
  918. BEGIN
  919. IF loader # NIL THEN
  920. res := loader.res;
  921. importing := loader.importing$;
  922. imported := loader.imported$;
  923. object := loader.object$
  924. ELSE
  925. res := loadres;
  926. importing := "";
  927. imported := "";
  928. object := ""
  929. END
  930. END GetLoaderResult;
  931. PROCEDURE ThisObject* (mod: Module; name: ARRAY OF SHORTCHAR): Object;
  932. VAR l, r, m: INTEGER; p: StrPtr;
  933. BEGIN
  934. l := 0; r := mod.export.num;
  935. WHILE l < r DO (* binary search *)
  936. m := (l + r) DIV 2;
  937. p := SYSTEM.VAL(StrPtr, SYSTEM.ADR(mod.names[mod.export.obj[m].id DIV 256]));
  938. IF p^ = name THEN RETURN SYSTEM.VAL(Object, SYSTEM.ADR(mod.export.obj[m])) END;
  939. IF p^ < name THEN l := m + 1 ELSE r := m END
  940. END;
  941. RETURN NIL
  942. END ThisObject;
  943. PROCEDURE ThisDesc* (mod: Module; fprint: INTEGER): Object;
  944. VAR i, n: INTEGER;
  945. BEGIN
  946. i := 0; n := mod.export.num;
  947. WHILE (i < n) & (mod.export.obj[i].id DIV 256 = 0) DO
  948. IF mod.export.obj[i].offs = fprint THEN
  949. RETURN SYSTEM.VAL(Object, SYSTEM.ADR(mod.export.obj[i]))
  950. END;
  951. INC(i)
  952. END;
  953. RETURN NIL
  954. END ThisDesc;
  955. PROCEDURE ThisField* (rec: Type; name: ARRAY OF SHORTCHAR): Object;
  956. VAR n: INTEGER; p: StrPtr; obj: Object; m: Module;
  957. BEGIN
  958. m := rec.mod;
  959. obj := SYSTEM.VAL(Object, SYSTEM.ADR(rec.fields.obj[0])); n := rec.fields.num;
  960. WHILE n > 0 DO
  961. p := SYSTEM.VAL(StrPtr, SYSTEM.ADR(m.names[obj.id DIV 256]));
  962. IF p^ = name THEN RETURN obj END;
  963. DEC(n); INC(SYSTEM.VAL(INTEGER, obj), 16)
  964. END;
  965. RETURN NIL
  966. END ThisField;
  967. (*PROCEDURE ThisCommand* (mod: Module; name: ARRAY OF SHORTCHAR): Command;
  968. VAR x: Object;
  969. BEGIN
  970. x := ThisObject(mod, name);
  971. IF (x # NIL) & (x.id MOD 16 = mProc) & (x.fprint = comSig) THEN
  972. RETURN SYSTEM.VAL(Command, mod.procBase + x.offs)
  973. ELSE
  974. RETURN NIL
  975. END
  976. END ThisCommand;*)
  977. PROCEDURE ThisCommand* (mod: Module; name: ARRAY OF SHORTCHAR): Command;
  978. VAR x: Object; sig: Signature;
  979. BEGIN
  980. x := ThisObject(mod, name);
  981. IF (x # NIL) & (x.id MOD 16 = mProc) THEN
  982. sig := SYSTEM.VAL(Signature, x.struct);
  983. IF (sig.retStruct = NIL) & (sig.num = 0) THEN RETURN SYSTEM.VAL(Command, mod.procBase + x.offs) END
  984. END;
  985. RETURN NIL
  986. END ThisCommand;
  987. PROCEDURE ThisType* (mod: Module; name: ARRAY OF SHORTCHAR): Type;
  988. VAR x: Object;
  989. BEGIN
  990. x := ThisObject(mod, name);
  991. IF (x # NIL) & (x.id MOD 16 = mTyp) & (SYSTEM.VAL(INTEGER, x.struct) DIV 256 # 0) THEN
  992. RETURN x.struct
  993. ELSE
  994. RETURN NIL
  995. END
  996. END ThisType;
  997. PROCEDURE TypeOf* (IN rec: ANYREC): Type;
  998. BEGIN
  999. RETURN SYSTEM.VAL(Type, SYSTEM.TYP(rec))
  1000. END TypeOf;
  1001. PROCEDURE LevelOf* (t: Type): SHORTINT;
  1002. BEGIN
  1003. RETURN SHORT(t.id DIV 16 MOD 16)
  1004. END LevelOf;
  1005. PROCEDURE NewObj* (VAR o: SYSTEM.PTR; t: Type);
  1006. VAR i: INTEGER;
  1007. BEGIN
  1008. IF t.size = -1 THEN o := NIL
  1009. ELSE
  1010. i := 0; WHILE t.ptroffs[i] >= 0 DO INC(i) END;
  1011. IF t.ptroffs[i+1] >= 0 THEN INC(SYSTEM.VAL(INTEGER, t)) END; (* with interface pointers *)
  1012. o := SYSTEM.VAL(SYSTEM.PTR, NewRec(SYSTEM.VAL(INTEGER, t))) (* generic NEW *)
  1013. END
  1014. END NewObj;
  1015. PROCEDURE GetObjName* (mod: Module; obj: Object; VAR name: Name);
  1016. VAR p: StrPtr;
  1017. BEGIN
  1018. p := SYSTEM.VAL(StrPtr, SYSTEM.ADR(mod.names[obj.id DIV 256]));
  1019. name := p^$
  1020. END GetObjName;
  1021. PROCEDURE GetTypeName* (t: Type; VAR name: Name);
  1022. VAR p: StrPtr;
  1023. BEGIN
  1024. p := SYSTEM.VAL(StrPtr, SYSTEM.ADR(t.mod.names[t.id DIV 256]));
  1025. name := p^$
  1026. END GetTypeName;
  1027. PROCEDURE RegisterMod* (mod: Module);
  1028. VAR i: INTEGER;(* t: KERNEL32.SystemTime;*) obj: Object; s: SET; c: Command; str: Name;
  1029. t: LinLibc.time_t; tm: LinLibc.tm;
  1030. BEGIN
  1031. mod.next := modList; modList := mod; mod.refcnt := 0; INCL(mod.opts, dyn); i := 0;
  1032. WHILE i < mod.nofimps DO
  1033. IF mod.imports[i] # NIL THEN INC(mod.imports[i].refcnt) END;
  1034. INC(i)
  1035. END;
  1036. t := LinLibc.time(NIL);
  1037. tm := LinLibc.localtime(t);
  1038. mod.loadTime[0] := SHORT(tm.tm_year + 1900); (* Linux counts years from 1900 but BlackBox from 0000 *)
  1039. mod.loadTime[1] := SHORT(tm.tm_mon + 1) (* Linux month range 0-11 but BB month range 1-12 *);
  1040. mod.loadTime[2] := SHORT(tm.tm_mday);
  1041. mod.loadTime[3] := SHORT(tm.tm_hour);
  1042. mod.loadTime[4] := SHORT(tm.tm_min);
  1043. mod.loadTime[5] := SHORT(tm.tm_sec);
  1044. tm := NIL;
  1045. IF ~(init IN mod.opts) THEN InitModule(mod) END
  1046. END RegisterMod;
  1047. PROCEDURE^ Collect*;
  1048. PROCEDURE UnloadMod* (mod: Module);
  1049. VAR i: INTEGER; t: Command;
  1050. BEGIN
  1051. IF mod.refcnt = 0 THEN
  1052. t := mod.term; mod.term := NIL;
  1053. IF t # NIL THEN t() END; (* terminate module *)
  1054. i := 0;
  1055. WHILE i < mod.nofptrs DO (* release global pointers *)
  1056. SYSTEM.PUT(mod.varBase + mod.ptrs[i], 0); INC(i)
  1057. END;
  1058. (*
  1059. ReleaseIPtrs(mod); (* release global interface pointers *)
  1060. *)
  1061. Collect; (* call finalizers *)
  1062. i := 0;
  1063. WHILE i < mod.nofimps DO (* release imported modules *)
  1064. IF mod.imports[i] # NIL THEN DEC(mod.imports[i].refcnt) END;
  1065. INC(i)
  1066. END;
  1067. mod.refcnt := -1;
  1068. IF dyn IN mod.opts THEN (* release memory *)
  1069. InvalModMem(mod.data + mod.dsize - mod.refs, mod.refs)
  1070. END
  1071. END
  1072. END UnloadMod;
  1073. (* -------------------- dynamic procedure call --------------------- *) (* COMPILER DEPENDENT *)
  1074. PROCEDURE [1] PUSH (p: INTEGER) 050H; (* push AX *)
  1075. PROCEDURE [1] CALL (a: INTEGER) 0FFH, 0D0H; (* call AX *)
  1076. PROCEDURE [1] RETI (): LONGINT;
  1077. PROCEDURE [1] RETR (): REAL;
  1078. (*
  1079. type par
  1080. 32 bit scalar value
  1081. 64 bit scalar low hi
  1082. var scalar address
  1083. record address tag
  1084. array address size
  1085. open array address length .. length
  1086. *)
  1087. PROCEDURE Call* (adr: INTEGER; sig: Signature; IN par: ARRAY OF INTEGER; n: INTEGER): LONGINT;
  1088. VAR p, kind, sp, size: INTEGER; typ: Type; r: REAL;
  1089. BEGIN
  1090. p := sig.num;
  1091. WHILE p > 0 DO (* push parameters from right to left *)
  1092. DEC(p);
  1093. typ := sig.par[p].struct;
  1094. kind := sig.par[p].id MOD 16;
  1095. IF (SYSTEM.VAL(INTEGER, typ) DIV 256 = 0) OR (typ.id MOD 4 IN {0, 3}) THEN (* scalar *)
  1096. IF (kind = 10) & ((SYSTEM.VAL(INTEGER, typ) = 8) OR (SYSTEM.VAL(INTEGER, typ) = 10)) THEN (* 64 bit *)
  1097. DEC(n); PUSH(par[n]) (* push hi word *)
  1098. END;
  1099. DEC(n); PUSH(par[n]) (* push value/address *)
  1100. ELSIF typ.id MOD 4 = 1 THEN (* record *)
  1101. IF kind # 10 THEN (* var par *)
  1102. DEC(n); PUSH(par[n]); (* push tag *)
  1103. DEC(n); PUSH(par[n]) (* push address *)
  1104. ELSE
  1105. DEC(n, 2); (* skip tag *)
  1106. SYSTEM.GETREG(SP, sp); sp := (sp - typ.size) DIV 4 * 4; SYSTEM.PUTREG(SP, sp); (* allocate space *)
  1107. SYSTEM.MOVE(par[n], sp, typ.size) (* copy to stack *)
  1108. END
  1109. ELSIF typ.size = 0 THEN (* open array *)
  1110. size := typ.id DIV 16 MOD 16; (* number of open dimensions *)
  1111. WHILE size > 0 DO
  1112. DEC(size); DEC(n); PUSH(par[n]) (* push length *)
  1113. END;
  1114. DEC(n); PUSH(par[n]) (* push address *)
  1115. ELSE (* fix array *)
  1116. IF kind # 10 THEN (* var par *)
  1117. DEC(n, 2); PUSH(par[n]) (* push address *)
  1118. ELSE
  1119. DEC(n); size := par[n]; DEC(n);
  1120. SYSTEM.GETREG(SP, sp); sp := (sp - size) DIV 4 * 4; SYSTEM.PUTREG(SP, sp); (* allocate space *)
  1121. SYSTEM.MOVE(par[n], sp, size) (* copy to stack *)
  1122. END
  1123. END
  1124. END;
  1125. ASSERT(n = 0);
  1126. IF SYSTEM.VAL(INTEGER, sig.retStruct) = 7 THEN (* shortreal *)
  1127. CALL(adr);
  1128. RETURN SYSTEM.VAL(INTEGER, SHORT(RETR())) (* return value in fpu register *)
  1129. ELSIF SYSTEM.VAL(INTEGER, sig.retStruct) = 8 THEN (* real *)
  1130. CALL(adr); r := RETR();
  1131. RETURN SYSTEM.VAL(LONGINT, r) (* return value in fpu register *)
  1132. ELSE
  1133. CALL(adr);
  1134. RETURN RETI() (* return value in integer registers *)
  1135. END
  1136. END Call;
  1137. (* -------------------- reference information (portable) --------------------- *)
  1138. PROCEDURE RefCh (VAR ref: INTEGER; VAR ch: SHORTCHAR);
  1139. BEGIN
  1140. SYSTEM.GET(ref, ch); INC(ref)
  1141. END RefCh;
  1142. PROCEDURE RefNum (VAR ref: INTEGER; VAR x: INTEGER);
  1143. VAR s, n: INTEGER; ch: SHORTCHAR;
  1144. BEGIN
  1145. s := 0; n := 0; RefCh(ref, ch);
  1146. WHILE ORD(ch) >= 128 DO INC(n, ASH(ORD(ch) - 128, s) ); INC(s, 7); RefCh(ref, ch) END;
  1147. x := n + ASH(ORD(ch) MOD 64 - ORD(ch) DIV 64 * 64, s)
  1148. END RefNum;
  1149. PROCEDURE RefName (VAR ref: INTEGER; VAR n: Name);
  1150. VAR i: INTEGER; ch: SHORTCHAR;
  1151. BEGIN
  1152. i := 0; RefCh(ref, ch);
  1153. WHILE ch # 0X DO n[i] := ch; INC(i); RefCh(ref, ch) END;
  1154. n[i] := 0X
  1155. END RefName;
  1156. PROCEDURE GetRefProc* (VAR ref: INTEGER; VAR adr: INTEGER; VAR name: Name);
  1157. VAR ch: SHORTCHAR;
  1158. BEGIN
  1159. SYSTEM.GET(ref, ch);
  1160. WHILE ch >= 0FDX DO (* skip variables *)
  1161. INC(ref); RefCh(ref, ch);
  1162. IF ch = 10X THEN INC(ref, 4) END;
  1163. RefNum(ref, adr); RefName(ref, name); SYSTEM.GET(ref, ch)
  1164. END;
  1165. WHILE (ch > 0X) & (ch < 0FCX) DO (* skip source refs *)
  1166. INC(ref); RefNum(ref, adr); SYSTEM.GET(ref, ch)
  1167. END;
  1168. IF ch = 0FCX THEN INC(ref); RefNum(ref, adr); RefName(ref, name)
  1169. ELSE adr := 0
  1170. END
  1171. END GetRefProc;
  1172. PROCEDURE GetRefVar* (VAR ref: INTEGER; VAR mode, form: SHORTCHAR; VAR desc: Type;
  1173. VAR adr: INTEGER; VAR name: Name
  1174. );
  1175. BEGIN
  1176. SYSTEM.GET(ref, mode); desc := NIL;
  1177. IF mode >= 0FDX THEN
  1178. mode := SHORT(CHR(ORD(mode) - 0FCH));
  1179. INC(ref); RefCh(ref, form);
  1180. IF form = 10X THEN
  1181. SYSTEM.GET(ref, desc); INC(ref, 4); form := SHORT(CHR(16 + desc.id MOD 4))
  1182. END;
  1183. RefNum(ref, adr); RefName(ref, name)
  1184. ELSE
  1185. mode := 0X; form := 0X; adr := 0
  1186. END
  1187. END GetRefVar;
  1188. PROCEDURE SourcePos* (mod: Module; codePos: INTEGER): INTEGER;
  1189. VAR ref, pos, ad, d: INTEGER; ch: SHORTCHAR; name: Name;
  1190. BEGIN
  1191. ref := mod.refs; pos := 0; ad := 0; SYSTEM.GET(ref, ch);
  1192. WHILE ch # 0X DO
  1193. WHILE (ch > 0X) & (ch < 0FCX) DO
  1194. INC(ad, ORD(ch)); INC(ref); RefNum(ref, d);
  1195. IF ad > codePos THEN RETURN pos END;
  1196. INC(pos, d); SYSTEM.GET(ref, ch)
  1197. END;
  1198. IF ch = 0FCX THEN INC(ref); RefNum(ref, d); RefName(ref, name); SYSTEM.GET(ref, ch) END;
  1199. WHILE ch >= 0FDX DO (* skip variables *)
  1200. INC(ref); RefCh(ref, ch);
  1201. IF ch = 10X THEN INC(ref, 4) END;
  1202. RefNum(ref, d); RefName(ref, name); SYSTEM.GET(ref, ch)
  1203. END
  1204. END;
  1205. RETURN -1
  1206. END SourcePos;
  1207. (* -------------------- dynamic link libraries --------------------- *)
  1208. (*
  1209. PROCEDURE LoadDll* (IN name: ARRAY OF SHORTCHAR; VAR ok: BOOLEAN);
  1210. VAR h: KERNEL32.Handle;
  1211. BEGIN
  1212. ok := FALSE;
  1213. h := KERNEL32.LoadLibraryA(name);
  1214. IF h # 0 THEN ok := TRUE END
  1215. END LoadDll;
  1216. PROCEDURE ThisDllObj* (mode, fprint: INTEGER; IN dll, name: ARRAY OF SHORTCHAR): INTEGER;
  1217. VAR ad: INTEGER; h: KERNEL32.Handle;
  1218. BEGIN
  1219. ad := 0;
  1220. IF mode = mProc THEN
  1221. h := KERNEL32.GetModuleHandleA(dll);
  1222. IF h # 0 THEN ad := KERNEL32.GetProcAddress(h, name) END
  1223. END;
  1224. RETURN ad
  1225. END ThisDllObj;
  1226. *)
  1227. PROCEDURE LoadDll* (IN name: ARRAY OF SHORTCHAR; VAR ok: BOOLEAN);
  1228. VAR h: LinDl.HANDLE;
  1229. BEGIN
  1230. ok := FALSE;
  1231. h := LinDl.dlopen(name, LinDl.RTLD_LAZY + LinDl.RTLD_GLOBAL);
  1232. IF h # LinDl.NULL THEN ok := TRUE END
  1233. END LoadDll;
  1234. PROCEDURE ThisDllObj* (mode, fprint: INTEGER; IN dll, name: ARRAY OF SHORTCHAR): INTEGER;
  1235. VAR ad: INTEGER; h: LinDl.HANDLE;
  1236. BEGIN
  1237. ad := 0;
  1238. IF mode IN {mVar, mProc} THEN
  1239. h := LinDl.dlopen(dll, LinDl.RTLD_LAZY+ LinDl.RTLD_GLOBAL);
  1240. IF h # LinDl.NULL THEN
  1241. ad := LinDl.dlsym(h, name);
  1242. END
  1243. END;
  1244. RETURN ad
  1245. END ThisDllObj;
  1246. (* -------------------- garbage collector (portable) --------------------- *)
  1247. PROCEDURE Mark (this: Block);
  1248. VAR father, son: Block; tag: Type; flag, offset, actual: INTEGER;
  1249. BEGIN
  1250. IF ~ODD(SYSTEM.VAL(INTEGER, this.tag)) THEN
  1251. father := NIL;
  1252. LOOP
  1253. INC(SYSTEM.VAL(INTEGER, this.tag));
  1254. flag := SYSTEM.VAL(INTEGER, this.tag) MOD 4;
  1255. tag := SYSTEM.VAL(Type, SYSTEM.VAL(INTEGER, this.tag) - flag);
  1256. IF flag >= 2 THEN actual := this.first; this.actual := actual
  1257. ELSE actual := SYSTEM.ADR(this.last)
  1258. END;
  1259. LOOP
  1260. offset := tag.ptroffs[0];
  1261. IF offset < 0 THEN
  1262. INC(SYSTEM.VAL(INTEGER, tag), offset + 4); (* restore tag *)
  1263. IF (flag >= 2) & (actual < this.last) & (offset < -4) THEN (* next array element *)
  1264. INC(actual, tag.size); this.actual := actual
  1265. ELSE (* up *)
  1266. this.tag := SYSTEM.VAL(Type, SYSTEM.VAL(INTEGER, tag) + flag);
  1267. IF father = NIL THEN RETURN END;
  1268. son := this; this := father;
  1269. flag := SYSTEM.VAL(INTEGER, this.tag) MOD 4;
  1270. tag := SYSTEM.VAL(Type, SYSTEM.VAL(INTEGER, this.tag) - flag);
  1271. offset := tag.ptroffs[0];
  1272. IF flag >= 2 THEN actual := this.actual ELSE actual := SYSTEM.ADR(this.last) END;
  1273. SYSTEM.GET(actual + offset, father); SYSTEM.PUT(actual + offset, SYSTEM.ADR(son.last));
  1274. INC(SYSTEM.VAL(INTEGER, tag), 4)
  1275. END
  1276. ELSE
  1277. SYSTEM.GET(actual + offset, son);
  1278. IF son # NIL THEN
  1279. DEC(SYSTEM.VAL(INTEGER, son), 4);
  1280. IF ~ODD(SYSTEM.VAL(INTEGER, son.tag)) THEN (* down *)
  1281. this.tag := SYSTEM.VAL(Type, SYSTEM.VAL(INTEGER, tag) + flag);
  1282. SYSTEM.PUT(actual + offset, father); father := this; this := son;
  1283. EXIT
  1284. END
  1285. END;
  1286. INC(SYSTEM.VAL(INTEGER, tag), 4)
  1287. END
  1288. END
  1289. END
  1290. END
  1291. END Mark;
  1292. PROCEDURE MarkGlobals;
  1293. VAR m: Module; i, p: INTEGER;
  1294. BEGIN
  1295. m := modList;
  1296. WHILE m # NIL DO
  1297. IF m.refcnt >= 0 THEN
  1298. i := 0;
  1299. WHILE i < m.nofptrs DO
  1300. SYSTEM.GET(m.varBase + m.ptrs[i], p); INC(i);
  1301. IF p # 0 THEN
  1302. Mark(SYSTEM.VAL(Block, p - 4))
  1303. END
  1304. END
  1305. END;
  1306. m := m.next
  1307. END
  1308. END MarkGlobals;
  1309. (*
  1310. PROCEDURE Next (b: Block): Block; (* next block in same cluster *)
  1311. VAR size: INTEGER;
  1312. BEGIN
  1313. SYSTEM.GET(SYSTEM.VAL(INTEGER, b.tag) DIV 4 * 4, size);
  1314. IF ODD(SYSTEM.VAL(INTEGER, b.tag) DIV 2) THEN INC(size, b.last - SYSTEM.ADR(b.last)) END;
  1315. RETURN SYSTEM.VAL(Block, SYSTEM.VAL(INTEGER, b) + (size + 19) DIV 16 * 16)
  1316. END Next;
  1317. *)
  1318. PROCEDURE [code] Next (b: Block): Block (* next block in same cluster *)
  1319. (*
  1320. MOV ECX,[EAX] b.tag
  1321. AND CL,0FCH b.tag DIV * 4
  1322. MOV ECX,[ECX] size
  1323. TESTB [EAX],02H ODD(b.tag DIV 2)
  1324. JE L1
  1325. ADD ECX,[EAX,4] size + b.last
  1326. SUB ECX,EAX
  1327. SUB ECX,4 size + b.last - ADR(b.last)
  1328. L1:
  1329. ADD ECX,19 size + 19
  1330. AND CL,0F0H (size + 19) DIV 16 * 16
  1331. ADD EAX,ECX b + size
  1332. *)
  1333. 08BH, 008H,
  1334. 080H, 0E1H, 0FCH,
  1335. 08BH, 009H,
  1336. 0F6H, 000H, 002H,
  1337. 074H, 008H,
  1338. 003H, 048H, 004H,
  1339. 029H, 0C1H,
  1340. 083H, 0E9H, 004H,
  1341. 083H, 0C1H, 013H,
  1342. 080H, 0E1H, 0F0H,
  1343. 001H, 0C8H;
  1344. PROCEDURE CheckCandidates;
  1345. (* pre: nofcand > 0 *)
  1346. VAR i, j, h, p, end: INTEGER; c: Cluster; blk, next: Block;
  1347. BEGIN
  1348. (* sort candidates (shellsort) *)
  1349. h := 1; REPEAT h := h*3 + 1 UNTIL h > nofcand;
  1350. REPEAT h := h DIV 3; i := h;
  1351. WHILE i < nofcand DO p := candidates[i]; j := i;
  1352. WHILE (j >= h) & (candidates[j-h] > p) DO
  1353. candidates[j] := candidates[j-h]; j := j-h
  1354. END;
  1355. candidates[j] := p; INC(i)
  1356. END
  1357. UNTIL h = 1;
  1358. (* sweep *)
  1359. c := root; i := 0;
  1360. WHILE c # NIL DO
  1361. blk := SYSTEM.VAL(Block, SYSTEM.VAL(INTEGER, c) + 12);
  1362. end := SYSTEM.VAL(INTEGER, blk) + (c.size - 12) DIV 16 * 16;
  1363. WHILE candidates[i] < SYSTEM.VAL(INTEGER, blk) DO
  1364. INC(i);
  1365. IF i = nofcand THEN RETURN END
  1366. END;
  1367. WHILE SYSTEM.VAL(INTEGER, blk) < end DO
  1368. next := Next(blk);
  1369. IF candidates[i] < SYSTEM.VAL(INTEGER, next) THEN
  1370. IF (SYSTEM.VAL(INTEGER, blk.tag) # SYSTEM.ADR(blk.last)) (* not a free block *)
  1371. & (~strictStackSweep OR (candidates[i] = SYSTEM.ADR(blk.last))) THEN
  1372. Mark(blk)
  1373. END;
  1374. REPEAT
  1375. INC(i);
  1376. IF i = nofcand THEN RETURN END
  1377. UNTIL candidates[i] >= SYSTEM.VAL(INTEGER, next)
  1378. END;
  1379. IF (SYSTEM.VAL(INTEGER, blk.tag) MOD 4 = 0)
  1380. & (SYSTEM.VAL(INTEGER, blk.tag) # SYSTEM.ADR(blk.last))
  1381. & (blk.tag.base[0] = NIL) & (blk.actual > 0)
  1382. THEN (* referenced interface record *)
  1383. Mark(blk)
  1384. END;
  1385. blk := next
  1386. END;
  1387. c := c.next
  1388. END
  1389. END CheckCandidates;
  1390. PROCEDURE MarkLocals;
  1391. VAR sp, p, min, max: INTEGER; c: Cluster;
  1392. BEGIN
  1393. SYSTEM.GETREG(FP, sp); nofcand := 0; c := root;
  1394. WHILE c.next # NIL DO c := c.next END;
  1395. min := SYSTEM.VAL(INTEGER, root); max := SYSTEM.VAL(INTEGER, c) + c.size;
  1396. WHILE sp < baseStack DO
  1397. SYSTEM.GET(sp, p);
  1398. IF (p > min) & (p < max) & (~strictStackSweep OR (p MOD 16 = 0)) THEN
  1399. candidates[nofcand] := p; INC(nofcand);
  1400. IF nofcand = LEN(candidates) - 1 THEN CheckCandidates; nofcand := 0 END
  1401. END;
  1402. INC(sp, 4)
  1403. END;
  1404. candidates[nofcand] := max; INC(nofcand); (* ensure complete scan for interface mark*)
  1405. IF nofcand > 0 THEN CheckCandidates END
  1406. END MarkLocals;
  1407. PROCEDURE MarkFinObj;
  1408. VAR f: FList;
  1409. BEGIN
  1410. wouldFinalize := FALSE;
  1411. f := finalizers;
  1412. WHILE f # NIL DO
  1413. IF ~ODD(SYSTEM.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END;
  1414. Mark(f.blk);
  1415. f := f.next
  1416. END;
  1417. f := hotFinalizers;
  1418. WHILE f # NIL DO IF ~ODD(SYSTEM.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END;
  1419. Mark(f.blk);
  1420. f := f.next
  1421. END
  1422. END MarkFinObj;
  1423. PROCEDURE CheckFinalizers;
  1424. VAR f, g, h, k: FList;
  1425. BEGIN
  1426. f := finalizers; g := NIL;
  1427. (* hotFinalizers := NIL; k := NIL; *)
  1428. IF hotFinalizers = NIL THEN k := NIL
  1429. ELSE
  1430. k := hotFinalizers;
  1431. WHILE k.next # NIL DO k := k.next END
  1432. END;
  1433. WHILE f # NIL DO
  1434. h := f; f := f.next;
  1435. IF ~ODD(SYSTEM.VAL(INTEGER, h.blk.tag)) THEN
  1436. IF g = NIL THEN finalizers := f ELSE g.next := f END;
  1437. IF k = NIL THEN hotFinalizers := h ELSE k.next := h END;
  1438. k := h; h.next := NIL
  1439. ELSE g := h
  1440. END
  1441. END;
  1442. h := hotFinalizers;
  1443. WHILE h # NIL DO Mark(h.blk); h := h.next END
  1444. END CheckFinalizers;
  1445. PROCEDURE ExecFinalizer (a, b, c: INTEGER);
  1446. VAR f: FList; fin: PROCEDURE(this: ANYPTR);
  1447. BEGIN
  1448. f := hotFinalizers; hotFinalizers := hotFinalizers.next;
  1449. IF f.aiptr THEN (*ArrFinalizer(SYSTEM.VAL(ANYPTR, S.ADR(f.blk.last)))*)
  1450. ELSE
  1451. SYSTEM.GET(SYSTEM.VAL(INTEGER, f.blk.tag) - 4, fin); (* method 0 *)
  1452. IF fin # NIL THEN fin(SYSTEM.VAL(ANYPTR, SYSTEM.ADR(f.blk.last))) END;
  1453. (*
  1454. IF f.iptr THEN RecFinalizer(SYSTEM.VAL(ANYPTR, SYSTEM.ADR(f.blk.last))) END
  1455. *)
  1456. END
  1457. END ExecFinalizer;
  1458. PROCEDURE^ Try* (h: TryHandler; a, b, c: INTEGER); (* COMPILER DEPENDENT *)
  1459. PROCEDURE CallFinalizers;
  1460. VAR f: FList;
  1461. BEGIN
  1462. WHILE hotFinalizers # NIL DO
  1463. f := hotFinalizers.next; hotFinalizers.next := NIL;
  1464. Try(ExecFinalizer, 0, 0, 0);
  1465. hotFinalizers := f
  1466. END;
  1467. wouldFinalize := FALSE
  1468. END CallFinalizers;
  1469. PROCEDURE Insert (blk: FreeBlock; size: INTEGER); (* insert block in free list *)
  1470. VAR i: INTEGER;
  1471. BEGIN
  1472. blk.size := size - 4; blk.tag := SYSTEM.VAL(Type, SYSTEM.ADR(blk.size));
  1473. i := MIN(N - 1, (blk.size DIV 16));
  1474. blk.next := free[i]; free[i] := blk
  1475. END Insert;
  1476. PROCEDURE Sweep (dealloc: BOOLEAN);
  1477. VAR cluster, last, c: Cluster; blk, next: Block; fblk, b, t: FreeBlock; end, i: INTEGER;
  1478. BEGIN
  1479. cluster := root; last := NIL; allocated := 0;
  1480. i := N;
  1481. REPEAT DEC(i); free[i] := sentinel UNTIL i = 0;
  1482. WHILE cluster # NIL DO
  1483. blk := SYSTEM.VAL(Block, SYSTEM.VAL(INTEGER, cluster) + 12);
  1484. end := SYSTEM.VAL(INTEGER, blk) + (cluster.size - 12) DIV 16 * 16;
  1485. fblk := NIL;
  1486. WHILE SYSTEM.VAL(INTEGER, blk) < end DO
  1487. next := Next(blk);
  1488. IF ODD(SYSTEM.VAL(INTEGER, blk.tag)) THEN
  1489. IF fblk # NIL THEN
  1490. Insert(fblk, SYSTEM.VAL(INTEGER, blk) - SYSTEM.VAL(INTEGER, fblk));
  1491. fblk := NIL
  1492. END;
  1493. DEC(SYSTEM.VAL(INTEGER, blk.tag)); (* unmark *)
  1494. INC(allocated, SYSTEM.VAL(INTEGER, next) - SYSTEM.VAL(INTEGER, blk))
  1495. ELSIF fblk = NIL THEN
  1496. fblk := SYSTEM.VAL(FreeBlock, blk)
  1497. END;
  1498. blk := next
  1499. END;
  1500. IF dealloc & (SYSTEM.VAL(INTEGER, fblk) = SYSTEM.VAL(INTEGER, cluster) + 12) THEN
  1501. (* deallocate cluster *)
  1502. c := cluster; cluster := cluster.next;
  1503. IF last = NIL THEN root := cluster ELSE last.next := cluster END;
  1504. FreeHeapMem(c)
  1505. ELSE
  1506. IF fblk # NIL THEN Insert(fblk, end - SYSTEM.VAL(INTEGER, fblk)) END;
  1507. last := cluster; cluster := cluster.next
  1508. END
  1509. END;
  1510. (* reverse free list *)
  1511. i := N;
  1512. REPEAT
  1513. DEC(i);
  1514. b := free[i]; fblk := sentinel;
  1515. WHILE b # sentinel DO t := b; b := t.next; t.next := fblk; fblk := t END;
  1516. free[i] := fblk
  1517. UNTIL i = 0
  1518. END Sweep;
  1519. PROCEDURE Collect*;
  1520. BEGIN
  1521. IF root # NIL THEN
  1522. CallFinalizers; (* trap cleanup *)
  1523. IF debug & (watcher # NIL) THEN watcher(1) END;
  1524. MarkGlobals;
  1525. MarkLocals;
  1526. CheckFinalizers;
  1527. Sweep(TRUE);
  1528. CallFinalizers
  1529. END
  1530. END Collect;
  1531. PROCEDURE FastCollect*;
  1532. BEGIN
  1533. IF root # NIL THEN
  1534. (*
  1535. CallFinalizers; (* trap cleanup *)
  1536. *)
  1537. IF debug & (watcher # NIL) THEN watcher(2) END;
  1538. MarkGlobals;
  1539. MarkLocals;
  1540. (* CheckFinalizers; *)
  1541. MarkFinObj;
  1542. Sweep(FALSE);
  1543. (*
  1544. CallFinalizers
  1545. *)
  1546. END
  1547. END FastCollect;
  1548. (*
  1549. PROCEDURE GlobalCollect*;
  1550. BEGIN
  1551. IF root # NIL THEN
  1552. MarkGlobals;
  1553. (* MarkLocals; *)
  1554. CheckFinalizers;
  1555. Sweep(FALSE);
  1556. END
  1557. END GlobalCollect;
  1558. *)
  1559. PROCEDURE WouldFinalize* (): BOOLEAN;
  1560. BEGIN
  1561. RETURN wouldFinalize
  1562. END WouldFinalize;
  1563. (* --------------------- memory allocation (portable) -------------------- *)
  1564. PROCEDURE OldBlock (size: INTEGER): FreeBlock; (* size MOD 16 = 0 *)
  1565. VAR b, l: FreeBlock; s, i: INTEGER;
  1566. BEGIN
  1567. IF debug & (watcher # NIL) THEN watcher(3) END;
  1568. s := size - 4;
  1569. i := MIN(N - 1, s DIV 16);
  1570. WHILE (i # N - 1) & (free[i] = sentinel) DO INC(i) END;
  1571. b := free[i]; l := NIL;
  1572. WHILE b.size < s DO l := b; b := b.next END;
  1573. IF b # sentinel THEN
  1574. IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END
  1575. ELSE b := NIL
  1576. END;
  1577. RETURN b
  1578. END OldBlock;
  1579. PROCEDURE LastBlock (limit: INTEGER): FreeBlock; (* size MOD 16 = 0 *)
  1580. VAR b, l: FreeBlock; s, i: INTEGER;
  1581. BEGIN
  1582. s := limit - 4;
  1583. i := 0;
  1584. REPEAT
  1585. b := free[i]; l := NIL;
  1586. WHILE (b # sentinel) & (SYSTEM.VAL(INTEGER, b) + b.size # s) DO l := b; b := b.next END;
  1587. IF b # sentinel THEN
  1588. IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END
  1589. ELSE b := NIL
  1590. END;
  1591. INC(i)
  1592. UNTIL (b # NIL) OR (i = N);
  1593. RETURN b
  1594. END LastBlock;
  1595. PROCEDURE NewBlock (size: INTEGER): Block;
  1596. VAR tsize, a, s: INTEGER; b: FreeBlock; new, c: Cluster; r: Reducer;
  1597. BEGIN
  1598. tsize := (size + 19) DIV 16 * 16;
  1599. b := OldBlock(tsize); (* 1) search for free block *)
  1600. IF b = NIL THEN
  1601. IF dllMem THEN
  1602. FastCollect; b := OldBlock(tsize); (* 2) collect *)
  1603. IF b = NIL THEN
  1604. AllocHeapMem(tsize + 12, new); (* 3) allocate new cluster *)
  1605. IF new # NIL THEN
  1606. IF (root = NIL) OR (SYSTEM.VAL(INTEGER, new) < SYSTEM.VAL(INTEGER, root)) THEN
  1607. new.next := root; root := new
  1608. ELSE
  1609. c := root;
  1610. WHILE (c.next # NIL) & (SYSTEM.VAL(INTEGER, new) > SYSTEM.VAL(INTEGER, c.next)) DO
  1611. c := c.next
  1612. END;
  1613. new.next := c.next; c.next := new
  1614. END;
  1615. b := SYSTEM.VAL(FreeBlock, SYSTEM.VAL(INTEGER, new) + 12);
  1616. b.size := (new.size - 12) DIV 16 * 16 - 4
  1617. ELSE
  1618. RETURN NIL (* 4) give up *)
  1619. END
  1620. END
  1621. ELSE
  1622. FastCollect; (* 2) collect *)
  1623. IF (b = NIL) & (HeapFull(tsize)) & (reducers # NIL) THEN (* 3) little space => reduce once *)
  1624. r := reducers; reducers := NIL;
  1625. WHILE r # NIL DO r.Reduce(FALSE); r := r.next END;
  1626. Collect
  1627. END;
  1628. s := 3 * (allocated + tsize) DIV 2;
  1629. a := 12 + (root.size - 12) DIV 16 * 16;
  1630. IF s <= total THEN
  1631. b := OldBlock(tsize);
  1632. IF b = NIL THEN s := a + tsize END
  1633. ELSIF s < a + tsize THEN
  1634. s := a + tsize
  1635. END;
  1636. IF total < s THEN (* 4) enlarge heap *)
  1637. GrowHeapMem(s, root);
  1638. IF root.size >= s THEN
  1639. b := LastBlock(SYSTEM.VAL(INTEGER, root) + a);
  1640. IF b # NIL THEN
  1641. b.size := (root.size - a + b.size + 4) DIV 16 * 16 - 4
  1642. ELSE
  1643. b := SYSTEM.VAL(FreeBlock, SYSTEM.VAL(INTEGER, root) + a);
  1644. b.size := (root.size - a) DIV 16 * 16 - 4
  1645. END
  1646. ELSIF reducers # NIL THEN (* 5) no space => fully reduce *)
  1647. r := reducers; reducers := NIL;
  1648. WHILE r # NIL DO r.Reduce(TRUE); r := r.next END;
  1649. Collect
  1650. END
  1651. END;
  1652. IF b = NIL THEN
  1653. b := OldBlock(tsize);
  1654. IF b = NIL THEN RETURN NIL END (* 6) give up *)
  1655. END
  1656. END
  1657. END;
  1658. (* b # NIL *)
  1659. a := b.size + 4 - tsize;
  1660. IF a > 0 THEN Insert(SYSTEM.VAL(FreeBlock, SYSTEM.VAL(INTEGER, b) + tsize), a) END;
  1661. IF size > 0 THEN Erase(SYSTEM.ADR(b.size), (size + 3) DIV 4) END;
  1662. INC(allocated, tsize);
  1663. RETURN SYSTEM.VAL(Block, b)
  1664. END NewBlock;
  1665. (*
  1666. PROCEDURE NewBlock (size: INTEGER): Block;
  1667. VAR tsize, a, s: INTEGER; b: FreeBlock; new, c: Cluster; r: Reducer;
  1668. BEGIN
  1669. tsize := (size + 19) DIV 16 * 16;
  1670. b := OldBlock(tsize); (* 1) search for free block *)
  1671. IF b = NIL THEN
  1672. (*FastCollect;*) b := OldBlock(tsize); (* 2) collect *)
  1673. IF b = NIL THEN
  1674. AllocHeapMem(tsize + 12, new); (* 3) allocate new cluster *)
  1675. IF new # NIL THEN
  1676. IF (root = NIL) OR (SYSTEM.VAL(INTEGER, new) < SYSTEM.VAL(INTEGER, root)) THEN
  1677. new.next := root; root := new
  1678. ELSE
  1679. c := root;
  1680. WHILE (c.next # NIL) & (SYSTEM.VAL(INTEGER, new) > SYSTEM.VAL(INTEGER, c.next)) DO
  1681. c := c.next
  1682. END;
  1683. new.next := c.next; c.next := new
  1684. END;
  1685. b := SYSTEM.VAL(FreeBlock, SYSTEM.VAL(INTEGER, new) + 12);
  1686. b.size := (new.size - 12) DIV 16 * 16 - 4
  1687. ELSE
  1688. RETURN NIL (* 4) give up *)
  1689. END
  1690. END
  1691. END;
  1692. (* b # NIL *)
  1693. a := b.size + 4 - tsize;
  1694. IF a > 0 THEN Insert(SYSTEM.VAL(FreeBlock, SYSTEM.VAL(INTEGER, b) + tsize), a) END;
  1695. IF size > 0 THEN Erase(SYSTEM.ADR(b.size), (size + 3) DIV 4) END;
  1696. INC(allocated, tsize);
  1697. RETURN SYSTEM.VAL(Block, b)
  1698. END NewBlock;
  1699. *)
  1700. PROCEDURE Allocated* (): INTEGER;
  1701. BEGIN
  1702. RETURN allocated
  1703. END Allocated;
  1704. PROCEDURE Used* (): INTEGER;
  1705. BEGIN
  1706. RETURN used
  1707. END Used;
  1708. PROCEDURE Root* (): INTEGER;
  1709. BEGIN
  1710. RETURN SYSTEM.VAL(INTEGER, root)
  1711. END Root;
  1712. (* -------------------- Trap Handling --------------------- *)
  1713. PROCEDURE^ InitFpu;
  1714. PROCEDURE Start* (code: Command);
  1715. BEGIN
  1716. restart := code;
  1717. res := LinLibc.sigsetjmp(loopContext, LinLibc.TRUE);
  1718. restart()
  1719. END Start;
  1720. PROCEDURE Quit* (exitCode: INTEGER);
  1721. VAR m: Module; term: Command; t: BOOLEAN; res: INTEGER;
  1722. BEGIN
  1723. trapViewer := NIL; trapChecker := NIL; restart := NIL;
  1724. t := terminating; terminating := TRUE; m := modList;
  1725. WHILE m # NIL DO (* call terminators *)
  1726. IF ~static OR ~t THEN
  1727. term := m.term; m.term := NIL;
  1728. IF term # NIL THEN term() END
  1729. END;
  1730. (*
  1731. ReleaseIPtrs(m);
  1732. *)
  1733. m := m.next
  1734. END;
  1735. CallFinalizers;
  1736. hotFinalizers := finalizers; finalizers := NIL;
  1737. CallFinalizers;
  1738. (*
  1739. WinOle.OleUninitialize();
  1740. *)
  1741. (*
  1742. IF ~inDll THEN
  1743. KERNEL32.RemoveExcp(excpPtr^);
  1744. KERNEL32.ExitProcess(exitCode) (* never returns *)
  1745. END
  1746. *)
  1747. res := LinLibc.fflush(0);
  1748. LinLibc.exit(exitCode)
  1749. END Quit;
  1750. PROCEDURE FatalError* (id: INTEGER; str: ARRAY OF CHAR);
  1751. VAR res: INTEGER; title: ARRAY 16 OF SHORTCHAR; text: ARRAY 256 OF SHORTCHAR;
  1752. BEGIN
  1753. title := "Error xy";
  1754. title[6] := SHORT(CHR(id DIV 10 + ORD("0")));
  1755. title[7] := SHORT(CHR(id MOD 10 + ORD("0")));
  1756. text := SHORT(str$);
  1757. res := MessageBox(title$, text$, {mbOk});
  1758. (*
  1759. WinOle.OleUninitialize();
  1760. *)
  1761. (*
  1762. IF ~inDll THEN KERNEL32.RemoveExcp(excpPtr^) END;
  1763. KERNEL32.ExitProcess(1)
  1764. *)
  1765. LinLibc.exit(1);
  1766. (* never returns *)
  1767. END FatalError;
  1768. PROCEDURE DefaultTrapViewer;
  1769. VAR len, ref, end, x, a, b, c: INTEGER; mod: Module;
  1770. name: Name; out: ARRAY 1024 OF SHORTCHAR;
  1771. PROCEDURE WriteString (s: ARRAY OF SHORTCHAR);
  1772. VAR i: INTEGER;
  1773. BEGIN
  1774. i := 0;
  1775. WHILE (len < LEN(out) - 1) & (s[i] # 0X) DO out[len] := s[i]; INC(i); INC(len) END
  1776. END WriteString;
  1777. PROCEDURE WriteHex (x, n: INTEGER);
  1778. VAR i, y: INTEGER;
  1779. BEGIN
  1780. IF len + n < LEN(out) THEN
  1781. i := len + n - 1;
  1782. WHILE i >= len DO
  1783. y := x MOD 16; x := x DIV 16;
  1784. IF y > 9 THEN y := y + (ORD("A") - ORD("0") - 10) END;
  1785. out[i] := SHORT(CHR(y + ORD("0"))); DEC(i)
  1786. END;
  1787. INC(len, n)
  1788. END
  1789. END WriteHex;
  1790. PROCEDURE WriteLn;
  1791. BEGIN
  1792. IF len < LEN(out) - 1 THEN out[len] := 0AX (* 0DX on Windows *); INC(len) END
  1793. END WriteLn;
  1794. BEGIN
  1795. len := 0;
  1796. IF err = 129 THEN WriteString("invalid with")
  1797. ELSIF err = 130 THEN WriteString("invalid case")
  1798. ELSIF err = 131 THEN WriteString("function without return")
  1799. ELSIF err = 132 THEN WriteString("type guard")
  1800. ELSIF err = 133 THEN WriteString("implied type guard")
  1801. ELSIF err = 134 THEN WriteString("value out of range")
  1802. ELSIF err = 135 THEN WriteString("index out of range")
  1803. ELSIF err = 136 THEN WriteString("string too long")
  1804. ELSIF err = 137 THEN WriteString("stack overflow")
  1805. ELSIF err = 138 THEN WriteString("integer overflow")
  1806. ELSIF err = 139 THEN WriteString("division by zero")
  1807. ELSIF err = 140 THEN WriteString("infinite real result")
  1808. ELSIF err = 141 THEN WriteString("real underflow")
  1809. ELSIF err = 142 THEN WriteString("real overflow")
  1810. ELSIF err = 143 THEN WriteString("undefined real result")
  1811. ELSIF err = 200 THEN WriteString("keyboard interrupt")
  1812. ELSIF err = 202 THEN WriteString("illegal instruction: ");
  1813. WriteHex(val, 4)
  1814. ELSIF err = 203 THEN WriteString("illegal memory read [ad = ");
  1815. WriteHex(val, 8); WriteString("]")
  1816. ELSIF err = 204 THEN WriteString("illegal memory write [ad = ");
  1817. WriteHex(val, 8); WriteString("]")
  1818. ELSIF err = 205 THEN WriteString("illegal execution [ad = ");
  1819. WriteHex(val, 8); WriteString("]")
  1820. ELSIF err < 0 THEN WriteString("exception #"); WriteHex(-err, 2)
  1821. ELSE err := err DIV 100 * 256 + err DIV 10 MOD 10 * 16 + err MOD 10;
  1822. WriteString("trap #"); WriteHex(err, 3)
  1823. END;
  1824. a := pc; b := fp; c := 12;
  1825. REPEAT
  1826. WriteLn; WriteString("- ");
  1827. mod := modList;
  1828. WHILE (mod # NIL) & ((a < mod.code) OR (a >= mod.code + mod.csize)) DO mod := mod.next END;
  1829. IF mod # NIL THEN
  1830. DEC(a, mod.code);
  1831. IF mod.refcnt >= 0 THEN
  1832. WriteString(mod.name); ref := mod.refs;
  1833. REPEAT GetRefProc(ref, end, name) UNTIL (end = 0) OR (a < end);
  1834. IF a < end THEN
  1835. WriteString("."); WriteString(name)
  1836. END
  1837. ELSE
  1838. WriteString("("); WriteString(mod.name); WriteString(")")
  1839. END;
  1840. WriteString(" ")
  1841. END;
  1842. WriteString("(pc="); WriteHex(a, 8);
  1843. WriteString(", fp="); WriteHex(b, 8); WriteString(")");
  1844. IF (b >= sp) & (b < stack) THEN
  1845. SYSTEM.GET(b+4, a); (* stacked pc *)
  1846. SYSTEM.GET(b, b); (* dynamic link *)
  1847. DEC(c)
  1848. ELSE c := 0
  1849. END
  1850. UNTIL c = 0;
  1851. out[len] := 0X;
  1852. x := MessageBox("BlackBox", out$, {mbOk})
  1853. END DefaultTrapViewer;
  1854. PROCEDURE TrapCleanup;
  1855. VAR t: TrapCleaner;
  1856. BEGIN
  1857. WHILE trapStack # NIL DO
  1858. t := trapStack; trapStack := trapStack.next; t.Cleanup
  1859. END;
  1860. IF (trapChecker # NIL) & (err # 128) THEN trapChecker END
  1861. END TrapCleanup;
  1862. (*
  1863. PROCEDURE Unwind(f: KERNEL32.ExcpFrmPtr); (* COMPILER DEPENDENT *)
  1864. CONST Label = 27; (* offset of Label: from proc start *)
  1865. BEGIN
  1866. PushFP;
  1867. KERNEL32.RtlUnwind(f, SYSTEM.ADR(Unwind) + Label, NIL, 0);
  1868. (* Label: *)
  1869. PopFP
  1870. END Unwind;
  1871. *)
  1872. (*
  1873. PROCEDURE TrapHandler (excpRec: KERNEL32.ExcpRecPtr; estFrame: KERNEL32.ExcpFrmPtr;
  1874. context: KERNEL32.ContextPtr; dispCont: INTEGER): INTEGER;
  1875. (* same parameter size as Try *)
  1876. BEGIN
  1877. IF excpRec^.flags * {1, 2} = {} THEN
  1878. IF (excpRec.code MOD 256 = 4) & ~interrupted THEN (* wrong trace trap *)
  1879. context.debug[5] := 0; (* disable all debug traps *)
  1880. LdSP8; PopSI; PopDI; PopFP; (* COMPILER DEPENDENT *)
  1881. Return0(0) (* return continueExecution without parameter remove *)
  1882. END;
  1883. Unwind(estFrame);
  1884. IF trapped & (excpRec.code MOD 256 # 1) & (excpRec.code MOD 256 # 253) THEN
  1885. DefaultTrapViewer;
  1886. IF ~secondTrap THEN trapped := FALSE; secondTrap := TRUE END
  1887. END;
  1888. err := -(excpRec.code MOD 256);
  1889. pc := context.ip; sp := context.sp; fp := context.bp; stack := baseStack;
  1890. IF err = -4 THEN err := 200 (* keyboard interrupt *)
  1891. ELSIF err = -5 THEN
  1892. val := excpRec.info[1];
  1893. IF val = pc THEN (* call to undef adr *)
  1894. err := 205; SYSTEM.GET(sp, pc); INC(sp, 4); DEC(pc)
  1895. ELSIF excpRec.info[0] = 0 THEN (* illegal read *)
  1896. err := 203
  1897. ELSE (* illegal write *)
  1898. err := 204
  1899. END
  1900. ELSIF (err = -29) OR (err = -30) THEN (* illegal instruction *)
  1901. err := 202; val := 0;
  1902. IF IsReadable(excpRec.adr, excpRec.adr + 4) THEN
  1903. SYSTEM.GET(excpRec.adr, val);
  1904. IF val MOD 100H = 8DH THEN (* lea reg,reg *)
  1905. IF val DIV 100H MOD 100H = 0F0H THEN
  1906. err := val DIV 10000H MOD 100H (* trap *)
  1907. ELSIF val DIV 1000H MOD 10H = 0EH THEN
  1908. err := 128 + val DIV 100H MOD 10H (* run time error *)
  1909. END
  1910. END
  1911. END
  1912. ELSIF err = -142 THEN DEC(pc); err := 140 (* fpu: div by zero *)
  1913. ELSIF (err = -144) OR (err = -146) THEN DEC(pc); err := 143 ; (* fpu: invalid op *)
  1914. val := context.float[0] MOD 4096 * 65536 + context.float[1] MOD 65536
  1915. ELSIF err = -145 THEN DEC(pc); err := 142 (* fpu: overflow *)
  1916. ELSIF err = -147 THEN DEC(pc); err := 141 (* fpu: underflow *)
  1917. ELSIF err = -148 THEN err := 139 (* division by zero *)
  1918. ELSIF err = -149 THEN err := 138 (* integer overflow *)
  1919. ELSIF (err = -1) OR (err = -253) THEN err := 137 (* stack overflow *)
  1920. END;
  1921. INC(trapCount);
  1922. InitFpu;
  1923. IF err # 137 THEN (* stack overflow handling is delayed *)
  1924. TrapCleanup;
  1925. IF err = 128 THEN (* do nothing *)
  1926. ELSIF(trapViewer # NIL) & (restart # NIL) & ~trapped & ~guarded THEN
  1927. trapped := TRUE; trapViewer()
  1928. ELSE DefaultTrapViewer
  1929. END
  1930. END;
  1931. trapped := FALSE; secondTrap := FALSE;
  1932. IF dispCont = 0 THEN (* InterfaceTrapHandler *) (* COMPILER DEPENDENT *)
  1933. KERNEL32.RemoveExcp(estFrame^);
  1934. SYSTEM.PUTREG(CX, estFrame(ExcpFramePtr).par);
  1935. SYSTEM.PUTREG(SP, SYSTEM.VAL(INTEGER, estFrame) + 12);
  1936. IF err = 137 THEN (* retrigger stack overflow *)
  1937. TrapCleanup; DefaultTrapViewer;
  1938. res := KERNEL32.VirtualProtect(FPageWord(8), 1024, {2, 8}, old);
  1939. IF res = 0 THEN res := KERNEL32.VirtualProtect(FPageWord(8), 1024, {0}, old) END
  1940. END;
  1941. PopSI; PopDI; PopBX; PopFP;
  1942. ReturnCX(WinApi.E_UNEXPECTED)
  1943. ELSIF estFrame # excpPtr THEN (* Try failed *) (* COMPILER DEPENDENT *)
  1944. KERNEL32.RemoveExcp(estFrame^);
  1945. res := SYSTEM.VAL(INTEGER, estFrame);
  1946. SYSTEM.PUTREG(FP, res + (SIZE(KERNEL32.ExcpFrm) + 8)); (* restore fp *)
  1947. SYSTEM.PUTREG(SP, res - 4); (* restore stack *)
  1948. IF err = 137 THEN (* retrigger stack overflow *)
  1949. TrapCleanup; DefaultTrapViewer;
  1950. res := KERNEL32.VirtualProtect(FPageWord(8), 1024, {2, 8}, old);
  1951. IF res = 0 THEN res := KERNEL32.VirtualProtect(FPageWord(8), 1024, {0}, old) END
  1952. END;
  1953. PopBX;
  1954. RETURN 0 (* return from Try *)
  1955. ELSIF restart # NIL THEN (* Start failed *)
  1956. SYSTEM.PUTREG(FP, baseStack); (* restore fp *)
  1957. SYSTEM.PUTREG(SP, baseStack); (* restore stack *)
  1958. IF err = 137 THEN (* retrigger stack overflow *)
  1959. TrapCleanup; DefaultTrapViewer;
  1960. res := KERNEL32.VirtualProtect(FPageWord(8), 1024, {2, 8}, old);
  1961. IF res = 0 THEN res := KERNEL32.VirtualProtect(FPageWord(8), 1024, {0}, old) END
  1962. END;
  1963. restart();
  1964. Quit(1)
  1965. ELSE (* boot process failed *)
  1966. Quit(1)
  1967. END
  1968. (* never returns *)
  1969. ELSE
  1970. LdSP8; PopSI; PopDI; PopFP; (* COMPILER DEPENDENT *)
  1971. Return0(1) (* return continueSearch without parameter remove *)
  1972. END
  1973. END TrapHandler;
  1974. *)
  1975. PROCEDURE SetTrapGuard* (on: BOOLEAN);
  1976. BEGIN
  1977. guarded := on
  1978. END SetTrapGuard;
  1979. (*
  1980. PROCEDURE Try* (h: TryHandler; a, b, c: INTEGER); (* COMPILER DEPENDENT *)
  1981. (* same parameter size as TrapHandler *)
  1982. VAR excp: KERNEL32.ExcpFrm; (* no other local variables! *)
  1983. BEGIN
  1984. PushBX;
  1985. excp.handler := TrapHandler;
  1986. KERNEL32.InstallExcp(excp);
  1987. h(a, b, c);
  1988. KERNEL32.RemoveExcp(excp);
  1989. PopBX
  1990. END Try;
  1991. *)
  1992. PROCEDURE Try* (h: TryHandler; a, b, c: INTEGER);
  1993. VAR res: INTEGER; context: LinLibc.sigjmp_buf; oldContext: POINTER TO LinLibc.sigjmp_buf;
  1994. BEGIN
  1995. oldContext := currentTryContext;
  1996. res := LinLibc.sigsetjmp(context, LinLibc.TRUE);
  1997. currentTryContext := SYSTEM.ADR(context);
  1998. IF res = 0 THEN (* first time around *)
  1999. h(a, b, c);
  2000. ELSIF res = trapReturn THEN (* after a trap *)
  2001. ELSE
  2002. HALT(100)
  2003. END;
  2004. currentTryContext := oldContext;
  2005. END Try;
  2006. PROCEDURE InterfaceTrapHandler* (excpRec, estFrame, context, dispCont: INTEGER): INTEGER;
  2007. (* known to compiler *)
  2008. VAR res: INTEGER;
  2009. BEGIN
  2010. (*
  2011. res := TrapHandler(SYSTEM.VAL(KERNEL32.ExcpRecPtr, excpRec),
  2012. SYSTEM.VAL(KERNEL32.ExcpFrmPtr, estFrame),
  2013. SYSTEM.VAL(KERNEL32.ContextPtr, context),
  2014. 0);
  2015. (* LdSP8 removes parameters of TrapHandler *)
  2016. LdSP8; PopSI; PopDI; PopFP; (* COMPILER DEPENDENT *)
  2017. Return0(1); (* return continueSearch without parameter remove *)
  2018. IF FALSE THEN RETURN 0 END
  2019. *)
  2020. RETURN 0
  2021. END InterfaceTrapHandler;
  2022. (* -------------------- keyboard interrupt handling --------------------- *)
  2023. (*
  2024. PROCEDURE KeyboardWatcher (main: INTEGER): INTEGER; (* runs in a thread *)
  2025. VAR res, id, a, to: INTEGER; msg: USER32.Message; wnd: USER32.Handle;
  2026. context: KERNEL32.Context; mod: Module;
  2027. BEGIN
  2028. wnd := USER32.CreateWindowExA({}, "Edit", "", {}, 0, 0, 0, 0, 0, 0, KERNEL32.GetModuleHandleA(NIL), 0);
  2029. res := USER32.RegisterHotKey(wnd, 13, {1}, 3); (* ctrl break *)
  2030. IF res = 0 THEN
  2031. res := USER32.RegisterHotKey(wnd, 14, {1, 2}, 3) (* shift ctrl break *)
  2032. END;
  2033. LOOP
  2034. res := USER32.GetMessageA(msg, 0, 0, 0);
  2035. IF msg.message = USER32.WMHotKey THEN
  2036. wnd := USER32.GetForegroundWindow();
  2037. res := USER32.GetWindowThreadProcessId(wnd, id);
  2038. IF (msg.wParam = 14) OR (id = KERNEL32.GetCurrentProcessId()) THEN
  2039. to := KERNEL32.GetTickCount() + 1000; (* 1 sec timeout *)
  2040. REPEAT
  2041. res := KERNEL32.SuspendThread(main);
  2042. context.flags := {0, 16};
  2043. res := KERNEL32.GetThreadContext(main, context);
  2044. mod := modList; a := context.ip;
  2045. WHILE (mod # NIL) & ((a < mod.code) OR (a >= mod.code + mod.csize)) DO
  2046. mod := mod.next
  2047. END;
  2048. IF (mod # NIL) & (mod.name = "Kernel") THEN mod := NIL END;
  2049. IF mod # NIL THEN
  2050. interrupted := TRUE;
  2051. INCL(SYSTEM.VAL(SET, context.pf), 8); (* set trap flag *)
  2052. res := KERNEL32.SetThreadContext(main, context)
  2053. END;
  2054. res := KERNEL32.ResumeThread(main);
  2055. KERNEL32.Sleep(0);
  2056. interrupted := FALSE
  2057. UNTIL (mod # NIL) OR (KERNEL32.GetTickCount() > to)
  2058. END
  2059. END
  2060. END;
  2061. RETURN 0
  2062. END KeyboardWatcher;
  2063. *)
  2064. (*
  2065. PROCEDURE InstallKeyboardInt;
  2066. VAR res, id: INTEGER; t, main: KERNEL32.Handle;
  2067. BEGIN
  2068. res := KERNEL32.DuplicateHandle(KERNEL32.GetCurrentProcess(), KERNEL32.GetCurrentThread(),
  2069. KERNEL32.GetCurrentProcess(), main, {1, 3, 4, 16..19}, 0, {});
  2070. t := KERNEL32.CreateThread(NIL, 4096, KeyboardWatcher, main, {}, id)
  2071. END InstallKeyboardInt;
  2072. *)
  2073. (* -------------------- Initialization --------------------- *)
  2074. PROCEDURE InitFpu; (* COMPILER DEPENDENT *)
  2075. (* could be eliminated, delayed for backward compatibility *)
  2076. VAR cw: SET;
  2077. BEGIN
  2078. FINIT;
  2079. FSTCW;
  2080. (* denorm, underflow, precision, zero div, overflow masked *)
  2081. (* invalid trapped *)
  2082. (* round to nearest, temp precision *)
  2083. cw := cw - {0..5, 8..11} + {1, 2, 3, 4, 5, 8, 9};
  2084. FLDCW
  2085. END InitFpu;
  2086. (* A. V. Shiryaev *)
  2087. (* show extended trap information *)
  2088. PROCEDURE ShowTrap (sig: INTEGER; siginfo: LinLibc.Ptrsiginfo_t; context: LinLibc.Ptrucontext_t);
  2089. PROCEDURE WriteChar (c: SHORTCHAR);
  2090. VAR s: ARRAY [untagged] 2 OF SHORTCHAR;
  2091. BEGIN
  2092. s[0] := c; s[1] := 0X;
  2093. res := LinLibc.printf(s)
  2094. END WriteChar;
  2095. PROCEDURE WriteString (s: ARRAY OF SHORTCHAR);
  2096. VAR res: INTEGER;
  2097. BEGIN
  2098. res := LinLibc.printf(s)
  2099. END WriteString;
  2100. PROCEDURE WriteHex (x, n: INTEGER);
  2101. VAR i, y: INTEGER;
  2102. s: ARRAY 9 OF SHORTCHAR;
  2103. BEGIN
  2104. s[n] := 0X;
  2105. i := 0 + n - 1;
  2106. WriteChar("$");
  2107. WHILE i >= 0 DO
  2108. y := x MOD 16; x := x DIV 16;
  2109. IF y > 9 THEN y := y + (ORD("A") - ORD("0") - 10) END;
  2110. s[i] := SHORT(CHR(y + ORD("0")));
  2111. DEC(i)
  2112. END;
  2113. WriteString(s)
  2114. END WriteHex;
  2115. PROCEDURE WriteLn;
  2116. BEGIN
  2117. WriteChar(0AX)
  2118. END WriteLn;
  2119. PROCEDURE KV (name: ARRAY OF SHORTCHAR; x: INTEGER);
  2120. BEGIN
  2121. WriteString(name); WriteString(" = "); WriteHex(x, 8)
  2122. END KV;
  2123. BEGIN
  2124. WriteString("================================"); WriteLn;
  2125. WriteString("TRAP:"); WriteLn;
  2126. WriteString("--------------------------------"); WriteLn;
  2127. KV("sig", sig); WriteString(", ");
  2128. KV("baseStack", baseStack); WriteLn;
  2129. KV("GS ", context.sc_gs); WriteString(", ");
  2130. KV("FS ", context.sc_fs); WriteString(", ");
  2131. KV("ES ", context.sc_es); WriteString(", ");
  2132. KV("DS ", context.sc_ds); WriteLn;
  2133. KV("EDI", context.sc_edi); WriteString(", ");
  2134. KV("ESI", context.sc_esi); WriteString(", ");
  2135. KV("EBP", context.sc_ebp); WriteString(", ");
  2136. KV("EBX", context.sc_ebx); WriteLn;
  2137. KV("EDX", context.sc_edx); WriteString(", ");
  2138. KV("ECX", context.sc_ecx); WriteString(", ");
  2139. KV("EAX", context.sc_eax); WriteString(", ");
  2140. KV("EIP", context.sc_eip); WriteLn;
  2141. KV("CS", context.sc_cs); WriteString(", ");
  2142. KV("EFLAGS", context.sc_eflags); WriteString(", ");
  2143. KV("ESP", context.sc_esp); WriteString(", ");
  2144. KV("SS", context.sc_ss); WriteLn;
  2145. KV("ONSTACK", context.sc_onstack); WriteString(", ");
  2146. KV("MASK", context.sc_mask); WriteString(", ");
  2147. KV("TRAPNO", context.sc_trapno); WriteString(", ");
  2148. KV("ERR", context.sc_err); WriteLn;
  2149. (* WriteString("--------------------------------"); WriteLn; *)
  2150. (* TODO: show siginfo *)
  2151. WriteString("================================"); WriteLn
  2152. END ShowTrap;
  2153. PROCEDURE TrapHandler (sig: INTEGER; siginfo: LinLibc.Ptrsiginfo_t; context: LinLibc.Ptrucontext_t);
  2154. BEGIN
  2155. (*
  2156. SYSTEM.GETREG(SP, sp);
  2157. SYSTEM.GETREG(FP, fp);
  2158. *)
  2159. stack := baseStack;
  2160. (* A. V. Shiryaev *)
  2161. ShowTrap(sig, siginfo, context);
  2162. (*
  2163. sp := context.uc_mcontext.gregs[7]; (* TODO: is the stack pointer really stored in register 7? *)
  2164. fp := context.uc_mcontext.gregs[6]; (* TODO: is the frame pointer really stored in register 6? *)
  2165. pc := context.uc_mcontext.gregs[14]; (* TODO: is the pc really stored in register 14? *)
  2166. *)
  2167. sp := context.sc_esp; fp := context.sc_ebp; pc := context.sc_eip;
  2168. (* val := siginfo.si_addr; *)
  2169. val := siginfo.si_pid; (* XXX *)
  2170. (*
  2171. Int(sig); Int(siginfo.si_signo); Int(siginfo.si_code); Int(siginfo.si_errno);
  2172. Int(siginfo.si_status); Int(siginfo.si_value); Int(siginfo.si_int);
  2173. *)
  2174. err := sig;
  2175. IF trapped THEN DefaultTrapViewer END;
  2176. CASE sig OF
  2177. LinLibc.SIGINT:
  2178. err := 200 (* Interrupt (ANSI). *)
  2179. | LinLibc.SIGILL: (* Illegal instruction (ANSI). *)
  2180. err := 202; val := 0;
  2181. IF IsReadable(pc, pc + 4) THEN
  2182. SYSTEM.GET(pc, val);
  2183. IF val MOD 100H = 8DH THEN (* lea reg,reg *)
  2184. IF val DIV 100H MOD 100H = 0F0H THEN
  2185. err := val DIV 10000H MOD 100H (* trap *)
  2186. ELSIF val DIV 1000H MOD 10H = 0EH THEN
  2187. err := 128 + val DIV 100H MOD 10H (* run time error *)
  2188. END
  2189. END
  2190. END
  2191. | LinLibc.SIGFPE:
  2192. CASE siginfo.si_code OF
  2193. 0: (* TODO: ?????? *)
  2194. (* A. V. Shiryaev *)
  2195. (*
  2196. IF siginfo.si_int = 8 THEN
  2197. err := 139
  2198. ELSIF siginfo.si_int = 0 THEN
  2199. err := 143
  2200. END
  2201. *)
  2202. err := 143;
  2203. | LinLibc.FPE_INTDIV: err := 139 (* Integer divide by zero. *)
  2204. | LinLibc.FPE_INTOVF: err := 138 (* Integer overflow. *)
  2205. | LinLibc.FPE_FLTDIV: err := 140 (* Floating point divide by zero. *)
  2206. | LinLibc.FPE_FLTOVF: err := 142 (* Floating point overflow. *)
  2207. | LinLibc.FPE_FLTUND: err := 141 (* Floating point underflow. *)
  2208. | LinLibc.FPE_FLTRES: err := 143 (* Floating point inexact result. *)
  2209. | LinLibc.FPE_FLTINV: err := 143 (* Floating point invalid operation. *)
  2210. | LinLibc.FPE_FLTSUB: err := 134 (* Subscript out of range. *)
  2211. ELSE
  2212. END
  2213. | LinLibc.SIGSEGV: (* Segmentation violation (ANSI). *)
  2214. err := 203
  2215. ELSE
  2216. END;
  2217. INC(trapCount);
  2218. InitFpu;
  2219. TrapCleanup;
  2220. IF err # 128 THEN
  2221. IF (trapViewer = NIL) OR trapped THEN
  2222. DefaultTrapViewer
  2223. ELSE
  2224. trapped := TRUE;
  2225. trapViewer();
  2226. trapped := FALSE
  2227. END
  2228. END;
  2229. IF currentTryContext # NIL THEN (* Try failed *)
  2230. LinLibc.siglongjmp(currentTryContext, trapReturn)
  2231. ELSE
  2232. IF restart # NIL THEN (* Start failed *)
  2233. LinLibc.siglongjmp(loopContext, trapReturn)
  2234. END;
  2235. Quit(1);
  2236. END;
  2237. trapped := FALSE
  2238. END TrapHandler;
  2239. PROCEDURE InstallSignals*;
  2240. VAR sa, old: LinLibc.sigaction_t; res, i: INTEGER;
  2241. BEGIN
  2242. sa.sa_sigaction := TrapHandler;
  2243. (*
  2244. res := LinLibc.sigemptyset(SYSTEM.ADR(sa.sa_mask));
  2245. *)
  2246. res := LinLibc.sigfillset(SYSTEM.ADR(sa.sa_mask));
  2247. sa.sa_flags := LinLibc.SA_SIGINFO; (* TrapHandler takes three arguments *)
  2248. (*
  2249. IF LinLibc.sigaction(LinLibc.SIGINT, sa, old) # 0 THEN Msg("failed to install SIGINT") END;
  2250. IF LinLibc.sigaction(LinLibc.SIGILL, sa, old) # 0 THEN Msg("failed to install SIGILL") END;
  2251. IF LinLibc.sigaction(LinLibc.SIGFPE, sa, old) # 0 THEN Msg("failed to install SIGFPE") END;
  2252. IF LinLibc.sigaction(LinLibc.SIGSEGV, sa, old) # 0 THEN Msg("failed to install SIGSEGV") END;
  2253. IF LinLibc.sigaction(LinLibc.SIGPIPE, sa, old) # 0 THEN Msg("failed to install SIGPIPE") END;
  2254. IF LinLibc.sigaction(LinLibc.SIGTERM, sa, old) # 0 THEN Msg("failed to install SIGTERM") END;
  2255. *)
  2256. (* respond to all possible signals *)
  2257. FOR i := 1 TO LinLibc._NSIG - 1 DO
  2258. IF (i # LinLibc.SIGKILL)
  2259. & (i # LinLibc.SIGSTOP)
  2260. & (i # LinLibc.SIGWINCH)
  2261. & (i # LinLibc.SIGTHR) (* A. V. Shiryaev: OpenBSD -pthread *)
  2262. THEN
  2263. IF LinLibc.sigaction(i, sa, old) # 0 THEN Msg("failed to install signal"); Int(i) END;
  2264. END
  2265. END
  2266. END InstallSignals;
  2267. PROCEDURE SetOpts;
  2268. VAR k: Module;
  2269. BEGIN
  2270. k := modList;
  2271. WHILE (k # NIL) & (k.name # "Kernel") DO k := k.next END;
  2272. ASSERT(k # NIL);
  2273. static := init IN k.opts;
  2274. inDll := dll IN k.opts
  2275. END SetOpts;
  2276. PROCEDURE SetCmdLine;
  2277. VAR i, l: INTEGER;
  2278. BEGIN
  2279. l := LEN(cmdLine);
  2280. cmdLine := bootInfo.argv[0]$;
  2281. FOR i := 1 TO bootInfo.argc - 1 DO cmdLine := cmdLine + " " + bootInfo.argv[i]END
  2282. END SetCmdLine;
  2283. PROCEDURE Init;
  2284. VAR (*excp: KERNEL32.ExcpFrm; *) t: Type; (*res: COM.RESULT; *) i: INTEGER;
  2285. env: LinLibc.jmp_buf; res: LONGINT;
  2286. BEGIN
  2287. InstallSignals; (* init exception handling *)
  2288. currentTryContext := NIL;
  2289. t := SYSTEM.VAL(Type, SYSTEM.ADR(Command)); (* type desc of Command *)
  2290. comSig := t.size; (* size = signature fprint for proc types *)
  2291. allocated := 0; total := 0; used := 0;
  2292. sentinelBlock.size := MAX(INTEGER);
  2293. sentinel := SYSTEM.ADR(sentinelBlock);
  2294. (* cdg/mf, 4.2.2004, dll support
  2295. SYSTEM.PUTREG(ML, SYSTEM.ADR(modList));
  2296. *)
  2297. IF dllMem THEN
  2298. i := N;
  2299. REPEAT DEC(i); free[i] := sentinel UNTIL i = 0;
  2300. root := NIL;
  2301. (*
  2302. heap := KERNEL32.GetProcessHeap()
  2303. *)
  2304. ELSE
  2305. i := N;
  2306. REPEAT DEC(i); free[i] := sentinel UNTIL i = 0;
  2307. AllocHeapMem(1, root); ASSERT(root # NIL, 100);
  2308. i := MIN(N - 1, (root.size - 12) DIV 16 - 1);
  2309. free[i] := SYSTEM.VAL(FreeBlock, SYSTEM.VAL(INTEGER, root) + 12);
  2310. free[i].next := sentinel;
  2311. free[i].size := (root.size - 12) DIV 16 * 16 - 4
  2312. END;
  2313. (*
  2314. res := WinOle.OleInitialize(0);
  2315. IF inDll THEN
  2316. baseStack := FPageWord(4) (* begin of stack segment *)
  2317. ELSE
  2318. InstallKeyboardInt;
  2319. InitFpu
  2320. END;
  2321. *)
  2322. InitFpu;
  2323. IF ~static THEN
  2324. InitModule(modList);
  2325. IF ~inDll THEN Quit(1) END
  2326. END;
  2327. told := 0; shift := 0;
  2328. END Init;
  2329. BEGIN
  2330. IF modList = NIL THEN (* only once *)
  2331. IF bootInfo # NIL THEN
  2332. modList := bootInfo.modList; (* boot loader initializes the bootInfo struct *)
  2333. SYSTEM.GETREG(SP, baseStack); (* TODO: Check that this is ok. *)
  2334. (* A. V. Shiryaev, 2012.09 *)
  2335. (* SetOpts; *)
  2336. static := init IN modList.opts;
  2337. inDll := dll IN modList.opts;
  2338. SetCmdLine
  2339. ELSE
  2340. SYSTEM.GETREG(ML, modList); (* linker loads module list to BX *)
  2341. SYSTEM.GETREG(SP, baseStack);
  2342. static := init IN modList.opts;
  2343. inDll := dll IN modList.opts;
  2344. END;
  2345. (*
  2346. dllMem := inDll;
  2347. *)
  2348. Init
  2349. END
  2350. CLOSE
  2351. IF ~terminating THEN
  2352. terminating := TRUE;
  2353. Quit(0)
  2354. END
  2355. END Kernel.
  2356. (!)DevDecoder.Decode Kernel