sysos2.pas 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809
  1. {****************************************************************************
  2. FPK-Pascal -- OS/2 runtime library
  3. Copyright (c) 1993,95 by Florian Kl„mpfl
  4. Copyright (c) 1997 by Dani‰l Mantione
  5. FPK-Pascal is distributed under the GNU Public License v2. So is this unit.
  6. The GNU Public License requires you to distribute the source code of this
  7. unit with any product that uses it. We grant you an exception to this, and
  8. that is, when you compile a program with the FPK Pascal compiler, you do not
  9. need to ship source code with that program, AS LONG AS YOU ARE USING
  10. UNMODIFIED CODE! If you modify this code, you MUST change the next line:
  11. <This an official, unmodified FPK Pascal source code file.>
  12. Send us your modified files, we can work together if you want!
  13. ****************************************************************************}
  14. unit sysos2;
  15. {$I os.inc}
  16. interface
  17. { die betriebssystemunabhangigen Deklarationen einfuegen: }
  18. {$I SYSTEMH.INC}
  19. {$I heaph.inc}
  20. type Tos=(osDOS,osOS2,osDPMI);
  21. var os_mode:Tos;
  22. first_meg:pointer;
  23. type Psysthreadib=^Tsysthreadib;
  24. Pthreadinfoblock=^Tthreadinfoblock;
  25. Pprocessinfoblock=^Tprocessinfoblock;
  26. Tbytearray=array[0..$ffff] of byte;
  27. Pbytearray=^Tbytearray;
  28. Tsysthreadib=record
  29. tid,
  30. priority,
  31. version:longint;
  32. MCcount,
  33. MCforceflag:word;
  34. end;
  35. Tthreadinfoblock=record
  36. pexchain,
  37. stack,
  38. stacklimit:pointer;
  39. tib2:Psysthreadib;
  40. version,
  41. ordinal:longint;
  42. end;
  43. Tprocessinfoblock=record
  44. pid,
  45. parentpid,
  46. hmte:longint;
  47. cmd,
  48. env:Pbytearray;
  49. flstatus,
  50. ttype:longint;
  51. end;
  52. procedure _DosGetInfoBlocks(var Atib:Pthreadinfoblock;
  53. var Apib:Pprocessinfoblock);
  54. implementation
  55. { die betriebssystemunabhangigen Implementationen einfuegen: }
  56. {$I SYSTEM.INC}
  57. procedure _DosGetInfoBlocks(var Atib:Pthreadinfoblock;
  58. var Apib:Pprocessinfoblock);[C];
  59. {****************************************************************************
  60. Miscelleanious related routines.
  61. ****************************************************************************}
  62. procedure halt;
  63. begin
  64. asm
  65. movw $0x4c00,%ax
  66. call ___syscall
  67. end;
  68. end;
  69. procedure halt(errnum : byte);
  70. begin
  71. asm
  72. movb $0x4c,%ah
  73. movb errnum,%al
  74. call ___syscall
  75. end;
  76. end;
  77. function paramcount : longint;
  78. begin
  79. asm
  80. movl _argc,%eax
  81. decl %eax
  82. leave
  83. ret
  84. end ['EAX'];
  85. end;
  86. function paramstr(l : longint):string;
  87. function args : pointer;
  88. begin
  89. asm
  90. movl _argv,%eax
  91. leave
  92. ret
  93. end ['EAX'];
  94. end;
  95. var p:^Pchar;
  96. begin
  97. if (l>=0) and (l<=paramcount) then
  98. begin
  99. p:=args;
  100. paramstr:=strpas(p[l]);
  101. end
  102. else paramstr:='';
  103. end;
  104. procedure randomize;
  105. var hl:longint;
  106. begin
  107. asm
  108. movb $0x2c,%ah
  109. call ___syscall
  110. movw %cx,-4(%ebp)
  111. movw %dx,-2(%ebp)
  112. end;
  113. randseed:=hl;
  114. end;
  115. {****************************************************************************
  116. Text-file I/O related routines.
  117. ****************************************************************************}
  118. function open(f:Pchar;flags:longint):longint;
  119. begin
  120. asm
  121. movb $0x3d,%ah
  122. movl 8(%ebp),%edx
  123. movb 12(%ebp),%al
  124. call ___syscall
  125. jnc LOPEN1
  126. movw %ax,U_SYSOS2_INOUTRES;
  127. xorl %eax,%eax
  128. LOPEN1:
  129. ; Returnwert ist in EAX
  130. leave
  131. ret $8
  132. end;
  133. end;
  134. function create(f : pchar):longint;
  135. begin
  136. asm
  137. movb $0x3c,%ah
  138. movl 8(%ebp),%edx
  139. xor %ecx,%ecx
  140. call ___syscall
  141. jnc Lcreate1
  142. movw %ax,U_SYSOS2_INOUTRES;
  143. xorl %eax,%eax
  144. Lcreate1:
  145. ; Returnwert ist in EAX
  146. leave
  147. ret $8
  148. end;
  149. end;
  150. procedure do_close(h:longint);
  151. begin
  152. asm
  153. movb $0x3e,%ah
  154. mov h,%ebx
  155. call ___syscall
  156. end;
  157. end;
  158. function dosfilepos(handle:longint) : longint;
  159. begin
  160. asm
  161. movb $0x42,%ah
  162. movb $0x1,%al
  163. movl 8(%ebp),%ebx
  164. xorl %edx,%edx
  165. call ___syscall
  166. jnc LDOSFILEPOS
  167. movw %ax,U_SYSOS2_INOUTRES;
  168. xorl %eax,%eax
  169. LDOSFILEPOS:
  170. leave
  171. ret $4
  172. end;
  173. end;
  174. procedure dosseek(handle:longint;pos:longint);
  175. begin
  176. asm
  177. movb $0x42,%ah
  178. xorb %al,%al
  179. movl 8(%ebp),%ebx
  180. movl 12(%ebp),%edx
  181. call ___syscall
  182. jnc LDOSSEEK1
  183. movw %ax,U_SYSOS2_INOUTRES;
  184. LDOSSEEK1:
  185. end;
  186. end;
  187. function dosfilesize(handle : longint):longint;
  188. function set_at_end(handle:longint) : longint;
  189. begin
  190. asm
  191. movb $0x42,%ah
  192. movb $0x2,%al
  193. ; Vorsicht Stack: 0 %ebp; 4 retaddr;
  194. ; 8 nextstackframe; 12 handle
  195. movl 12(%ebp),%ebx
  196. xorl %edx,%edx
  197. call ___syscall
  198. jnc Lset_at_end
  199. movw %ax,U_SYSOS2_INOUTRES;
  200. xorl %eax,%eax
  201. Lset_at_end:
  202. leave
  203. ret $8
  204. end;
  205. end;
  206. var tempfilesize,aktfilepos:longint;
  207. begin
  208. aktfilepos:=dosfilepos(handle);
  209. tempfilesize:=set_at_end(handle);
  210. dosseek(handle,aktfilepos);
  211. dosfilesize:=tempfilesize;
  212. end;
  213. procedure fileclosefunc(var t : textrec);
  214. begin
  215. do_close(t.handle);
  216. t.mode:=fmclosed;
  217. end;
  218. procedure fileopenfunc(var f:textrec);
  219. var b:array[0..255] of char;
  220. size:longint;
  221. begin
  222. move(f.name[1],b,length(f.name));
  223. b[length(f.name)]:=#0;
  224. f.inoutfunc:=@fileinoutfunc;
  225. f.flushfunc:=@fileinoutfunc;
  226. f.closefunc:=@fileclosefunc;
  227. case f.mode of
  228. fminput:
  229. f.handle:=open(b,0);
  230. fmoutput:
  231. f.handle:=create(b);
  232. fmappend:
  233. begin
  234. f.handle:=open(b,1);
  235. f.mode:=fmoutput;
  236. size:=dosfilesize(f.handle);
  237. if size>0 then
  238. begin
  239. {Set filepointer to eof character if present,
  240. or to end of file if not. Any change to the
  241. file causes the eof character to be overwritten,
  242. so we get a correct text file.}
  243. dosseek(f.handle,size-1);
  244. dosread(f.handle,longint(@b),1);
  245. if b[0]<>#26 then
  246. dosseek(f.handle,size);
  247. end;
  248. end;
  249. end;
  250. end;
  251. function eof(var t:text):boolean;[iocheck];
  252. var zoekpos:byte;
  253. begin
  254. { maybe we need new data }
  255. if textrec(t).bufpos+3>=textrec(t).bufend then
  256. dateifunc(textrec(t).inoutfunc)(textrec(t));
  257. eof:=dosfilesize(textrec(t).handle)<=dosfilepos(textrec(t).handle);
  258. if eof then
  259. eof:=textrec(t).bufend<=textrec(t).bufpos;
  260. if not eof then
  261. begin
  262. {If the next character is an end-of-file character,
  263. or if we are at eoln and first character on next line
  264. is eof then we should also return true.}
  265. zoekpos:=textrec(t).bufpos;
  266. while textrec(t).buffer[zoekpos] in [#13,#10] do
  267. inc(zoekpos);
  268. if zoekpos>textrec(t).bufpos+2 then
  269. eof:=false
  270. else
  271. eof:=textrec(t).buffer[zoekpos]=#26;
  272. end;
  273. end;
  274. {****************************************************************************
  275. File I/O related routines.
  276. ****************************************************************************}
  277. procedure doserase(p:Pchar);
  278. begin
  279. asm
  280. movl 8(%ebp),%edx
  281. movb $0x41,%ah
  282. call ___syscall
  283. jnc LERASE1
  284. movw %ax,U_SYSOS2_INOUTRES;
  285. LERASE1:
  286. end;
  287. end;
  288. procedure dosrename(p1,p2:Pchar);
  289. begin
  290. asm
  291. movl 8(%ebp),%edx
  292. movl 12(%ebp),%edi
  293. movb $0x56,%ah
  294. call ___syscall
  295. jnc LRENAME1
  296. movw %ax,U_SYSOS2_INOUTRES;
  297. LRENAME1:
  298. end;
  299. end;
  300. function dosread(h,addr,len:longint):longint;
  301. begin
  302. asm
  303. movl 16(%ebp),%ecx
  304. movl 12(%ebp),%edx
  305. movl 8(%ebp),%ebx
  306. movb $0x3f,%ah
  307. call ___syscall
  308. jnc LDOSREAD1
  309. movw %ax,U_SYSOS2_INOUTRES;
  310. xorl %eax,%eax
  311. LDOSREAD1:
  312. leave
  313. ret $12
  314. end;
  315. end;
  316. function doswrite(h,addr,len:longint) : longint;
  317. begin
  318. asm
  319. movl 16(%ebp),%ecx
  320. movl 12(%ebp),%edx
  321. movl 8(%ebp),%ebx
  322. movb $0x40,%ah
  323. call ___syscall
  324. jnc LDOSWRITE1
  325. movw %ax,U_SYSOS2_INOUTRES;
  326. LDOSWRITE1:
  327. movl %eax,-4(%ebp)
  328. end;
  329. end;
  330. procedure rewrite(var f:file;l:word);
  331. var b:array[0..255] of char;
  332. begin
  333. {According to Turbo Pascal helpfile, a file is automatically closed
  334. if it's open.}
  335. if filerec(f).mode<>fmclosed then
  336. close(f);
  337. filerec(f).mode:=fmoutput;
  338. move(filerec(f).name[1],b,length(filerec(f).name));
  339. b[length(filerec(f).name)]:=#0;
  340. filerec(f).handle:=create(b);
  341. filerec(f).recsize:=l;
  342. end;
  343. procedure rewrite(var f:file);
  344. begin
  345. rewrite(f,128);
  346. end;
  347. procedure reset(var f:file;l:word);
  348. var b:array[0..255] of char;
  349. begin
  350. {According to Turbo Pascal helpfile, a file is automatically closed
  351. if it's open.}
  352. if filerec(f).mode<>fmclosed then
  353. close(f);
  354. move(filerec(f).name[1],b,length(filerec(f).name));
  355. b[length(filerec(f).name)]:=#0;
  356. case filemode of
  357. 0:
  358. begin
  359. filerec(f).mode:=fminput;
  360. filerec(f).handle:=open(b,0);
  361. end;
  362. 1:
  363. begin
  364. filerec(f).mode:=fmoutput;
  365. filerec(f).handle:=open(b,1);
  366. end;
  367. 2:
  368. begin
  369. filerec(f).mode:=fminout;
  370. filerec(f).handle:=open(b,2);
  371. end;
  372. end;
  373. filerec(f).recsize:=l;
  374. end;
  375. procedure reset(var f:file);
  376. begin
  377. reset(f,128);
  378. end;
  379. procedure blockwrite(var f:file;var buf;count:longint);
  380. var p:pointer;
  381. size:longint;
  382. begin
  383. p:=@buf;
  384. doswrite(filerec(f).handle,longint(p),count*filerec(f).recsize);
  385. end;
  386. procedure blockread(var f:file;var buf;count:longint;var result:longint);
  387. begin
  388. result:=dosread(filerec(f).handle,longint(@buf),
  389. count*filerec(f).recsize) div filerec(f).recsize;
  390. end;
  391. procedure blockread(var f:file;var buf;count:longint);
  392. var result:longint;
  393. begin
  394. blockread(f,buf,count,result);
  395. end;
  396. procedure truncate (var f : file);[iocheck];
  397. var p : pointer;
  398. begin
  399. doswrite(filerec(f).handle,longint(p),0);
  400. end;
  401. procedure close(var f:file);
  402. begin
  403. if (filerec(f).mode<>fmclosed) then
  404. begin
  405. filerec(f).mode:=fmclosed;
  406. do_close(filerec(f).handle);
  407. end;
  408. end;
  409. function filepos(var f:file):longint;
  410. var l:longint;
  411. begin
  412. filepos:=dosfilepos(filerec(f).handle) div filerec(f).recsize;
  413. end;
  414. function filesize(var f:file) : longint;
  415. begin
  416. filesize:=dosfilesize(filerec(f).handle) div filerec(f).recsize;
  417. end;
  418. function eof(var f:file):boolean;[iocheck];
  419. begin
  420. eof:=filesize(f)<=filepos(f);
  421. end;
  422. procedure seek(var f:file;pos : longint);
  423. begin
  424. dosseek(filerec(f).handle,pos*filerec(f).recsize);
  425. end;
  426. {****************************************************************************
  427. Directory related routines.
  428. ****************************************************************************}
  429. procedure dos_dirs(func:byte;name:Pchar);
  430. begin
  431. asm
  432. movl 10(%ebp),%edx
  433. movb 8(%ebp),%ah
  434. call ___syscall
  435. jnc LDOS_DIRS1
  436. movw %ax,U_SYSOS2_INOUTRES;
  437. LDOS_DIRS1:
  438. leave
  439. ret $6
  440. end;
  441. end;
  442. procedure _dir(func:byte;const s:string);
  443. var buffer:array[0..255] of char;
  444. begin
  445. move(s[1],buffer,length(s));
  446. buffer[length(s)]:=#0;
  447. dos_dirs(func,buffer);
  448. end;
  449. procedure mkdir(const s:string);
  450. begin
  451. _dir($39,s);
  452. end;
  453. procedure rmdir(const s:string);
  454. begin
  455. _dir($3a,s);
  456. end;
  457. procedure chdir(const s:string);
  458. begin
  459. _dir($3b,s);
  460. end;
  461. { thanks to Michael Van Canneyt <[email protected]>, }
  462. { who wrote this code }
  463. procedure getdir(drivenr:byte;var dir:string);
  464. var temp:string;
  465. sof:pointer;
  466. i:byte;
  467. begin
  468. sof:=@dir[4];
  469. { dir[1..3] will contain '[drivenr]:\', but is not }
  470. { supplied by DOS, so we let dos string start at }
  471. { dir[4] }
  472. asm
  473. { Get dir from drivenr:0=default, 1=A etc... }
  474. movb drivenr,%dl
  475. { put (previously saved) offset in si }
  476. movl sof,%esi
  477. { call msdos function 47H : Get dir }
  478. mov $0x47,%ah
  479. { make the call }
  480. call ___syscall
  481. { Rem: if call unsuccesfull, carry is set, and AX has }
  482. { error code }
  483. end;
  484. { Now Dir should be filled with directory in ASCIIZ, }
  485. { starting from dir[4] }
  486. dir[0]:=#3;
  487. dir[2]:=':';
  488. dir[3]:='\';
  489. i:=4;
  490. { conversation to Pascal string }
  491. while (dir[i]<>#0) do
  492. begin
  493. { convert path name to DOS }
  494. if dir[i]='/' then
  495. dir[i]:='\';
  496. dir[0]:=chr(i);
  497. inc(i);
  498. end;
  499. { upcase the string (FPKPascal function) }
  500. dir:=upcase(dir);
  501. if drivenr<>0 then { Drive was supplied. We know it }
  502. dir[1]:=chr(65+drivenr-1)
  503. else
  504. begin
  505. { We need to get the current drive from DOS function 19H }
  506. { because the drive was the default, which can be unknown }
  507. asm
  508. movb $0x19,%ah
  509. call ___syscall
  510. addb $65,%al
  511. movb %al,i
  512. end;
  513. dir[1]:=chr(i)
  514. end;
  515. end;
  516. {****************************************************************************
  517. Heap management releated routines.
  518. ****************************************************************************}
  519. { this function allows to extend the heap by calling
  520. syscall $7f00 resizes the brk area}
  521. function sbrk(size:longint):longint;
  522. begin
  523. asm
  524. movl size,%edx
  525. movl $0x7f00,%ax
  526. int $0x21
  527. movl %eax,__RESULT
  528. end;
  529. end;
  530. function getheapstart:pointer;
  531. begin
  532. asm
  533. movl __heap_base,%eax
  534. leave
  535. ret
  536. end ['EAX'];
  537. end;
  538. {$i heap.inc}
  539. {***************************************************************************
  540. Runtime error checking related routines.
  541. ***************************************************************************}
  542. {$S-}
  543. procedure st1(stack_size:longint);[public,alias: 'STACKCHECK'];
  544. begin
  545. { called when trying to get local stack }
  546. { if the compiler directive $S is set }
  547. asm
  548. movl stack_size,%ebx
  549. movl %esp,%eax
  550. subl %ebx,%eax
  551. {$ifdef SYSTEMDEBUG}
  552. movl U_SYSOS2_LOWESTSTACK,%ebx
  553. cmpl %eax,%ebx
  554. jb _is_not_lowest
  555. movl %eax,U_SYSOS2_LOWESTSTACK
  556. _is_not_lowest:
  557. {$endif SYSTEMDEBUG}
  558. cmpb $2,U_SYSOS2_OS_MODE
  559. jne _running_in_dos
  560. movl U_SYSOS2_STACKBOTTOM,%ebx
  561. jmp _running_in_os2
  562. _running_in_dos:
  563. movl __heap_brk,%ebx
  564. _running_in_os2:
  565. cmpl %eax,%ebx
  566. jae __short_on_stack
  567. leave
  568. ret $4
  569. __short_on_stack:
  570. end ['EAX','EBX'];
  571. { this needs a local variable }
  572. { so the function called itself !! }
  573. { Writeln('low in stack ');}
  574. RunError(202);
  575. end;
  576. {no stack check in system }
  577. {****************************************************************************
  578. System unit initialization.
  579. ****************************************************************************}
  580. var
  581. pib:Pprocessinfoblock;
  582. tib:Pthreadinfoblock;
  583. begin
  584. {Determine the operating system we are running on.}
  585. asm
  586. movw $0x7f0a,%ax
  587. call ___syscall
  588. test $512,%bx ; Bit 9 is OS/2 flag.
  589. setnzb U_SYSOS2_OS_MODE
  590. test $4096,%bx
  591. jz _noRSX
  592. movb $2,U_SYSOS2_OS_MODE
  593. _noRSX:
  594. end;
  595. {Now request, if we are running under DOS,
  596. read-access to the first meg. of memory.}
  597. if os_mode in [osDOS,osDPMI] then
  598. asm
  599. mov $0x7f13,%ax
  600. xor %ebx,%ebx
  601. mov $0xfff,%ecx
  602. xor %edx,%edx
  603. call ___syscall
  604. mov %eax,U_SYSOS2_FIRST_MEG
  605. end
  606. else
  607. first_meg:=nil;
  608. {At 0.9.2, case for enumeration does not work.}
  609. case os_mode of
  610. osDOS:
  611. stackbottom:=0;
  612. osOS2:
  613. begin
  614. _DosGetInfoBlocks(tib,pib);
  615. stackbottom:=longint(tib^.stack);
  616. end;
  617. osDPMI:
  618. stackbottom:=0; {Not sure how to get it, but seems to be
  619. always zero.}
  620. end;
  621. exitproc:=nil;
  622. {Initialize the heap.}
  623. InitHeap;
  624. { to test stack depth }
  625. loweststack:=maxlongint;
  626. {Enable the brk area by initializing it with the initial heap size.}
  627. asm
  628. mov $0x7f01,%ax
  629. movl HEAPSIZE,%edx
  630. call ___syscall
  631. end;
  632. { Ein- und Ausgabe initialisieren }
  633. assign(input,'');
  634. textrec(input).handle:=0;
  635. textrec(input).mode:=fminput;
  636. textrec(input).inoutfunc:=@fileinoutfunc;
  637. textrec(input).flushfunc:=@fileinoutfunc;
  638. assign(output,'');
  639. textrec(output).handle:=1;
  640. textrec(output).mode:=fmoutput;
  641. textrec(output).inoutfunc:=@fileinoutfunc;
  642. textrec(output).flushfunc:=@fileinoutfunc;
  643. textrec(input).mode:=fminput;
  644. { kein Ein- Ausgabefehler }
  645. inoutres:=0;
  646. end.