Kernel.txt 60 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155
  1. MODULE Kernel;
  2. (* THIS IS TEXT COPY OF Kernel.odc *)
  3. (* DO NOT EDIT *)
  4. (* A. V. Shiryaev, 2012.11
  5. OpenBSD Kernel
  6. Based on 1.6-rc6 Windows Kernel
  7. + 20120822 Marc changes
  8. Some parts taken from OpenBUGS linKernel
  9. Most Windows-specific code removed
  10. Some Windows-specific code commented and marked red
  11. Windows COM-specific code re-marked from green to gray
  12. OpenBSD(/Linux)-specific code marked green
  13. TODO:
  14. handle stack overflow exceptions
  15. Quit from TrapHandler
  16. *)
  17. IMPORT S := SYSTEM, Libc := LinLibc, Dl := LinDl;
  18. CONST
  19. strictStackSweep = TRUE;
  20. nameLen* = 256;
  21. littleEndian* = TRUE;
  22. timeResolution* = 1000; (* ticks per second *)
  23. processor* = 10; (* i386 *)
  24. objType* = "ocf"; (* file types *)
  25. symType* = "osf";
  26. docType* = "odc";
  27. (* loader constants *)
  28. done* = 0;
  29. fileNotFound* = 1;
  30. syntaxError* = 2;
  31. objNotFound* = 3;
  32. illegalFPrint* = 4;
  33. cyclicImport* = 5;
  34. noMem* = 6;
  35. commNotFound* = 7;
  36. commSyntaxError* = 8;
  37. moduleNotFound* = 9;
  38. any = 1000000;
  39. CX = 1;
  40. SP = 4; (* register number of stack pointer *)
  41. FP = 5; (* register number of frame pointer *)
  42. ML = 3; (* register which holds the module list at program start *)
  43. N = 128 DIV 16; (* free lists *)
  44. (* kernel flags in module desc *)
  45. init = 16; dyn = 17; dll = 24; iptrs = 30;
  46. (* meta interface consts *)
  47. mConst = 1; mTyp = 2; mVar = 3; mProc = 4; mField = 5;
  48. debug = FALSE;
  49. (*
  50. sigStackSize = MAX(Libc.SIGSTKSZ, 65536);
  51. *)
  52. trapReturn = 1; (* Return value for sigsetjmp given from siglongjmp *)
  53. (* constants for the message boxes *)
  54. mbClose* = -1; mbOk* = 0; mbCancel* =1; mbRetry* = 2; mbIgnore* = 3; mbYes* = 4; mbNo* = 5;
  55. TYPE
  56. Name* = ARRAY nameLen OF SHORTCHAR;
  57. Command* = PROCEDURE;
  58. Module* = POINTER TO RECORD [untagged]
  59. next-: Module;
  60. opts-: SET; (* 0..15: compiler opts, 16..31: kernel flags *)
  61. refcnt-: INTEGER; (* <0: module invalidated *)
  62. compTime-, loadTime-: ARRAY 6 OF SHORTINT;
  63. ext-: INTEGER; (* currently not used *)
  64. term-: Command; (* terminator *)
  65. nofimps-, nofptrs-: INTEGER;
  66. csize-, dsize-, rsize-: INTEGER;
  67. code-, data-, refs-: INTEGER;
  68. procBase-, varBase-: INTEGER; (* meta base addresses *)
  69. names-: POINTER TO ARRAY [untagged] OF SHORTCHAR; (* names[0] = 0X *)
  70. ptrs-: POINTER TO ARRAY [untagged] OF INTEGER;
  71. imports-: POINTER TO ARRAY [untagged] OF Module;
  72. export-: Directory; (* exported objects (name sorted) *)
  73. name-: Name
  74. END;
  75. Type* = POINTER TO RECORD [untagged]
  76. (* record: ptr to method n at offset - 4 * (n+1) *)
  77. size-: INTEGER; (* record: size, array: #elem, dyn array: 0, proc: sigfp *)
  78. mod-: Module;
  79. id-: INTEGER; (* name idx * 256 + lev * 16 + attr * 4 + form *)
  80. base-: ARRAY 16 OF Type; (* signature if form = ProcTyp *)
  81. fields-: Directory; (* new fields (declaration order) *)
  82. ptroffs-: ARRAY any OF INTEGER (* array of any length *)
  83. END;
  84. Object* = POINTER TO ObjDesc;
  85. ObjDesc* = RECORD [untagged]
  86. fprint-: INTEGER;
  87. offs-: INTEGER; (* pvfprint for record types *)
  88. id-: INTEGER; (* name idx * 256 + vis * 16 + mode *)
  89. struct-: Type (* id of basic type or pointer to typedesc/signature *)
  90. END;
  91. Directory* = POINTER TO RECORD [untagged]
  92. num-: INTEGER; (* number of entries *)
  93. obj-: ARRAY any OF ObjDesc (* array of any length *)
  94. END;
  95. Signature* = POINTER TO RECORD [untagged]
  96. retStruct-: Type; (* id of basic type or pointer to typedesc or 0 *)
  97. num-: INTEGER; (* number of parameters *)
  98. par-: ARRAY any OF RECORD [untagged] (* parameters *)
  99. id-: INTEGER; (* name idx * 256 + kind *)
  100. struct-: Type (* id of basic type or pointer to typedesc *)
  101. END
  102. END;
  103. Handler* = PROCEDURE;
  104. Reducer* = POINTER TO ABSTRACT RECORD
  105. next: Reducer
  106. END;
  107. Identifier* = ABSTRACT RECORD
  108. typ*: INTEGER;
  109. obj-: ANYPTR
  110. END;
  111. TrapCleaner* = POINTER TO ABSTRACT RECORD
  112. next: TrapCleaner
  113. END;
  114. TryHandler* = PROCEDURE (a, b, c: INTEGER);
  115. (* meta extension suport *)
  116. ItemExt* = POINTER TO ABSTRACT RECORD END;
  117. ItemAttr* = RECORD
  118. obj*, vis*, typ*, adr*: INTEGER;
  119. mod*: Module;
  120. desc*: Type;
  121. ptr*: S.PTR;
  122. ext*: ItemExt
  123. END;
  124. Hook* = POINTER TO ABSTRACT RECORD END;
  125. LoaderHook* = POINTER TO ABSTRACT RECORD (Hook)
  126. res*: INTEGER;
  127. importing*, imported*, object*: ARRAY 256 OF CHAR
  128. END;
  129. GuiHook* = POINTER TO ABSTRACT RECORD (Hook) END; (* Implemented by HostGnome *)
  130. Block = POINTER TO RECORD [untagged]
  131. tag: Type;
  132. last: INTEGER; (* arrays: last element *)
  133. actual: INTEGER; (* arrays: used during mark phase *)
  134. first: INTEGER (* arrays: first element *)
  135. END;
  136. FreeBlock = POINTER TO FreeDesc;
  137. FreeDesc = RECORD [untagged]
  138. tag: Type; (* f.tag = ADR(f.size) *)
  139. size: INTEGER;
  140. next: FreeBlock
  141. END;
  142. Cluster = POINTER TO RECORD [untagged]
  143. size: INTEGER; (* total size *)
  144. next: Cluster;
  145. max: INTEGER
  146. (* start of first block *)
  147. END;
  148. FList = POINTER TO RECORD
  149. next: FList;
  150. blk: Block;
  151. iptr, aiptr: BOOLEAN
  152. END;
  153. CList = POINTER TO RECORD
  154. next: CList;
  155. do: Command;
  156. trapped: BOOLEAN
  157. END;
  158. PtrType = RECORD v: S.PTR END; (* used for array of pointer *)
  159. Char8Type = RECORD v: SHORTCHAR END;
  160. Char16Type = RECORD v: CHAR END;
  161. Int8Type = RECORD v: BYTE END;
  162. Int16Type = RECORD v: SHORTINT END;
  163. Int32Type = RECORD v: INTEGER END;
  164. Int64Type = RECORD v: LONGINT END;
  165. BoolType = RECORD v: BOOLEAN END;
  166. SetType = RECORD v: SET END;
  167. Real32Type = RECORD v: SHORTREAL END;
  168. Real64Type = RECORD v: REAL END;
  169. ProcType = RECORD v: PROCEDURE END;
  170. UPtrType = RECORD v: INTEGER END;
  171. StrPtr = POINTER TO ARRAY [untagged] OF SHORTCHAR;
  172. (* Linux specific boot loader info. Record must be identical to struct in the loader. *)
  173. BootInfo* = POINTER TO RECORD [untagged]
  174. modList: Module;
  175. argc-: INTEGER;
  176. argv-: Libc.StrArray
  177. END;
  178. VAR
  179. baseStack: INTEGER; (* modList, root, and baseStack must be together for remote debugging *)
  180. root: Cluster; (* cluster list *)
  181. modList-: Module; (* root of module list *)
  182. trapCount-: INTEGER;
  183. err-, pc-, sp-, fp-, stack-, val-: INTEGER;
  184. free: ARRAY N OF FreeBlock; (* free list *)
  185. sentinelBlock: FreeDesc;
  186. sentinel: FreeBlock;
  187. candidates: ARRAY 1024 OF INTEGER;
  188. nofcand: INTEGER;
  189. allocated: INTEGER; (* bytes allocated on BlackBox heap *)
  190. total: INTEGER; (* current total size of BlackBox heap *)
  191. used: INTEGER; (* bytes allocated on system heap *)
  192. finalizers: FList;
  193. hotFinalizers: FList;
  194. cleaners: CList;
  195. reducers: Reducer;
  196. trapStack: TrapCleaner;
  197. actual: Module; (* valid during module initialization *)
  198. res: INTEGER; (* auxiliary global variables used for trap handling *)
  199. old: INTEGER;
  200. trapViewer, trapChecker: Handler;
  201. trapped, guarded, secondTrap: BOOLEAN;
  202. interrupted: BOOLEAN;
  203. static, inDll, terminating: BOOLEAN;
  204. restart: Command;
  205. told, shift: INTEGER; (* used in Time() *)
  206. loader: LoaderHook;
  207. loadres: INTEGER;
  208. wouldFinalize: BOOLEAN;
  209. watcher*: PROCEDURE (event: INTEGER); (* for debugging *)
  210. (*
  211. sigStack: Libc.PtrVoid;
  212. *)
  213. loopContext: Libc.sigjmp_buf; (* trap return context, if no Kernel.Try has been used. *)
  214. currentTryContext: POINTER TO Libc.sigjmp_buf; (* trap return context, if Kernel.Try has been used. *)
  215. isReadableContext: Libc.sigjmp_buf; (* for IsReadable *)
  216. isReadableCheck: BOOLEAN;
  217. guiHook: GuiHook;
  218. (* !!! This variable has to be the last variable in the list. !!! *)
  219. bootInfo-: BootInfo;
  220. (* code procedures for fpu *)
  221. PROCEDURE [1] FINIT 0DBH, 0E3H;
  222. PROCEDURE [1] FLDCW 0D9H, 06DH, 0FCH; (* -4, FP *)
  223. PROCEDURE [1] FSTCW 0D9H, 07DH, 0FCH; (* -4, FP *)
  224. (* code procedure for memory erase *)
  225. PROCEDURE [code] Erase (adr, words: INTEGER)
  226. 089H, 0C7H, (* MOV EDI, EAX *)
  227. 031H, 0C0H, (* XOR EAX, EAX *)
  228. 059H, (* POP ECX *)
  229. 0F2H, 0ABH; (* REP STOS *)
  230. (* code procedure for stack allocate *)
  231. PROCEDURE [code] ALLOC (* argument in CX *)
  232. (*
  233. PUSH EAX
  234. ADD ECX,-5
  235. JNS L0
  236. XOR ECX,ECX
  237. L0: AND ECX,-4 (n-8+3)/4*4
  238. MOV EAX,ECX
  239. AND EAX,4095
  240. SUB ESP,EAX
  241. MOV EAX,ECX
  242. SHR EAX,12
  243. JEQ L2
  244. L1: PUSH 0
  245. SUB ESP,4092
  246. DEC EAX
  247. JNE L1
  248. L2: ADD ECX,8
  249. MOV EAX,[ESP,ECX,-4]
  250. PUSH EAX
  251. MOV EAX,[ESP,ECX,-4]
  252. SHR ECX,2
  253. RET
  254. *);
  255. PROCEDURE (VAR id: Identifier) Identified* (): BOOLEAN, NEW, ABSTRACT;
  256. PROCEDURE (r: Reducer) Reduce* (full: BOOLEAN), NEW, ABSTRACT;
  257. PROCEDURE (c: TrapCleaner) Cleanup*, NEW, EMPTY;
  258. (* meta extension suport *)
  259. PROCEDURE (e: ItemExt) Lookup* (name: ARRAY OF CHAR; VAR i: ANYREC), NEW, ABSTRACT;
  260. PROCEDURE (e: ItemExt) Index* (index: INTEGER; VAR elem: ANYREC), NEW, ABSTRACT;
  261. PROCEDURE (e: ItemExt) Deref* (VAR ref: ANYREC), NEW, ABSTRACT;
  262. PROCEDURE (e: ItemExt) Valid* (): BOOLEAN, NEW, ABSTRACT;
  263. PROCEDURE (e: ItemExt) Size* (): INTEGER, NEW, ABSTRACT;
  264. PROCEDURE (e: ItemExt) BaseTyp* (): INTEGER, NEW, ABSTRACT;
  265. PROCEDURE (e: ItemExt) Len* (): INTEGER, NEW, ABSTRACT;
  266. PROCEDURE (e: ItemExt) Call* (OUT ok: BOOLEAN), NEW, ABSTRACT;
  267. PROCEDURE (e: ItemExt) BoolVal* (): BOOLEAN, NEW, ABSTRACT;
  268. PROCEDURE (e: ItemExt) PutBoolVal* (x: BOOLEAN), NEW, ABSTRACT;
  269. PROCEDURE (e: ItemExt) CharVal* (): CHAR, NEW, ABSTRACT;
  270. PROCEDURE (e: ItemExt) PutCharVal* (x: CHAR), NEW, ABSTRACT;
  271. PROCEDURE (e: ItemExt) IntVal* (): INTEGER, NEW, ABSTRACT;
  272. PROCEDURE (e: ItemExt) PutIntVal* (x: INTEGER), NEW, ABSTRACT;
  273. PROCEDURE (e: ItemExt) LongVal* (): LONGINT, NEW, ABSTRACT;
  274. PROCEDURE (e: ItemExt) PutLongVal* (x: LONGINT), NEW, ABSTRACT;
  275. PROCEDURE (e: ItemExt) RealVal* (): REAL, NEW, ABSTRACT;
  276. PROCEDURE (e: ItemExt) PutRealVal* (x: REAL), NEW, ABSTRACT;
  277. PROCEDURE (e: ItemExt) SetVal* (): SET, NEW, ABSTRACT;
  278. PROCEDURE (e: ItemExt) PutSetVal* (x: SET), NEW, ABSTRACT;
  279. PROCEDURE (e: ItemExt) PtrVal* (): ANYPTR, NEW, ABSTRACT;
  280. PROCEDURE (e: ItemExt) PutPtrVal* (x: ANYPTR), NEW, ABSTRACT;
  281. PROCEDURE (e: ItemExt) GetSStringVal* (OUT x: ARRAY OF SHORTCHAR;
  282. OUT ok: BOOLEAN), NEW, ABSTRACT;
  283. PROCEDURE (e: ItemExt) PutSStringVal* (IN x: ARRAY OF SHORTCHAR;
  284. OUT ok: BOOLEAN), NEW, ABSTRACT;
  285. PROCEDURE (e: ItemExt) GetStringVal* (OUT x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT;
  286. PROCEDURE (e: ItemExt) PutStringVal* (IN x: ARRAY OF CHAR; OUT ok: BOOLEAN), NEW, ABSTRACT;
  287. (* -------------------- miscellaneous tools -------------------- *)
  288. PROCEDURE Msg (IN str: ARRAY OF CHAR);
  289. VAR ss: ARRAY 1024 OF SHORTCHAR; res, l: INTEGER;
  290. BEGIN
  291. ss := SHORT(str);
  292. l := LEN(ss$);
  293. ss[l] := 0AX; ss[l + 1] := 0X;
  294. res := Libc.printf(ss)
  295. END Msg;
  296. PROCEDURE Int (x: LONGINT);
  297. VAR j, k: INTEGER; ch: CHAR; a, s: ARRAY 32 OF CHAR;
  298. BEGIN
  299. IF x # MIN(LONGINT) THEN
  300. IF x < 0 THEN s[0] := "-"; k := 1; x := -x ELSE k := 0 END;
  301. j := 0; REPEAT a[j] := CHR(x MOD 10 + ORD("0")); x := x DIV 10; INC(j) UNTIL x = 0
  302. ELSE
  303. a := "8085774586302733229"; s[0] := "-"; k := 1;
  304. j := 0; WHILE a[j] # 0X DO INC(j) END
  305. END;
  306. ASSERT(k + j < LEN(s), 20);
  307. REPEAT DEC(j); ch := a[j]; s[k] := ch; INC(k) UNTIL j = 0;
  308. s[k] := 0X;
  309. Msg(s);
  310. END Int;
  311. PROCEDURE (h: GuiHook) MessageBox* (
  312. title, msg: ARRAY OF CHAR; buttons: SET): INTEGER, NEW, ABSTRACT;
  313. PROCEDURE (h: GuiHook) Beep*, NEW, ABSTRACT;
  314. (* Is extended by HostGnome to show dialogs. If no dialog is present or
  315. if the dialog is not closed by using one button, then "mbClose" is returned *)
  316. PROCEDURE MessageBox* (title, msg: ARRAY OF CHAR; buttons: SET): INTEGER;
  317. VAR res: INTEGER;
  318. BEGIN
  319. IF guiHook # NIL THEN
  320. res := guiHook.MessageBox(title, msg, buttons)
  321. ELSE
  322. Msg(" ");
  323. Msg("****");
  324. Msg("* " + title);
  325. Msg("* " + msg);
  326. Msg("****");
  327. res := mbClose;
  328. END;
  329. RETURN res
  330. END MessageBox;
  331. PROCEDURE SetGuiHook* (hook: GuiHook);
  332. BEGIN
  333. guiHook := hook
  334. END SetGuiHook;
  335. PROCEDURE SplitName* (name: ARRAY OF CHAR; VAR head, tail: ARRAY OF CHAR);
  336. (* portable *)
  337. VAR i, j: INTEGER; ch, lch: CHAR;
  338. BEGIN
  339. i := 0; ch := name[0];
  340. IF ch # 0X THEN
  341. REPEAT
  342. head[i] := ch; lch := ch; INC(i); ch := name[i]
  343. UNTIL (ch = 0X)
  344. OR ((ch >= "A") & (ch <= "Z") OR (ch >= "À") & (ch # "×") & (ch <= "Þ"))
  345. & ((lch < "A") OR (lch > "Z") & (lch < "À") OR (lch = "×") OR (lch > "Þ"));
  346. head[i] := 0X; j := 0;
  347. WHILE ch # 0X DO tail[j] := ch; INC(i); INC(j); ch := name[i] END;
  348. tail[j] := 0X;
  349. IF tail = "" THEN tail := head$; head := "" END
  350. ELSE head := ""; tail := ""
  351. END
  352. END SplitName;
  353. PROCEDURE MakeFileName* (VAR name: ARRAY OF CHAR; type: ARRAY OF CHAR);
  354. VAR i, j: INTEGER; ext: ARRAY 8 OF CHAR; ch: CHAR;
  355. BEGIN
  356. i := 0;
  357. WHILE (name[i] # 0X) & (name[i] # ".") DO INC(i) END;
  358. IF name[i] = "." THEN
  359. IF name[i + 1] = 0X THEN name[i] := 0X END
  360. ELSIF i < LEN(name) - 4 THEN
  361. IF type = "" THEN ext := docType ELSE ext := type$ END;
  362. name[i] := "."; INC(i); j := 0; ch := ext[0];
  363. WHILE ch # 0X DO
  364. IF (ch >= "A") & (ch <= "Z") THEN
  365. ch := CHR(ORD(ch) + ORD("a") - ORD("A"))
  366. END;
  367. name[i] := ch; INC(i); INC(j); ch := ext[j]
  368. END;
  369. name[i] := 0X
  370. END
  371. END MakeFileName;
  372. PROCEDURE Time* (): LONGINT;
  373. VAR t: INTEGER;
  374. BEGIN
  375. (* t := WinApi.GetTickCount(); *)
  376. (* A. V. Shiryaev: OpenBSD *)
  377. ASSERT(Libc.CLOCKS_PER_SEC = 100);
  378. t := 10 * Libc.clock();
  379. IF t < told THEN INC(shift) END;
  380. told := t;
  381. RETURN shift * 100000000L + t
  382. END Time;
  383. PROCEDURE Beep* ();
  384. VAR ss: ARRAY 2 OF SHORTCHAR;
  385. BEGIN
  386. IF guiHook # NIL THEN
  387. guiHook.Beep
  388. ELSE
  389. ss[0] := 007X; ss[1] := 0X;
  390. res := Libc.printf(ss); res := Libc.fflush(Libc.NULL)
  391. END
  392. END Beep;
  393. PROCEDURE SearchProcVar* (var: INTEGER; VAR m: Module; VAR adr: INTEGER);
  394. BEGIN
  395. adr := var; m := NIL;
  396. IF var # 0 THEN
  397. m := modList;
  398. WHILE (m # NIL) & ((var < m.code) OR (var >= m.code + m.csize)) DO m := m.next END;
  399. IF m # NIL THEN DEC(adr, m.code) END
  400. END
  401. END SearchProcVar;
  402. (* -------------------- system memory management --------------------- *)
  403. (* A. V. Shiryaev, 2012.10: NOTE: it seems that GC works correctly with positive addesses only *)
  404. (*
  405. PROCEDURE HeapAlloc (adr: INTEGER; size: INTEGER; prot: SET): Libc.PtrVoid;
  406. VAR
  407. x: Libc.PtrVoid;
  408. res: INTEGER;
  409. BEGIN
  410. x := Libc.calloc(1, size); (* calloc initialize allocated space to zero *)
  411. IF x # Libc.NULL THEN
  412. res := Libc.mprotect(x, size, prot);
  413. IF res # 0 THEN
  414. Libc.free(x);
  415. x := Libc.NULL;
  416. Msg("Kernel.HeapAlloc: mprotect failed!");
  417. HALT(100)
  418. END
  419. END;
  420. RETURN x
  421. END HeapAlloc;
  422. *)
  423. PROCEDURE HeapAlloc (adr: Libc.PtrVoid; size: INTEGER; prot: SET): Libc.PtrVoid;
  424. VAR x: Libc.PtrVoid;
  425. BEGIN
  426. x := Libc.mmap(adr, size, prot, Libc.MAP_PRIVATE + Libc.MAP_ANON, -1, 0);
  427. IF x = Libc.MAP_FAILED THEN
  428. x := Libc.NULL
  429. ELSE
  430. ASSERT(size MOD 4 = 0, 100);
  431. Erase(x, size DIV 4)
  432. END;
  433. RETURN x
  434. END HeapAlloc;
  435. (*
  436. PROCEDURE HeapFree (adr: Libc.PtrVoid; size: INTEGER);
  437. VAR res: INTEGER;
  438. BEGIN
  439. (*
  440. ASSERT(size MOD 4 = 0, 100);
  441. Erase(adr, size DIV 4);
  442. res := Libc.mprotect(adr, size, Libc.PROT_NONE);
  443. ASSERT(res = 0, 101);
  444. *)
  445. Libc.free(adr)
  446. END HeapFree;
  447. *)
  448. PROCEDURE HeapFree (adr: Libc.PtrVoid; size: INTEGER);
  449. VAR res: INTEGER;
  450. BEGIN
  451. (*
  452. ASSERT(size MOD 4 = 0, 100);
  453. Erase(adr, size DIV 4);
  454. res := Libc.mprotect(adr, size, Libc.PROT_NONE);
  455. ASSERT(res = 0, 101);
  456. *)
  457. res := Libc.munmap(adr, size);
  458. ASSERT(res = 0, 102)
  459. END HeapFree;
  460. PROCEDURE AllocHeapMem (size: INTEGER; VAR c: Cluster);
  461. (* allocate at least size bytes, typically at least 256 kbytes are allocated *)
  462. CONST N = 65536; (* cluster size for dll *)
  463. prot = Libc.PROT_READ + Libc.PROT_WRITE (* + Libc.PROT_EXEC *);
  464. VAR adr: INTEGER;
  465. allocated: INTEGER;
  466. BEGIN
  467. INC(size, 16);
  468. ASSERT(size > 0, 100); adr := 0;
  469. IF size < N THEN adr := HeapAlloc(65536, N, prot) END;
  470. IF adr = 0 THEN adr := HeapAlloc(65536, size, prot); allocated := size ELSE allocated := N END;
  471. IF adr = 0 THEN c := NIL
  472. ELSE
  473. c := S.VAL(Cluster, (adr + 15) DIV 16 * 16); c.max := adr;
  474. c.size := allocated - (S.VAL(INTEGER, c) - adr);
  475. INC(used, c.size); INC(total, c.size)
  476. END
  477. (* post: (c = NIL) OR (c MOD 16 = 0) & (c.size >= size) *)
  478. END AllocHeapMem;
  479. PROCEDURE FreeHeapMem (c: Cluster);
  480. BEGIN
  481. DEC(used, c.size); DEC(total, c.size);
  482. HeapFree(c.max, (S.VAL(INTEGER, c) - c.max) + c.size)
  483. END FreeHeapMem;
  484. PROCEDURE AllocModMem* (descSize, modSize: INTEGER; VAR descAdr, modAdr: INTEGER);
  485. CONST
  486. prot = Libc.PROT_READ + Libc.PROT_WRITE (* + Libc.PROT_EXEC *);
  487. BEGIN
  488. descAdr := HeapAlloc(0, descSize, prot);
  489. IF descAdr # 0 THEN
  490. modAdr := HeapAlloc(0, modSize, prot);
  491. IF modAdr # 0 THEN INC(used, descSize + modSize)
  492. ELSE HeapFree(descAdr, descSize); descAdr := 0
  493. END
  494. ELSE modAdr := 0
  495. END
  496. END AllocModMem;
  497. PROCEDURE DeallocModMem* (descSize, modSize, descAdr, modAdr: INTEGER);
  498. BEGIN
  499. DEC(used, descSize + modSize);
  500. HeapFree(descAdr, descSize);
  501. HeapFree(modAdr, modSize)
  502. END DeallocModMem;
  503. PROCEDURE InvalModMem (modSize, modAdr: INTEGER);
  504. BEGIN
  505. DEC(used, modSize);
  506. HeapFree(modAdr, modSize)
  507. END InvalModMem;
  508. (*
  509. PROCEDURE IsReadable* (from, to: INTEGER): BOOLEAN;
  510. (* check wether memory between from (incl.) and to (excl.) may be read *)
  511. BEGIN
  512. RETURN WinApi.IsBadReadPtr(from, to - from) = 0
  513. END IsReadable;
  514. *)
  515. (* Alexander Shiryaev, 2012.10: I do not know other way that works in OpenBSD *)
  516. (* This procedure can be called from TrapHandler also *)
  517. PROCEDURE IsReadable* (from, to: INTEGER): BOOLEAN;
  518. (* check wether memory between from (incl.) and to (excl.) may be read *)
  519. VAR res: BOOLEAN; res1: INTEGER;
  520. x: SHORTCHAR;
  521. mask, omask: Libc.sigset_t;
  522. BEGIN
  523. (* save old sigmask and unblock SIGSEGV *)
  524. res1 := Libc.sigemptyset(S.ADR(mask));
  525. ASSERT(res1 = 0, 100);
  526. res1 := Libc.sigaddset(S.ADR(mask), Libc.SIGSEGV);
  527. ASSERT(res1 = 0, 101);
  528. res1 := Libc.sigprocmask(Libc.SIG_UNBLOCK, mask, omask);
  529. ASSERT(res1 = 0, 102);
  530. res := FALSE;
  531. res1 := Libc.sigsetjmp(isReadableContext, Libc.TRUE);
  532. IF res1 = 0 THEN
  533. isReadableCheck := TRUE;
  534. (* read memory *)
  535. REPEAT
  536. S.GET(from, x);
  537. INC(from)
  538. UNTIL from = to;
  539. res := TRUE
  540. ELSE
  541. ASSERT(res1 = 1, 103)
  542. END;
  543. isReadableCheck := FALSE;
  544. (* restore saved sigmask *)
  545. res1 := Libc.sigprocmask(Libc.SIG_SETMASK, omask, NIL);
  546. ASSERT(res1 = 0, 104);
  547. RETURN res
  548. END IsReadable;
  549. (* --------------------- NEW implementation (portable) -------------------- *)
  550. PROCEDURE^ NewBlock (size: INTEGER): Block;
  551. PROCEDURE NewRec* (typ: INTEGER): INTEGER; (* implementation of NEW(ptr) *)
  552. VAR size: INTEGER; b: Block; tag: Type; l: FList;
  553. BEGIN
  554. IF ODD(typ) THEN (* record contains interface pointers *)
  555. tag := S.VAL(Type, typ - 1);
  556. b := NewBlock(tag.size);
  557. IF b = NIL THEN RETURN 0 END;
  558. b.tag := tag;
  559. l := S.VAL(FList, S.ADR(b.last)); (* anchor new object! *)
  560. l := S.VAL(FList, NewRec(S.TYP(FList))); (* NEW(l) *)
  561. l.blk := b; l.iptr := TRUE; l.next := finalizers; finalizers := l;
  562. RETURN S.ADR(b.last)
  563. ELSE
  564. tag := S.VAL(Type, typ);
  565. b := NewBlock(tag.size);
  566. IF b = NIL THEN RETURN 0 END;
  567. b.tag := tag; S.GET(typ - 4, size);
  568. IF size # 0 THEN (* record uses a finalizer *)
  569. l := S.VAL(FList, S.ADR(b.last)); (* anchor new object! *)
  570. l := S.VAL(FList, NewRec(S.TYP(FList))); (* NEW(l) *)
  571. l.blk := b; l.next := finalizers; finalizers := l
  572. END;
  573. RETURN S.ADR(b.last)
  574. END
  575. END NewRec;
  576. PROCEDURE NewArr* (eltyp, nofelem, nofdim: INTEGER): INTEGER; (* impl. of NEW(ptr, dim0, dim1, ...) *)
  577. VAR b: Block; size, headSize: INTEGER; t: Type; fin: BOOLEAN; l: FList;
  578. BEGIN
  579. IF (nofdim < 0)OR(nofdim>1FFFFFFCH) THEN RETURN 0 END;(*20120822 Marc*)
  580. headSize := 4 * nofdim + 12; fin := FALSE;
  581. CASE eltyp OF
  582. (*
  583. | -1: eltyp := S.ADR(IntPtrType); fin := TRUE
  584. *)
  585. | -1: HALT(100)
  586. | 0: eltyp := S.ADR(PtrType)
  587. | 1: eltyp := S.ADR(Char8Type)
  588. | 2: eltyp := S.ADR(Int16Type)
  589. | 3: eltyp := S.ADR(Int8Type)
  590. | 4: eltyp := S.ADR(Int32Type)
  591. | 5: eltyp := S.ADR(BoolType)
  592. | 6: eltyp := S.ADR(SetType)
  593. | 7: eltyp := S.ADR(Real32Type)
  594. | 8: eltyp := S.ADR(Real64Type)
  595. | 9: eltyp := S.ADR(Char16Type)
  596. | 10: eltyp := S.ADR(Int64Type)
  597. | 11: eltyp := S.ADR(ProcType)
  598. | 12: eltyp := S.ADR(UPtrType)
  599. ELSE (* eltyp is desc *)
  600. IF ODD(eltyp) THEN DEC(eltyp); fin := TRUE END
  601. END;
  602. t := S.VAL(Type, eltyp);
  603. ASSERT(t .size> 0,100);
  604. IF (nofelem < 0) OR( (7FFFFFFFH-headSize) DIV t.size < nofelem) THEN (* 20120822 Marc*)
  605. RETURN 0
  606. END;
  607. size := headSize + nofelem * t.size;
  608. b := NewBlock(size);
  609. IF b = NIL THEN RETURN 0 END;
  610. b.tag := S.VAL(Type, eltyp + 2); (* tag + array mark *)
  611. b.last := S.ADR(b.last) + size - t.size; (* pointer to last elem *)
  612. b.first := S.ADR(b.last) + headSize; (* pointer to first elem *)
  613. IF fin THEN
  614. l := S.VAL(FList, S.ADR(b.last)); (* anchor new object! *)
  615. l := S.VAL(FList, NewRec(S.TYP(FList))); (* NEW(l) *)
  616. l.blk := b; l.aiptr := TRUE; l.next := finalizers; finalizers := l
  617. END;
  618. RETURN S.ADR(b.last)
  619. END NewArr;
  620. (* -------------------- handler installation (portable) --------------------- *)
  621. PROCEDURE ThisFinObj* (VAR id: Identifier): ANYPTR;
  622. VAR l: FList;
  623. BEGIN
  624. ASSERT(id.typ # 0, 100);
  625. l := finalizers;
  626. WHILE l # NIL DO
  627. IF S.VAL(INTEGER, l.blk.tag) = id.typ THEN
  628. id.obj := S.VAL(ANYPTR, S.ADR(l.blk.last));
  629. IF id.Identified() THEN RETURN id.obj END
  630. END;
  631. l := l.next
  632. END;
  633. RETURN NIL
  634. END ThisFinObj;
  635. PROCEDURE InstallReducer* (r: Reducer);
  636. BEGIN
  637. r.next := reducers; reducers := r
  638. END InstallReducer;
  639. PROCEDURE InstallTrapViewer* (h: Handler);
  640. BEGIN
  641. trapViewer := h
  642. END InstallTrapViewer;
  643. PROCEDURE InstallTrapChecker* (h: Handler);
  644. BEGIN
  645. trapChecker := h
  646. END InstallTrapChecker;
  647. PROCEDURE PushTrapCleaner* (c: TrapCleaner);
  648. VAR t: TrapCleaner;
  649. BEGIN
  650. t := trapStack; WHILE (t # NIL) & (t # c) DO t := t.next END;
  651. ASSERT(t = NIL, 20);
  652. c.next := trapStack; trapStack := c
  653. END PushTrapCleaner;
  654. PROCEDURE PopTrapCleaner* (c: TrapCleaner);
  655. VAR t: TrapCleaner;
  656. BEGIN
  657. t := NIL;
  658. WHILE (trapStack # NIL) & (t # c) DO
  659. t := trapStack; trapStack := trapStack.next
  660. END
  661. END PopTrapCleaner;
  662. PROCEDURE InstallCleaner* (p: Command);
  663. VAR c: CList;
  664. BEGIN
  665. c := S.VAL(CList, NewRec(S.TYP(CList))); (* NEW(c) *)
  666. c.do := p; c.trapped := FALSE; c.next := cleaners; cleaners := c
  667. END InstallCleaner;
  668. PROCEDURE RemoveCleaner* (p: Command);
  669. VAR c0, c: CList;
  670. BEGIN
  671. c := cleaners; c0 := NIL;
  672. WHILE (c # NIL) & (c.do # p) DO c0 := c; c := c.next END;
  673. IF c # NIL THEN
  674. IF c0 = NIL THEN cleaners := cleaners.next ELSE c0.next := c.next END
  675. END
  676. END RemoveCleaner;
  677. PROCEDURE Cleanup*;
  678. VAR c, c0: CList;
  679. BEGIN
  680. c := cleaners; c0 := NIL;
  681. WHILE c # NIL DO
  682. IF ~c.trapped THEN
  683. c.trapped := TRUE; c.do; c.trapped := FALSE; c0 := c
  684. ELSE
  685. IF c0 = NIL THEN cleaners := cleaners.next
  686. ELSE c0.next := c.next
  687. END
  688. END;
  689. c := c.next
  690. END
  691. END Cleanup;
  692. (* -------------------- meta information (portable) --------------------- *)
  693. PROCEDURE (h: LoaderHook) ThisMod* (IN name: ARRAY OF SHORTCHAR): Module, NEW, ABSTRACT;
  694. PROCEDURE SetLoaderHook*(h: LoaderHook);
  695. BEGIN
  696. loader := h
  697. END SetLoaderHook;
  698. PROCEDURE InitModule (mod: Module); (* initialize linked modules *)
  699. VAR body: Command;
  700. res: INTEGER; errno: INTEGER;
  701. BEGIN
  702. IF ~(dyn IN mod.opts) & (mod.next # NIL) & ~(init IN mod.next.opts) THEN InitModule(mod.next) END;
  703. IF ~(init IN mod.opts) THEN
  704. body := S.VAL(Command, mod.code);
  705. INCL(mod.opts, init);
  706. actual := mod;
  707. (* A. V. Shiryaev: Allow execution on code pages *)
  708. res := Libc.mprotect(mod.code, mod.csize,
  709. Libc.PROT_READ + Libc.PROT_WRITE + Libc.PROT_EXEC);
  710. IF res = -1 THEN
  711. S.GET( Libc.__errno_location(), errno );
  712. Msg("ERROR: Kernel.InitModule: mprotect failed!");
  713. Msg(mod.name$); Int(mod.code); Int(mod.csize); Int(errno);
  714. HALT(100)
  715. ELSE ASSERT(res = 0)
  716. END;
  717. body(); actual := NIL
  718. END
  719. END InitModule;
  720. PROCEDURE ThisLoadedMod* (IN name: ARRAY OF SHORTCHAR): Module; (* loaded modules only *)
  721. VAR m: Module;
  722. BEGIN
  723. loadres := done;
  724. m := modList;
  725. WHILE (m # NIL) & ((m.name # name) OR (m.refcnt < 0)) DO m := m.next END;
  726. IF (m # NIL) & ~(init IN m.opts) THEN InitModule(m) END;
  727. IF m = NIL THEN loadres := moduleNotFound END;
  728. RETURN m
  729. END ThisLoadedMod;
  730. PROCEDURE ThisMod* (IN name: ARRAY OF CHAR): Module;
  731. VAR n : Name;
  732. BEGIN
  733. n := SHORT(name$);
  734. IF loader # NIL THEN
  735. loader.res := done;
  736. RETURN loader.ThisMod(n)
  737. ELSE
  738. RETURN ThisLoadedMod(n)
  739. END
  740. END ThisMod;
  741. PROCEDURE LoadMod* (IN name: ARRAY OF CHAR);
  742. VAR m: Module;
  743. BEGIN
  744. m := ThisMod(name)
  745. END LoadMod;
  746. PROCEDURE GetLoaderResult* (OUT res: INTEGER; OUT importing, imported, object: ARRAY OF CHAR);
  747. BEGIN
  748. IF loader # NIL THEN
  749. res := loader.res;
  750. importing := loader.importing$;
  751. imported := loader.imported$;
  752. object := loader.object$
  753. ELSE
  754. res := loadres;
  755. importing := "";
  756. imported := "";
  757. object := ""
  758. END
  759. END GetLoaderResult;
  760. PROCEDURE ThisObject* (mod: Module; name: ARRAY OF SHORTCHAR): Object;
  761. VAR l, r, m: INTEGER; p: StrPtr;
  762. BEGIN
  763. l := 0; r := mod.export.num;
  764. WHILE l < r DO (* binary search *)
  765. m := (l + r) DIV 2;
  766. p := S.VAL(StrPtr, S.ADR(mod.names[mod.export.obj[m].id DIV 256]));
  767. IF p^ = name THEN RETURN S.VAL(Object, S.ADR(mod.export.obj[m])) END;
  768. IF p^ < name THEN l := m + 1 ELSE r := m END
  769. END;
  770. RETURN NIL
  771. END ThisObject;
  772. PROCEDURE ThisDesc* (mod: Module; fprint: INTEGER): Object;
  773. VAR i, n: INTEGER;
  774. BEGIN
  775. i := 0; n := mod.export.num;
  776. WHILE (i < n) & (mod.export.obj[i].id DIV 256 = 0) DO
  777. IF mod.export.obj[i].offs = fprint THEN RETURN S.VAL(Object, S.ADR(mod.export.obj[i])) END;
  778. INC(i)
  779. END;
  780. RETURN NIL
  781. END ThisDesc;
  782. PROCEDURE ThisField* (rec: Type; name: ARRAY OF SHORTCHAR): Object;
  783. VAR n: INTEGER; p: StrPtr; obj: Object; m: Module;
  784. BEGIN
  785. m := rec.mod;
  786. obj := S.VAL(Object, S.ADR(rec.fields.obj[0])); n := rec.fields.num;
  787. WHILE n > 0 DO
  788. p := S.VAL(StrPtr, S.ADR(m.names[obj.id DIV 256]));
  789. IF p^ = name THEN RETURN obj END;
  790. DEC(n); INC(S.VAL(INTEGER, obj), 16)
  791. END;
  792. RETURN NIL
  793. END ThisField;
  794. PROCEDURE ThisCommand* (mod: Module; name: ARRAY OF SHORTCHAR): Command;
  795. VAR x: Object; sig: Signature;
  796. BEGIN
  797. x := ThisObject(mod, name);
  798. IF (x # NIL) & (x.id MOD 16 = mProc) THEN
  799. sig := S.VAL(Signature, x.struct);
  800. IF (sig.retStruct = NIL) & (sig.num = 0) THEN RETURN S.VAL(Command, mod.procBase + x.offs) END
  801. END;
  802. RETURN NIL
  803. END ThisCommand;
  804. PROCEDURE ThisType* (mod: Module; name: ARRAY OF SHORTCHAR): Type;
  805. VAR x: Object;
  806. BEGIN
  807. x := ThisObject(mod, name);
  808. IF (x # NIL) & (x.id MOD 16 = mTyp) & (S.VAL(INTEGER, x.struct) DIV 256 # 0) THEN
  809. RETURN x.struct
  810. ELSE
  811. RETURN NIL
  812. END
  813. END ThisType;
  814. PROCEDURE TypeOf* (IN rec: ANYREC): Type;
  815. BEGIN
  816. RETURN S.VAL(Type, S.TYP(rec))
  817. END TypeOf;
  818. PROCEDURE LevelOf* (t: Type): SHORTINT;
  819. BEGIN
  820. RETURN SHORT(t.id DIV 16 MOD 16)
  821. END LevelOf;
  822. PROCEDURE NewObj* (VAR o: S.PTR; t: Type);
  823. VAR i: INTEGER;
  824. BEGIN
  825. IF t.size = -1 THEN o := NIL
  826. ELSE
  827. i := 0; WHILE t.ptroffs[i] >= 0 DO INC(i) END;
  828. IF t.ptroffs[i+1] >= 0 THEN INC(S.VAL(INTEGER, t)) END; (* with interface pointers *)
  829. o := S.VAL(S.PTR, NewRec(S.VAL(INTEGER, t))) (* generic NEW *)
  830. END
  831. END NewObj;
  832. PROCEDURE GetObjName* (mod: Module; obj: Object; VAR name: Name);
  833. VAR p: StrPtr;
  834. BEGIN
  835. p := S.VAL(StrPtr, S.ADR(mod.names[obj.id DIV 256]));
  836. name := p^$
  837. END GetObjName;
  838. PROCEDURE GetTypeName* (t: Type; VAR name: Name);
  839. VAR p: StrPtr;
  840. BEGIN
  841. p := S.VAL(StrPtr, S.ADR(t.mod.names[t.id DIV 256]));
  842. name := p^$
  843. END GetTypeName;
  844. PROCEDURE RegisterMod* (mod: Module);
  845. VAR i: INTEGER;
  846. t: Libc.time_t; tm: Libc.tm;
  847. BEGIN
  848. mod.next := modList; modList := mod; mod.refcnt := 0; INCL(mod.opts, dyn); i := 0;
  849. WHILE i < mod.nofimps DO
  850. IF mod.imports[i] # NIL THEN INC(mod.imports[i].refcnt) END;
  851. INC(i)
  852. END;
  853. t := Libc.time(NIL);
  854. tm := Libc.localtime(t);
  855. mod.loadTime[0] := SHORT(tm.tm_year + 1900); (* Linux counts years from 1900 but BlackBox from 0000 *)
  856. mod.loadTime[1] := SHORT(tm.tm_mon + 1) (* Linux month range 0-11 but BB month range 1-12 *);
  857. mod.loadTime[2] := SHORT(tm.tm_mday);
  858. mod.loadTime[3] := SHORT(tm.tm_hour);
  859. mod.loadTime[4] := SHORT(tm.tm_min);
  860. mod.loadTime[5] := SHORT(tm.tm_sec);
  861. tm := NIL;
  862. IF ~(init IN mod.opts) THEN InitModule(mod) END
  863. END RegisterMod;
  864. PROCEDURE^ Collect*;
  865. PROCEDURE UnloadMod* (mod: Module);
  866. VAR i: INTEGER; t: Command;
  867. BEGIN
  868. IF mod.refcnt = 0 THEN
  869. t := mod.term; mod.term := NIL;
  870. IF t # NIL THEN t() END; (* terminate module *)
  871. i := 0;
  872. WHILE i < mod.nofptrs DO (* release global pointers *)
  873. S.PUT(mod.varBase + mod.ptrs[i], 0); INC(i)
  874. END;
  875. (*
  876. ReleaseIPtrs(mod); (* release global interface pointers *)
  877. *)
  878. Collect; (* call finalizers *)
  879. i := 0;
  880. WHILE i < mod.nofimps DO (* release imported modules *)
  881. IF mod.imports[i] # NIL THEN DEC(mod.imports[i].refcnt) END;
  882. INC(i)
  883. END;
  884. mod.refcnt := -1;
  885. IF dyn IN mod.opts THEN (* release memory *)
  886. InvalModMem(mod.data + mod.dsize - mod.refs, mod.refs)
  887. END
  888. END
  889. END UnloadMod;
  890. (* -------------------- dynamic procedure call --------------------- *) (* COMPILER DEPENDENT *)
  891. PROCEDURE [1] PUSH (p: INTEGER) 050H; (* push AX *)
  892. PROCEDURE [1] CALL (a: INTEGER) 0FFH, 0D0H; (* call AX *)
  893. PROCEDURE [1] RETI (): LONGINT;
  894. PROCEDURE [1] RETR (): REAL;
  895. (*
  896. type par
  897. 32 bit scalar value
  898. 64 bit scalar low hi
  899. var scalar address
  900. record address tag
  901. array address size
  902. open array address length .. length
  903. *)
  904. PROCEDURE Call* (adr: INTEGER; sig: Signature; IN par: ARRAY OF INTEGER; n: INTEGER): LONGINT;
  905. VAR p, kind, sp, size: INTEGER; typ: Type; r: REAL;
  906. BEGIN
  907. p := sig.num;
  908. WHILE p > 0 DO (* push parameters from right to left *)
  909. DEC(p);
  910. typ := sig.par[p].struct;
  911. kind := sig.par[p].id MOD 16;
  912. IF (S.VAL(INTEGER, typ) DIV 256 = 0) OR (typ.id MOD 4 IN {0, 3}) THEN (* scalar *)
  913. IF (kind = 10) & ((S.VAL(INTEGER, typ) = 8) OR (S.VAL(INTEGER, typ) = 10)) THEN (* 64 bit *)
  914. DEC(n); PUSH(par[n]) (* push hi word *)
  915. END;
  916. DEC(n); PUSH(par[n]) (* push value/address *)
  917. ELSIF typ.id MOD 4 = 1 THEN (* record *)
  918. IF kind # 10 THEN (* var par *)
  919. DEC(n); PUSH(par[n]); (* push tag *)
  920. DEC(n); PUSH(par[n]) (* push address *)
  921. ELSE
  922. DEC(n, 2); (* skip tag *)
  923. S.GETREG(SP, sp); sp := (sp - typ.size) DIV 4 * 4; S.PUTREG(SP, sp); (* allocate space *)
  924. S.MOVE(par[n], sp, typ.size) (* copy to stack *)
  925. END
  926. ELSIF typ.size = 0 THEN (* open array *)
  927. size := typ.id DIV 16 MOD 16; (* number of open dimensions *)
  928. WHILE size > 0 DO
  929. DEC(size); DEC(n); PUSH(par[n]) (* push length *)
  930. END;
  931. DEC(n); PUSH(par[n]) (* push address *)
  932. ELSE (* fix array *)
  933. IF kind # 10 THEN (* var par *)
  934. DEC(n, 2); PUSH(par[n]) (* push address *)
  935. ELSE
  936. DEC(n); size := par[n]; DEC(n);
  937. S.GETREG(SP, sp); sp := (sp - size) DIV 4 * 4; S.PUTREG(SP, sp); (* allocate space *)
  938. S.MOVE(par[n], sp, size) (* copy to stack *)
  939. END
  940. END
  941. END;
  942. ASSERT(n = 0);
  943. IF S.VAL(INTEGER, sig.retStruct) = 7 THEN (* shortreal *)
  944. CALL(adr);
  945. RETURN S.VAL(INTEGER, SHORT(RETR())) (* return value in fpu register *)
  946. ELSIF S.VAL(INTEGER, sig.retStruct) = 8 THEN (* real *)
  947. CALL(adr); r := RETR();
  948. RETURN S.VAL(LONGINT, r) (* return value in fpu register *)
  949. ELSE
  950. CALL(adr);
  951. RETURN RETI() (* return value in integer registers *)
  952. END
  953. END Call;
  954. (* -------------------- reference information (portable) --------------------- *)
  955. PROCEDURE RefCh (VAR ref: INTEGER; VAR ch: SHORTCHAR);
  956. BEGIN
  957. S.GET(ref, ch); INC(ref)
  958. END RefCh;
  959. PROCEDURE RefNum (VAR ref: INTEGER; VAR x: INTEGER);
  960. VAR s, n: INTEGER; ch: SHORTCHAR;
  961. BEGIN
  962. s := 0; n := 0; RefCh(ref, ch);
  963. WHILE ORD(ch) >= 128 DO INC(n, ASH(ORD(ch) - 128, s) ); INC(s, 7); RefCh(ref, ch) END;
  964. x := n + ASH(ORD(ch) MOD 64 - ORD(ch) DIV 64 * 64, s)
  965. END RefNum;
  966. PROCEDURE RefName (VAR ref: INTEGER; VAR n: Name);
  967. VAR i: INTEGER; ch: SHORTCHAR;
  968. BEGIN
  969. i := 0; RefCh(ref, ch);
  970. WHILE ch # 0X DO n[i] := ch; INC(i); RefCh(ref, ch) END;
  971. n[i] := 0X
  972. END RefName;
  973. PROCEDURE GetRefProc* (VAR ref: INTEGER; VAR adr: INTEGER; VAR name: Name);
  974. VAR ch: SHORTCHAR;
  975. BEGIN
  976. S.GET(ref, ch);
  977. WHILE ch >= 0FDX DO (* skip variables *)
  978. INC(ref); RefCh(ref, ch);
  979. IF ch = 10X THEN INC(ref, 4) END;
  980. RefNum(ref, adr); RefName(ref, name); S.GET(ref, ch)
  981. END;
  982. WHILE (ch > 0X) & (ch < 0FCX) DO (* skip source refs *)
  983. INC(ref); RefNum(ref, adr); S.GET(ref, ch)
  984. END;
  985. IF ch = 0FCX THEN INC(ref); RefNum(ref, adr); RefName(ref, name)
  986. ELSE adr := 0
  987. END
  988. END GetRefProc;
  989. (* A. V. Shiryaev, 2012.11 *)
  990. PROCEDURE CheckRefVarReadable (ref: INTEGER): BOOLEAN;
  991. VAR ok: BOOLEAN; ch: SHORTCHAR;
  992. p: INTEGER; (* address *)
  993. PROCEDURE Get;
  994. BEGIN
  995. IF ok THEN
  996. IF IsReadable(ref, ref+1) THEN (* S.GET(ref, ch); INC(ref) *) RefCh(ref, ch)
  997. ELSE ok := FALSE
  998. END
  999. END
  1000. END Get;
  1001. PROCEDURE Num;
  1002. BEGIN
  1003. Get; WHILE ok & (ORD(ch) >= 128) DO Get END
  1004. END Num;
  1005. PROCEDURE Name;
  1006. BEGIN
  1007. Get; WHILE ok & (ch # 0X) DO Get END
  1008. END Name;
  1009. BEGIN
  1010. ok := TRUE;
  1011. Get; (* mode *)
  1012. IF ok & (ch >= 0FDX) THEN
  1013. Get; (* form *)
  1014. IF ok & (ch = 10X) THEN
  1015. IF IsReadable(ref, ref + 4) THEN (* desc *)
  1016. S.GET(ref, p); INC(ref, 4);
  1017. ok := IsReadable(p + 2 * 4, p + 3 * 4) (* desc.id *)
  1018. ELSE ok := FALSE
  1019. END
  1020. END;
  1021. Num; Name
  1022. END;
  1023. RETURN ok
  1024. END CheckRefVarReadable;
  1025. PROCEDURE GetRefVar* (VAR ref: INTEGER; VAR mode, form: SHORTCHAR; VAR desc: Type;
  1026. VAR adr: INTEGER; VAR name: Name);
  1027. BEGIN
  1028. IF CheckRefVarReadable(ref) THEN
  1029. S.GET(ref, mode); desc := NIL;
  1030. IF mode >= 0FDX THEN
  1031. mode := SHORT(CHR(ORD(mode) - 0FCH));
  1032. INC(ref); RefCh(ref, form);
  1033. IF form = 10X THEN
  1034. S.GET(ref, desc); INC(ref, 4); form := SHORT(CHR(16 + desc.id MOD 4))
  1035. END;
  1036. RefNum(ref, adr); RefName(ref, name)
  1037. ELSE
  1038. mode := 0X; form := 0X; adr := 0
  1039. END
  1040. ELSE
  1041. Msg("Kernel.GetRefVar failed!"); Int(ref);
  1042. mode := 0X; form := 0X; adr := 0
  1043. END
  1044. END GetRefVar;
  1045. PROCEDURE SourcePos* (mod: Module; codePos: INTEGER): INTEGER;
  1046. VAR ref, pos, ad, d: INTEGER; ch: SHORTCHAR; name: Name;
  1047. BEGIN
  1048. ref := mod.refs; pos := 0; ad := 0; S.GET(ref, ch);
  1049. WHILE ch # 0X DO
  1050. WHILE (ch > 0X) & (ch < 0FCX) DO
  1051. INC(ad, ORD(ch)); INC(ref); RefNum(ref, d);
  1052. IF ad > codePos THEN RETURN pos END;
  1053. INC(pos, d); S.GET(ref, ch)
  1054. END;
  1055. IF ch = 0FCX THEN INC(ref); RefNum(ref, d); RefName(ref, name); S.GET(ref, ch) END;
  1056. WHILE ch >= 0FDX DO (* skip variables *)
  1057. INC(ref); RefCh(ref, ch);
  1058. IF ch = 10X THEN INC(ref, 4) END;
  1059. RefNum(ref, d); RefName(ref, name); S.GET(ref, ch)
  1060. END
  1061. END;
  1062. RETURN -1
  1063. END SourcePos;
  1064. (* -------------------- dynamic link libraries --------------------- *)
  1065. (*
  1066. PROCEDURE DlOpen (name: ARRAY OF SHORTCHAR): Dl.HANDLE;
  1067. CONST flags = Dl.RTLD_LAZY + Dl.RTLD_GLOBAL;
  1068. VAR h: Dl.HANDLE;
  1069. i: INTEGER;
  1070. BEGIN
  1071. h := Dl.NULL;
  1072. i := 0; WHILE (i < LEN(name)) & (name[i] # 0X) DO INC(i) END;
  1073. IF i < LEN(name) THEN
  1074. h := Dl.dlopen(name, flags);
  1075. WHILE (h = Dl.NULL) & (i > 0) DO
  1076. DEC(i);
  1077. WHILE (i > 0) & (name[i] # '.') DO DEC(i) END;
  1078. IF i > 0 THEN
  1079. name[i] := 0X;
  1080. h := Dl.dlopen(name, flags);
  1081. (* IF h # Dl.NULL THEN Msg(name$) END *)
  1082. END
  1083. END
  1084. END;
  1085. RETURN h
  1086. END DlOpen;
  1087. *)
  1088. PROCEDURE LoadDll* (IN name: ARRAY OF SHORTCHAR; VAR ok: BOOLEAN);
  1089. VAR h: Dl.HANDLE;
  1090. BEGIN
  1091. ok := FALSE;
  1092. h := Dl.dlopen(name, Dl.RTLD_LAZY + Dl.RTLD_GLOBAL);
  1093. IF h # Dl.NULL THEN ok := TRUE END
  1094. END LoadDll;
  1095. PROCEDURE ThisDllObj* (mode, fprint: INTEGER; IN dll, name: ARRAY OF SHORTCHAR): INTEGER;
  1096. VAR ad: INTEGER; h: Dl.HANDLE;
  1097. BEGIN
  1098. ad := 0;
  1099. IF mode IN {mVar, mProc} THEN
  1100. h := Dl.dlopen(dll, Dl.RTLD_LAZY+ Dl.RTLD_GLOBAL);
  1101. IF h # Dl.NULL THEN
  1102. ad := Dl.dlsym(h, name);
  1103. END
  1104. END;
  1105. RETURN ad
  1106. END ThisDllObj;
  1107. (* -------------------- garbage collector (portable) --------------------- *)
  1108. PROCEDURE Mark (this: Block);
  1109. VAR father, son: Block; tag: Type; flag, offset, actual: INTEGER;
  1110. BEGIN
  1111. IF ~ODD(S.VAL(INTEGER, this.tag)) THEN
  1112. father := NIL;
  1113. LOOP
  1114. INC(S.VAL(INTEGER, this.tag));
  1115. flag := S.VAL(INTEGER, this.tag) MOD 4;
  1116. tag := S.VAL(Type, S.VAL(INTEGER, this.tag) - flag);
  1117. IF flag >= 2 THEN actual := this.first; this.actual := actual
  1118. ELSE actual := S.ADR(this.last)
  1119. END;
  1120. LOOP
  1121. offset := tag.ptroffs[0];
  1122. IF offset < 0 THEN
  1123. INC(S.VAL(INTEGER, tag), offset + 4); (* restore tag *)
  1124. IF (flag >= 2) & (actual < this.last) & (offset < -4) THEN (* next array element *)
  1125. INC(actual, tag.size); this.actual := actual
  1126. ELSE (* up *)
  1127. this.tag := S.VAL(Type, S.VAL(INTEGER, tag) + flag);
  1128. IF father = NIL THEN RETURN END;
  1129. son := this; this := father;
  1130. flag := S.VAL(INTEGER, this.tag) MOD 4;
  1131. tag := S.VAL(Type, S.VAL(INTEGER, this.tag) - flag);
  1132. offset := tag.ptroffs[0];
  1133. IF flag >= 2 THEN actual := this.actual ELSE actual := S.ADR(this.last) END;
  1134. S.GET(actual + offset, father); S.PUT(actual + offset, S.ADR(son.last));
  1135. INC(S.VAL(INTEGER, tag), 4)
  1136. END
  1137. ELSE
  1138. S.GET(actual + offset, son);
  1139. IF son # NIL THEN
  1140. DEC(S.VAL(INTEGER, son), 4);
  1141. IF ~ODD(S.VAL(INTEGER, son.tag)) THEN (* down *)
  1142. this.tag := S.VAL(Type, S.VAL(INTEGER, tag) + flag);
  1143. S.PUT(actual + offset, father); father := this; this := son;
  1144. EXIT
  1145. END
  1146. END;
  1147. INC(S.VAL(INTEGER, tag), 4)
  1148. END
  1149. END
  1150. END
  1151. END
  1152. END Mark;
  1153. PROCEDURE MarkGlobals;
  1154. VAR m: Module; i, p: INTEGER;
  1155. BEGIN
  1156. m := modList;
  1157. WHILE m # NIL DO
  1158. IF m.refcnt >= 0 THEN
  1159. i := 0;
  1160. WHILE i < m.nofptrs DO
  1161. S.GET(m.varBase + m.ptrs[i], p); INC(i);
  1162. IF p # 0 THEN Mark(S.VAL(Block, p - 4)) END
  1163. END
  1164. END;
  1165. m := m.next
  1166. END
  1167. END MarkGlobals;
  1168. (* This is the specification for the code procedure following below:
  1169. PROCEDURE Next (b: Block): Block; (* next block in same cluster *)
  1170. VAR size: INTEGER;
  1171. BEGIN
  1172. S.GET(S.VAL(INTEGER, b.tag) DIV 4 * 4, size);
  1173. IF ODD(S.VAL(INTEGER, b.tag) DIV 2) THEN INC(size, b.last - S.ADR(b.last)) END;
  1174. RETURN S.VAL(Block, S.VAL(INTEGER, b) + (size + 19) DIV 16 * 16)
  1175. END Next;
  1176. *)
  1177. PROCEDURE [code] Next (b: Block): Block (* next block in same cluster *)
  1178. (*
  1179. MOV ECX,[EAX] b.tag
  1180. AND CL,0FCH b.tag DIV * 4
  1181. MOV ECX,[ECX] size
  1182. TESTB [EAX],02H ODD(b.tag DIV 2)
  1183. JE L1
  1184. ADD ECX,[EAX,4] size + b.last
  1185. SUB ECX,EAX
  1186. SUB ECX,4 size + b.last - ADR(b.last)
  1187. L1:
  1188. ADD ECX,19 size + 19
  1189. AND CL,0F0H (size + 19) DIV 16 * 16
  1190. ADD EAX,ECX b + size
  1191. *)
  1192. 08BH, 008H,
  1193. 080H, 0E1H, 0FCH,
  1194. 08BH, 009H,
  1195. 0F6H, 000H, 002H,
  1196. 074H, 008H,
  1197. 003H, 048H, 004H,
  1198. 029H, 0C1H,
  1199. 083H, 0E9H, 004H,
  1200. 083H, 0C1H, 013H,
  1201. 080H, 0E1H, 0F0H,
  1202. 001H, 0C8H;
  1203. PROCEDURE CheckCandidates;
  1204. (* pre: nofcand > 0 *)
  1205. VAR i, j, h, p, end: INTEGER; c: Cluster; blk, next: Block;
  1206. BEGIN
  1207. (* sort candidates (shellsort) *)
  1208. h := 1; REPEAT h := h*3 + 1 UNTIL h > nofcand;
  1209. REPEAT h := h DIV 3; i := h;
  1210. WHILE i < nofcand DO p := candidates[i]; j := i;
  1211. WHILE (j >= h) & (candidates[j-h] > p) DO
  1212. candidates[j] := candidates[j-h]; j := j-h
  1213. END;
  1214. candidates[j] := p; INC(i)
  1215. END
  1216. UNTIL h = 1;
  1217. (* sweep *)
  1218. c := root; i := 0;
  1219. WHILE c # NIL DO
  1220. blk := S.VAL(Block, S.VAL(INTEGER, c) + 12);
  1221. end := S.VAL(INTEGER, blk) + (c.size - 12) DIV 16 * 16;
  1222. WHILE candidates[i] < S.VAL(INTEGER, blk) DO
  1223. INC(i);
  1224. IF i = nofcand THEN RETURN END
  1225. END;
  1226. WHILE S.VAL(INTEGER, blk) < end DO
  1227. next := Next(blk);
  1228. IF candidates[i] < S.VAL(INTEGER, next) THEN
  1229. IF (S.VAL(INTEGER, blk.tag) # S.ADR(blk.last)) (* not a free block *)
  1230. & (~strictStackSweep OR (candidates[i] = S.ADR(blk.last))) THEN
  1231. Mark(blk)
  1232. END;
  1233. REPEAT
  1234. INC(i);
  1235. IF i = nofcand THEN RETURN END
  1236. UNTIL candidates[i] >= S.VAL(INTEGER, next)
  1237. END;
  1238. IF (S.VAL(INTEGER, blk.tag) MOD 4 = 0) & (S.VAL(INTEGER, blk.tag) # S.ADR(blk.last))
  1239. & (blk.tag.base[0] = NIL) & (blk.actual > 0) THEN (* referenced interface record *)
  1240. Mark(blk)
  1241. END;
  1242. blk := next
  1243. END;
  1244. c := c.next
  1245. END
  1246. END CheckCandidates;
  1247. PROCEDURE MarkLocals;
  1248. VAR sp, p, min, max: INTEGER; c: Cluster;
  1249. BEGIN
  1250. S.GETREG(FP, sp); nofcand := 0; c := root;
  1251. WHILE c.next # NIL DO c := c.next END;
  1252. min := S.VAL(INTEGER, root); max := S.VAL(INTEGER, c) + c.size;
  1253. WHILE sp < baseStack DO
  1254. S.GET(sp, p);
  1255. IF (p > min) & (p < max) & (~strictStackSweep OR (p MOD 16 = 0)) THEN
  1256. candidates[nofcand] := p; INC(nofcand);
  1257. IF nofcand = LEN(candidates) - 1 THEN CheckCandidates; nofcand := 0 END
  1258. END;
  1259. INC(sp, 4)
  1260. END;
  1261. candidates[nofcand] := max; INC(nofcand); (* ensure complete scan for interface mark*)
  1262. IF nofcand > 0 THEN CheckCandidates END
  1263. END MarkLocals;
  1264. PROCEDURE MarkFinObj;
  1265. VAR f: FList;
  1266. BEGIN
  1267. wouldFinalize := FALSE;
  1268. f := finalizers;
  1269. WHILE f # NIL DO
  1270. IF ~ODD(S.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END;
  1271. Mark(f.blk);
  1272. f := f.next
  1273. END;
  1274. f := hotFinalizers;
  1275. WHILE f # NIL DO IF ~ODD(S.VAL(INTEGER, f.blk.tag)) THEN wouldFinalize := TRUE END;
  1276. Mark(f.blk);
  1277. f := f.next
  1278. END
  1279. END MarkFinObj;
  1280. PROCEDURE CheckFinalizers;
  1281. VAR f, g, h, k: FList;
  1282. BEGIN
  1283. f := finalizers; g := NIL;
  1284. IF hotFinalizers = NIL THEN k := NIL
  1285. ELSE
  1286. k := hotFinalizers;
  1287. WHILE k.next # NIL DO k := k.next END
  1288. END;
  1289. WHILE f # NIL DO
  1290. h := f; f := f.next;
  1291. IF ~ODD(S.VAL(INTEGER, h.blk.tag)) THEN
  1292. IF g = NIL THEN finalizers := f ELSE g.next := f END;
  1293. IF k = NIL THEN hotFinalizers := h ELSE k.next := h END;
  1294. k := h; h.next := NIL
  1295. ELSE g := h
  1296. END
  1297. END;
  1298. h := hotFinalizers;
  1299. WHILE h # NIL DO Mark(h.blk); h := h.next END
  1300. END CheckFinalizers;
  1301. PROCEDURE ExecFinalizer (a, b, c: INTEGER);
  1302. VAR f: FList; fin: PROCEDURE(this: ANYPTR);
  1303. BEGIN
  1304. f := S.VAL(FList, a);
  1305. IF f.aiptr THEN (* ArrFinalizer(S.VAL(ANYPTR, S.ADR(f.blk.last))) *)
  1306. ELSE
  1307. S.GET(S.VAL(INTEGER, f.blk.tag) - 4, fin); (* method 0 *)
  1308. IF (fin # NIL) & (f.blk.tag.mod.refcnt >= 0) THEN fin(S.VAL(ANYPTR, S.ADR(f.blk.last))) END;
  1309. (*
  1310. IF f.iptr THEN RecFinalizer(S.VAL(ANYPTR, S.ADR(f.blk.last))) END
  1311. *)
  1312. END
  1313. END ExecFinalizer;
  1314. PROCEDURE^ Try* (h: TryHandler; a, b, c: INTEGER); (* COMPILER DEPENDENT *)
  1315. PROCEDURE CallFinalizers;
  1316. VAR f: FList;
  1317. BEGIN
  1318. WHILE hotFinalizers # NIL DO
  1319. f := hotFinalizers; hotFinalizers := hotFinalizers.next;
  1320. Try(ExecFinalizer, S.VAL(INTEGER, f), 0, 0)
  1321. END;
  1322. wouldFinalize := FALSE
  1323. END CallFinalizers;
  1324. PROCEDURE Insert (blk: FreeBlock; size: INTEGER); (* insert block in free list *)
  1325. VAR i: INTEGER;
  1326. BEGIN
  1327. blk.size := size - 4; blk.tag := S.VAL(Type, S.ADR(blk.size));
  1328. i := MIN(N - 1, (blk.size DIV 16));
  1329. blk.next := free[i]; free[i] := blk
  1330. END Insert;
  1331. PROCEDURE Sweep (dealloc: BOOLEAN);
  1332. VAR cluster, last, c: Cluster; blk, next: Block; fblk, b, t: FreeBlock; end, i: INTEGER;
  1333. BEGIN
  1334. cluster := root; last := NIL; allocated := 0;
  1335. i := N;
  1336. REPEAT DEC(i); free[i] := sentinel UNTIL i = 0;
  1337. WHILE cluster # NIL DO
  1338. blk := S.VAL(Block, S.VAL(INTEGER, cluster) + 12);
  1339. end := S.VAL(INTEGER, blk) + (cluster.size - 12) DIV 16 * 16;
  1340. fblk := NIL;
  1341. WHILE S.VAL(INTEGER, blk) < end DO
  1342. next := Next(blk);
  1343. IF ODD(S.VAL(INTEGER, blk.tag)) THEN
  1344. IF fblk # NIL THEN
  1345. Insert(fblk, S.VAL(INTEGER, blk) - S.VAL(INTEGER, fblk));
  1346. fblk := NIL
  1347. END;
  1348. DEC(S.VAL(INTEGER, blk.tag)); (* unmark *)
  1349. INC(allocated, S.VAL(INTEGER, next) - S.VAL(INTEGER, blk))
  1350. ELSIF fblk = NIL THEN
  1351. fblk := S.VAL(FreeBlock, blk)
  1352. END;
  1353. blk := next
  1354. END;
  1355. IF dealloc & (S.VAL(INTEGER, fblk) = S.VAL(INTEGER, cluster) + 12) THEN (* deallocate cluster *)
  1356. c := cluster; cluster := cluster.next;
  1357. IF last = NIL THEN root := cluster ELSE last.next := cluster END;
  1358. FreeHeapMem(c)
  1359. ELSE
  1360. IF fblk # NIL THEN Insert(fblk, end - S.VAL(INTEGER, fblk)) END;
  1361. last := cluster; cluster := cluster.next
  1362. END
  1363. END;
  1364. (* reverse free list *)
  1365. i := N;
  1366. REPEAT
  1367. DEC(i);
  1368. b := free[i]; fblk := sentinel;
  1369. WHILE b # sentinel DO t := b; b := t.next; t.next := fblk; fblk := t END;
  1370. free[i] := fblk
  1371. UNTIL i = 0
  1372. END Sweep;
  1373. PROCEDURE Collect*;
  1374. BEGIN
  1375. IF root # NIL THEN
  1376. CallFinalizers; (* trap cleanup *)
  1377. IF debug & (watcher # NIL) THEN watcher(1) END;
  1378. MarkGlobals;
  1379. MarkLocals;
  1380. CheckFinalizers;
  1381. Sweep(TRUE);
  1382. CallFinalizers
  1383. END
  1384. END Collect;
  1385. PROCEDURE FastCollect*;
  1386. BEGIN
  1387. IF root # NIL THEN
  1388. IF debug & (watcher # NIL) THEN watcher(2) END;
  1389. MarkGlobals;
  1390. MarkLocals;
  1391. MarkFinObj;
  1392. Sweep(FALSE)
  1393. END
  1394. END FastCollect;
  1395. PROCEDURE WouldFinalize* (): BOOLEAN;
  1396. BEGIN
  1397. RETURN wouldFinalize
  1398. END WouldFinalize;
  1399. (* --------------------- memory allocation (portable) -------------------- *)
  1400. PROCEDURE OldBlock (size: INTEGER): FreeBlock; (* size MOD 16 = 0 *)
  1401. VAR b, l: FreeBlock; s, i: INTEGER;
  1402. BEGIN
  1403. IF debug & (watcher # NIL) THEN watcher(3) END;
  1404. s := size - 4;
  1405. i := MIN(N - 1, s DIV 16);
  1406. WHILE (i # N - 1) & (free[i] = sentinel) DO INC(i) END;
  1407. b := free[i]; l := NIL;
  1408. WHILE b.size < s DO l := b; b := b.next END;
  1409. IF b # sentinel THEN
  1410. IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END
  1411. ELSE b := NIL
  1412. END;
  1413. RETURN b
  1414. END OldBlock;
  1415. PROCEDURE LastBlock (limit: INTEGER): FreeBlock; (* size MOD 16 = 0 *)
  1416. VAR b, l: FreeBlock; s, i: INTEGER;
  1417. BEGIN
  1418. s := limit - 4;
  1419. i := 0;
  1420. REPEAT
  1421. b := free[i]; l := NIL;
  1422. WHILE (b # sentinel) & (S.VAL(INTEGER, b) + b.size # s) DO l := b; b := b.next END;
  1423. IF b # sentinel THEN
  1424. IF l = NIL THEN free[i] := b.next ELSE l.next := b.next END
  1425. ELSE b := NIL
  1426. END;
  1427. INC(i)
  1428. UNTIL (b # NIL) OR (i = N);
  1429. RETURN b
  1430. END LastBlock;
  1431. PROCEDURE NewBlock (size: INTEGER): Block;
  1432. VAR tsize, a, s: INTEGER; b: FreeBlock; new, c: Cluster; r: Reducer;
  1433. BEGIN
  1434. ASSERT(size>=0,20);
  1435. IF size >7FFFFFECH THEN RETURN NIL END; (*20120822 Marc*)
  1436. tsize := (size + 19) DIV 16 * 16;
  1437. b := OldBlock(tsize); (* 1) search for free block *)
  1438. IF b = NIL THEN
  1439. FastCollect; b := OldBlock(tsize); (* 2) collect *)
  1440. IF b = NIL THEN
  1441. Collect; b := OldBlock(tsize); (* 2a) fully collect *)
  1442. END;
  1443. IF b = NIL THEN
  1444. AllocHeapMem(tsize + 12, new); (* 3) allocate new cluster *)
  1445. IF new # NIL THEN
  1446. IF (root = NIL) OR (S.VAL(INTEGER, new) < S.VAL(INTEGER, root)) THEN
  1447. new.next := root; root := new
  1448. ELSE
  1449. c := root;
  1450. WHILE (c.next # NIL) & (S.VAL(INTEGER, new) > S.VAL(INTEGER, c.next)) DO c := c.next END;
  1451. new.next := c.next; c.next := new
  1452. END;
  1453. b := S.VAL(FreeBlock, S.VAL(INTEGER, new) + 12);
  1454. b.size := (new.size - 12) DIV 16 * 16 - 4
  1455. ELSE
  1456. RETURN NIL (* 4) give up *)
  1457. END
  1458. END
  1459. END;
  1460. (* b # NIL *)
  1461. a := b.size + 4 - tsize;
  1462. IF a > 0 THEN Insert(S.VAL(FreeBlock, S.VAL(INTEGER, b) + tsize), a) END;
  1463. IF size > 0 THEN Erase(S.ADR(b.size), (size + 3) DIV 4) END;
  1464. INC(allocated, tsize);
  1465. RETURN S.VAL(Block, b)
  1466. END NewBlock;
  1467. PROCEDURE Allocated* (): INTEGER;
  1468. BEGIN
  1469. RETURN allocated
  1470. END Allocated;
  1471. PROCEDURE Used* (): INTEGER;
  1472. BEGIN
  1473. RETURN used
  1474. END Used;
  1475. PROCEDURE Root* (): INTEGER;
  1476. BEGIN
  1477. RETURN S.VAL(INTEGER, root)
  1478. END Root;
  1479. (* -------------------- Trap Handling --------------------- *)
  1480. PROCEDURE^ InitFpu;
  1481. PROCEDURE Start* (code: Command);
  1482. BEGIN
  1483. restart := code;
  1484. S.GETREG(SP, baseStack); (* save base stack *)
  1485. res := Libc.sigsetjmp(loopContext, Libc.TRUE);
  1486. code()
  1487. END Start;
  1488. PROCEDURE Quit* (exitCode: INTEGER);
  1489. VAR m: Module; term: Command; t: BOOLEAN;
  1490. res: INTEGER;
  1491. BEGIN
  1492. trapViewer := NIL; trapChecker := NIL; restart := NIL;
  1493. t := terminating; terminating := TRUE; m := modList;
  1494. WHILE m # NIL DO (* call terminators *)
  1495. IF ~static OR ~t THEN
  1496. term := m.term; m.term := NIL;
  1497. IF term # NIL THEN term() END
  1498. END;
  1499. (*
  1500. ReleaseIPtrs(m);
  1501. *)
  1502. m := m.next
  1503. END;
  1504. CallFinalizers;
  1505. hotFinalizers := finalizers; finalizers := NIL;
  1506. CallFinalizers;
  1507. (*
  1508. IF ~inDll THEN
  1509. RemoveExcp(excpPtr^);
  1510. WinApi.ExitProcess(exitCode) (* never returns *)
  1511. END
  1512. *)
  1513. res := Libc.fflush(0);
  1514. Libc.exit(exitCode)
  1515. END Quit;
  1516. PROCEDURE FatalError* (id: INTEGER; str: ARRAY OF CHAR);
  1517. VAR res: INTEGER; title: ARRAY 16 OF CHAR; text: ARRAY 256 OF SHORTCHAR;
  1518. BEGIN
  1519. title := "Error xy";
  1520. title[6] := CHR(id DIV 10 + ORD("0"));
  1521. title[7] := CHR(id MOD 10 + ORD("0"));
  1522. (*
  1523. res := WinApi.MessageBoxW(0, str, title, {});
  1524. *)
  1525. text := SHORT(str$);
  1526. res := MessageBox(title$, SHORT(str), {mbOk});
  1527. (*
  1528. IF ~inDll THEN RemoveExcp(excpPtr^) END;
  1529. *)
  1530. (*
  1531. WinApi.ExitProcess(1)
  1532. *)
  1533. Libc.exit(1)
  1534. (* never returns *)
  1535. END FatalError;
  1536. PROCEDURE DefaultTrapViewer;
  1537. VAR len, ref, end, x, a, b, c: INTEGER; mod: Module;
  1538. name: Name; out: ARRAY 1024 OF SHORTCHAR;
  1539. PROCEDURE WriteString (s: ARRAY OF SHORTCHAR);
  1540. VAR i: INTEGER;
  1541. BEGIN
  1542. i := 0;
  1543. WHILE (len < LEN(out) - 1) & (s[i] # 0X) DO out[len] := s[i]; INC(i); INC(len) END
  1544. END WriteString;
  1545. PROCEDURE WriteHex (x, n: INTEGER);
  1546. VAR i, y: INTEGER;
  1547. BEGIN
  1548. IF len + n < LEN(out) THEN
  1549. i := len + n - 1;
  1550. WHILE i >= len DO
  1551. y := x MOD 16; x := x DIV 16;
  1552. IF y > 9 THEN y := y + (ORD("A") - ORD("0") - 10) END;
  1553. out[i] := SHORT(CHR(y + ORD("0"))); DEC(i)
  1554. END;
  1555. INC(len, n)
  1556. END
  1557. END WriteHex;
  1558. PROCEDURE WriteLn;
  1559. BEGIN
  1560. IF len < LEN(out) - 1 THEN out[len] := 0AX (* 0DX on Windows *); INC(len) END
  1561. END WriteLn;
  1562. BEGIN
  1563. len := 0;
  1564. IF err = 129 THEN WriteString("invalid with")
  1565. ELSIF err = 130 THEN WriteString("invalid case")
  1566. ELSIF err = 131 THEN WriteString("function without return")
  1567. ELSIF err = 132 THEN WriteString("type guard")
  1568. ELSIF err = 133 THEN WriteString("implied type guard")
  1569. ELSIF err = 134 THEN WriteString("value out of range")
  1570. ELSIF err = 135 THEN WriteString("index out of range")
  1571. ELSIF err = 136 THEN WriteString("string too long")
  1572. ELSIF err = 137 THEN WriteString("stack overflow")
  1573. ELSIF err = 138 THEN WriteString("integer overflow")
  1574. ELSIF err = 139 THEN WriteString("division by zero")
  1575. ELSIF err = 140 THEN WriteString("infinite real result")
  1576. ELSIF err = 141 THEN WriteString("real underflow")
  1577. ELSIF err = 142 THEN WriteString("real overflow")
  1578. ELSIF err = 143 THEN WriteString("undefined real result")
  1579. ELSIF err = 200 THEN WriteString("keyboard interrupt")
  1580. ELSIF err = 202 THEN WriteString("illegal instruction: ");
  1581. WriteHex(val, 4)
  1582. ELSIF err = 203 THEN WriteString("illegal memory read [ad = ");
  1583. WriteHex(val, 8); WriteString("]")
  1584. ELSIF err = 204 THEN WriteString("illegal memory write [ad = ");
  1585. WriteHex(val, 8); WriteString("]")
  1586. ELSIF err = 205 THEN WriteString("illegal execution [ad = ");
  1587. WriteHex(val, 8); WriteString("]")
  1588. ELSIF err < 0 THEN WriteString("exception #"); WriteHex(-err, 2)
  1589. ELSE err := err DIV 100 * 256 + err DIV 10 MOD 10 * 16 + err MOD 10;
  1590. WriteString("trap #"); WriteHex(err, 3)
  1591. END;
  1592. a := pc; b := fp; c := 12;
  1593. REPEAT
  1594. WriteLn; WriteString("- ");
  1595. mod := modList;
  1596. WHILE (mod # NIL) & ((a < mod.code) OR (a >= mod.code + mod.csize)) DO mod := mod.next END;
  1597. IF mod # NIL THEN
  1598. DEC(a, mod.code);
  1599. IF mod.refcnt >= 0 THEN
  1600. WriteString(mod.name); ref := mod.refs;
  1601. REPEAT GetRefProc(ref, end, name) UNTIL (end = 0) OR (a < end);
  1602. IF a < end THEN
  1603. WriteString("."); WriteString(name)
  1604. END
  1605. ELSE
  1606. WriteString("("); WriteString(mod.name); WriteString(")")
  1607. END;
  1608. WriteString(" ")
  1609. END;
  1610. WriteString("(pc="); WriteHex(a, 8);
  1611. WriteString(", fp="); WriteHex(b, 8); WriteString(")");
  1612. IF (b >= sp) & (b < stack) THEN
  1613. S.GET(b+4, a); (* stacked pc *)
  1614. S.GET(b, b); (* dynamic link *)
  1615. DEC(c)
  1616. ELSE c := 0
  1617. END
  1618. UNTIL c = 0;
  1619. out[len] := 0X;
  1620. x := MessageBox("BlackBox", out$, {mbOk})
  1621. END DefaultTrapViewer;
  1622. PROCEDURE TrapCleanup;
  1623. VAR t: TrapCleaner;
  1624. BEGIN
  1625. WHILE trapStack # NIL DO
  1626. t := trapStack; trapStack := trapStack.next; t.Cleanup
  1627. END;
  1628. IF (trapChecker # NIL) & (err # 128) THEN trapChecker END
  1629. END TrapCleanup;
  1630. PROCEDURE SetTrapGuard* (on: BOOLEAN);
  1631. BEGIN
  1632. guarded := on
  1633. END SetTrapGuard;
  1634. PROCEDURE Try* (h: TryHandler; a, b, c: INTEGER);
  1635. VAR res: INTEGER; context: Libc.sigjmp_buf; oldContext: POINTER TO Libc.sigjmp_buf;
  1636. BEGIN
  1637. oldContext := currentTryContext;
  1638. res := Libc.sigsetjmp(context, Libc.TRUE);
  1639. currentTryContext := S.ADR(context);
  1640. IF res = 0 THEN (* first time around *)
  1641. h(a, b, c);
  1642. ELSIF res = trapReturn THEN (* after a trap *)
  1643. ELSE
  1644. HALT(100)
  1645. END;
  1646. currentTryContext := oldContext;
  1647. END Try;
  1648. (* -------------------- Initialization --------------------- *)
  1649. PROCEDURE InitFpu; (* COMPILER DEPENDENT *)
  1650. (* could be eliminated, delayed for backward compatibility *)
  1651. VAR cw: SET;
  1652. BEGIN
  1653. FINIT;
  1654. FSTCW;
  1655. (* denorm, underflow, precision, zero div, overflow masked *)
  1656. (* invalid trapped *)
  1657. (* round to nearest, temp precision *)
  1658. cw := cw - {0..5, 8..11} + {1, 2, 3, 4, 5, 8, 9};
  1659. FLDCW
  1660. END InitFpu;
  1661. (* A. V. Shiryaev: Show extended trap information (OpenBSD) *)
  1662. PROCEDURE ShowTrap (sig: INTEGER; siginfo: Libc.Ptrsiginfo_t; context: Libc.Ptrucontext_t);
  1663. PROCEDURE WriteChar (c: SHORTCHAR);
  1664. VAR s: ARRAY [untagged] 2 OF SHORTCHAR;
  1665. BEGIN
  1666. s[0] := c; s[1] := 0X;
  1667. res := Libc.printf(s)
  1668. END WriteChar;
  1669. PROCEDURE WriteString (s: ARRAY OF SHORTCHAR);
  1670. VAR res: INTEGER;
  1671. BEGIN
  1672. res := Libc.printf(s)
  1673. END WriteString;
  1674. PROCEDURE WriteHex (x, n: INTEGER);
  1675. VAR i, y: INTEGER;
  1676. s: ARRAY 9 OF SHORTCHAR;
  1677. BEGIN
  1678. s[n] := 0X;
  1679. i := 0 + n - 1;
  1680. WriteChar("$");
  1681. WHILE i >= 0 DO
  1682. y := x MOD 16; x := x DIV 16;
  1683. IF y > 9 THEN y := y + (ORD("A") - ORD("0") - 10) END;
  1684. s[i] := SHORT(CHR(y + ORD("0")));
  1685. DEC(i)
  1686. END;
  1687. WriteString(s)
  1688. END WriteHex;
  1689. PROCEDURE WriteLn;
  1690. BEGIN
  1691. WriteChar(0AX)
  1692. END WriteLn;
  1693. PROCEDURE KV (name: ARRAY OF SHORTCHAR; x: INTEGER);
  1694. BEGIN
  1695. WriteString(name); WriteString(" = "); WriteHex(x, 8)
  1696. END KV;
  1697. BEGIN
  1698. WriteString("================================"); WriteLn;
  1699. WriteString("TRAP:"); WriteLn;
  1700. WriteString("--------------------------------"); WriteLn;
  1701. KV("sig", sig); WriteString(", ");
  1702. KV("baseStack", baseStack); WriteLn;
  1703. KV("GS ", context.sc_gs); WriteString(", ");
  1704. KV("FS ", context.sc_fs); WriteString(", ");
  1705. KV("ES ", context.sc_es); WriteString(", ");
  1706. KV("DS ", context.sc_ds); WriteLn;
  1707. KV("EDI", context.sc_edi); WriteString(", ");
  1708. KV("ESI", context.sc_esi); WriteString(", ");
  1709. KV("EBP", context.sc_ebp); WriteString(", ");
  1710. KV("EBX", context.sc_ebx); WriteLn;
  1711. KV("EDX", context.sc_edx); WriteString(", ");
  1712. KV("ECX", context.sc_ecx); WriteString(", ");
  1713. KV("EAX", context.sc_eax); WriteString(", ");
  1714. KV("EIP", context.sc_eip); WriteLn;
  1715. KV("CS", context.sc_cs); WriteString(", ");
  1716. KV("EFLAGS", context.sc_eflags); WriteString(", ");
  1717. KV("ESP", context.sc_esp); WriteString(", ");
  1718. KV("SS", context.sc_ss); WriteLn;
  1719. KV("ONSTACK", context.sc_onstack); WriteString(", ");
  1720. KV("MASK", context.sc_mask); WriteString(", ");
  1721. KV("TRAPNO", context.sc_trapno); WriteString(", ");
  1722. KV("ERR", context.sc_err); WriteLn;
  1723. WriteString("---- siginfo: ------------------"); WriteLn;
  1724. KV("signo", siginfo.si_signo); WriteString(", ");
  1725. KV("code", siginfo.si_code); WriteString(", ");
  1726. KV("errno", siginfo.si_errno); WriteLn;
  1727. KV("fault.addr", siginfo._data._fault._addr); WriteString(", ");
  1728. KV("fault.trapno", siginfo._data._fault._trapno); WriteLn;
  1729. WriteString("================================"); WriteLn
  1730. END ShowTrap;
  1731. PROCEDURE [ccall] TrapHandler (sig: INTEGER; siginfo: Libc.Ptrsiginfo_t; context: Libc.Ptrucontext_t);
  1732. BEGIN
  1733. IF isReadableCheck THEN
  1734. isReadableCheck := FALSE;
  1735. Msg("~IsReadable");
  1736. Libc.siglongjmp(isReadableContext, 1)
  1737. END;
  1738. (*
  1739. S.GETREG(SP, sp);
  1740. S.GETREG(FP, fp);
  1741. *)
  1742. stack := baseStack;
  1743. (* A. V. Shiryaev *)
  1744. (*
  1745. sp := context.uc_mcontext.gregs[7]; (* TODO: is the stack pointer really stored in register 7? *)
  1746. fp := context.uc_mcontext.gregs[6]; (* TODO: is the frame pointer really stored in register 6? *)
  1747. pc := context.uc_mcontext.gregs[14]; (* TODO: is the pc really stored in register 14? *)
  1748. *)
  1749. (* val := siginfo.si_addr; *)
  1750. (* OpenBSD *)
  1751. ShowTrap(sig, siginfo, context);
  1752. sp := context.sc_esp; fp := context.sc_ebp; pc := context.sc_eip;
  1753. val := siginfo._data._fault._addr;
  1754. (*
  1755. Int(sig); Int(siginfo.si_signo); Int(siginfo.si_code); Int(siginfo.si_errno);
  1756. Int(siginfo.si_status); Int(siginfo.si_value); Int(siginfo.si_int);
  1757. *)
  1758. err := sig;
  1759. IF trapped THEN DefaultTrapViewer END;
  1760. CASE sig OF
  1761. Libc.SIGINT:
  1762. err := 200 (* Interrupt (ANSI). *)
  1763. | Libc.SIGILL: (* Illegal instruction (ANSI). *)
  1764. err := 202; val := 0;
  1765. IF IsReadable(pc, pc + 4) THEN
  1766. S.GET(pc, val);
  1767. IF val MOD 100H = 8DH THEN (* lea reg,reg *)
  1768. IF val DIV 100H MOD 100H = 0F0H THEN
  1769. err := val DIV 10000H MOD 100H (* trap *)
  1770. ELSIF val DIV 1000H MOD 10H = 0EH THEN
  1771. err := 128 + val DIV 100H MOD 10H (* run time error *)
  1772. END
  1773. END
  1774. END
  1775. | Libc.SIGFPE:
  1776. CASE siginfo.si_code OF
  1777. 0: (* TODO: ?????? *)
  1778. (* A. V. Shiryaev: OpenBSD *)
  1779. (*
  1780. IF siginfo.si_int = 8 THEN
  1781. err := 139
  1782. ELSIF siginfo.si_int = 0 THEN
  1783. err := 143
  1784. END
  1785. *)
  1786. err := 143;
  1787. | Libc.FPE_INTDIV: err := 139 (* Integer divide by zero. *)
  1788. | Libc.FPE_INTOVF: err := 138 (* Integer overflow. *)
  1789. | Libc.FPE_FLTDIV: err := 140 (* Floating point divide by zero. *)
  1790. | Libc.FPE_FLTOVF: err := 142 (* Floating point overflow. *)
  1791. | Libc.FPE_FLTUND: err := 141 (* Floating point underflow. *)
  1792. | Libc.FPE_FLTRES: err := 143 (* Floating point inexact result. *)
  1793. | Libc.FPE_FLTINV: err := 143 (* Floating point invalid operation. *)
  1794. | Libc.FPE_FLTSUB: err := 134 (* Subscript out of range. *)
  1795. ELSE
  1796. END
  1797. | Libc.SIGSEGV: (* Segmentation violation (ANSI). *)
  1798. err := 203
  1799. ELSE
  1800. END;
  1801. INC(trapCount);
  1802. InitFpu;
  1803. TrapCleanup;
  1804. IF err # 128 THEN
  1805. IF (trapViewer = NIL) OR trapped THEN
  1806. DefaultTrapViewer
  1807. ELSE
  1808. trapped := TRUE;
  1809. trapViewer();
  1810. trapped := FALSE
  1811. END
  1812. END;
  1813. IF currentTryContext # NIL THEN (* Try failed *)
  1814. Libc.siglongjmp(currentTryContext, trapReturn)
  1815. ELSE
  1816. IF restart # NIL THEN (* Start failed *)
  1817. Libc.siglongjmp(loopContext, trapReturn)
  1818. END;
  1819. Quit(1); (* FIXME *)
  1820. END;
  1821. trapped := FALSE
  1822. END TrapHandler;
  1823. PROCEDURE InstallSignals*;
  1824. VAR sa, old: Libc.sigaction_t; res, i: INTEGER;
  1825. (*
  1826. sigstk: Libc.sigaltstack_t;
  1827. errno: INTEGER;
  1828. *)
  1829. BEGIN
  1830. (*
  1831. (* A. V. Shiryaev: Set alternative stack on which signals are to be processed *)
  1832. sigstk.ss_sp := sigStack;
  1833. sigstk.ss_size := sigStackSize;
  1834. sigstk.ss_flags := 0;
  1835. res := Libc.sigaltstack(sigstk, NIL);
  1836. IF res # 0 THEN Msg("ERROR: Kernel.InstallSignals: sigaltstack failed!");
  1837. S.GET( Libc.__errno_location(), errno );
  1838. Int(errno);
  1839. Libc.exit(1)
  1840. END;
  1841. *)
  1842. sa.sa_sigaction := TrapHandler;
  1843. (*
  1844. res := LinLibc.sigemptyset(S.ADR(sa.sa_mask));
  1845. *)
  1846. res := Libc.sigfillset(S.ADR(sa.sa_mask));
  1847. sa.sa_flags := (* Libc.SA_ONSTACK + *) Libc.SA_SIGINFO; (* TrapHandler takes three arguments *)
  1848. (*
  1849. IF LinLibc.sigaction(LinLibc.SIGINT, sa, old) # 0 THEN Msg("failed to install SIGINT") END;
  1850. IF LinLibc.sigaction(LinLibc.SIGILL, sa, old) # 0 THEN Msg("failed to install SIGILL") END;
  1851. IF LinLibc.sigaction(LinLibc.SIGFPE, sa, old) # 0 THEN Msg("failed to install SIGFPE") END;
  1852. IF LinLibc.sigaction(LinLibc.SIGSEGV, sa, old) # 0 THEN Msg("failed to install SIGSEGV") END;
  1853. IF LinLibc.sigaction(LinLibc.SIGPIPE, sa, old) # 0 THEN Msg("failed to install SIGPIPE") END;
  1854. IF LinLibc.sigaction(LinLibc.SIGTERM, sa, old) # 0 THEN Msg("failed to install SIGTERM") END;
  1855. *)
  1856. (* respond to all possible signals *)
  1857. FOR i := 1 TO Libc._NSIG - 1 DO
  1858. IF (i # Libc.SIGKILL)
  1859. & (i # Libc.SIGSTOP)
  1860. & (i # Libc.SIGWINCH)
  1861. & (i # Libc.SIGTHR) (* A. V. Shiryaev: OpenBSD -pthread *)
  1862. THEN
  1863. IF Libc.sigaction(i, sa, old) # 0 THEN Msg("failed to install signal"); Int(i) END;
  1864. END
  1865. END
  1866. END InstallSignals;
  1867. PROCEDURE Init;
  1868. VAR i: INTEGER;
  1869. BEGIN
  1870. (*
  1871. (* for sigaltstack *)
  1872. sigStack := Libc.calloc(1, sigStackSize);
  1873. IF sigStack = Libc.NULL THEN
  1874. Msg("ERROR: Kernel.Init: calloc(1, sigStackSize) failed!");
  1875. Libc.exit(1)
  1876. END;
  1877. *)
  1878. isReadableCheck := FALSE;
  1879. InstallSignals; (* init exception handling *)
  1880. currentTryContext := NIL;
  1881. allocated := 0; total := 0; used := 0;
  1882. sentinelBlock.size := MAX(INTEGER);
  1883. sentinel := S.ADR(sentinelBlock);
  1884. (*
  1885. S.PUTREG(ML, S.ADR(modList));
  1886. *)
  1887. i := N;
  1888. REPEAT DEC(i); free[i] := sentinel UNTIL i = 0;
  1889. IF inDll THEN
  1890. (*
  1891. baseStack := FPageWord(4); (* begin of stack segment *)
  1892. *)
  1893. END;
  1894. InitFpu;
  1895. IF ~static THEN
  1896. InitModule(modList);
  1897. IF ~inDll THEN Quit(1) END
  1898. END;
  1899. told := 0; shift := 0
  1900. END Init;
  1901. BEGIN
  1902. IF modList = NIL THEN (* only once *)
  1903. S.GETREG(SP, baseStack); (* TODO: Check that this is ok. *)
  1904. IF bootInfo # NIL THEN
  1905. modList := bootInfo.modList (* boot loader initializes the bootInfo struct *)
  1906. ELSE
  1907. S.GETREG(ML, modList) (* linker loads module list to BX *)
  1908. END;
  1909. static := init IN modList.opts;
  1910. inDll := dll IN modList.opts;
  1911. Init
  1912. END
  1913. CLOSE
  1914. IF ~terminating THEN
  1915. terminating := TRUE;
  1916. Quit(0)
  1917. END
  1918. END Kernel.