2
0

Kernel.txt 59 KB

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