2
0

Obsd.Kernel.txt 60 KB

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