sysos2.pas 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732
  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. FPK-Pascal is distributed in the hope that it will be useful,
  14. but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. Library GNU General Public License for more details.
  17. You should have received a copy of the Library GNU General Public License
  18. along with FPK-Pascal; see the file COPYING.LIB. If not, write to
  19. the Free Software Foundation, 59 Temple Place - Suite 330,
  20. Boston, MA 02111-1307, USA.
  21. ****************************************************************************}
  22. unit sysos2;
  23. {Changelog:
  24. People:
  25. DM - Dani‰l Mantione
  26. Date: Description of change: Changed by:
  27. - First released version 0.1. DM
  28. Coding style:
  29. My coding style is a bit unusual for Pascal. Nevertheless I friendly ask
  30. you to try to make your changes not look all to different. In general,
  31. set your IDE to use tab characters, optimal fill on and a tabsize of 4.}
  32. {$I os.inc}
  33. interface
  34. {Link the startup code.}
  35. {$l prt1.oo2}
  36. {$I SYSTEMH.INC}
  37. {$I heaph.inc}
  38. type Tos=(osDOS,osOS2,osDPMI);
  39. var os_mode:Tos;
  40. first_meg:pointer;
  41. type Psysthreadib=^Tsysthreadib;
  42. Pthreadinfoblock=^Tthreadinfoblock;
  43. Pprocessinfoblock=^Tprocessinfoblock;
  44. Tbytearray=array[0..$ffff] of byte;
  45. Pbytearray=^Tbytearray;
  46. Tsysthreadib=record
  47. tid,
  48. priority,
  49. version:longint;
  50. MCcount,
  51. MCforceflag:word;
  52. end;
  53. Tthreadinfoblock=record
  54. pexchain,
  55. stack,
  56. stacklimit:pointer;
  57. tib2:Psysthreadib;
  58. version,
  59. ordinal:longint;
  60. end;
  61. Tprocessinfoblock=record
  62. pid,
  63. parentpid,
  64. hmte:longint;
  65. cmd,
  66. env:Pbytearray;
  67. flstatus,
  68. ttype:longint;
  69. end;
  70. const UnusedHandle=$ffff;
  71. StdInputHandle=0;
  72. StdOutputHandle=1;
  73. StdErrorHandle=2;
  74. implementation
  75. { die betriebssystemunabhangigen Implementationen einfuegen: }
  76. {$I SYSTEM.INC}
  77. procedure dosgetinfoblocks(var Atib:Pthreadinfoblock;
  78. var Apib:Pprocessinfoblock);
  79. external 'DOSCALLS' index 312;
  80. {***************************************************************************
  81. Runtime error checking related routines.
  82. ***************************************************************************}
  83. {$S-}
  84. procedure st1(stack_size:longint);[public,alias: 'STACKCHECK'];
  85. begin
  86. { called when trying to get local stack }
  87. { if the compiler directive $S is set }
  88. asm
  89. movl stack_size,%ebx
  90. movl %esp,%eax
  91. subl %ebx,%eax
  92. {$ifdef SYSTEMDEBUG}
  93. movl U_SYSOS2_LOWESTSTACK,%ebx
  94. cmpl %eax,%ebx
  95. jb _is_not_lowest
  96. movl %eax,U_SYSOS2_LOWESTSTACK
  97. _is_not_lowest:
  98. {$endif SYSTEMDEBUG}
  99. cmpb $2,U_SYSOS2_OS_MODE
  100. jne _running_in_dos
  101. movl U_SYSOS2_STACKBOTTOM,%ebx
  102. jmp _running_in_os2
  103. _running_in_dos:
  104. movl __heap_brk,%ebx
  105. _running_in_os2:
  106. cmpl %eax,%ebx
  107. jae __short_on_stack
  108. leave
  109. ret $4
  110. __short_on_stack:
  111. end ['EAX','EBX'];
  112. { this needs a local variable }
  113. { so the function called itself !! }
  114. { Writeln('low in stack ');}
  115. RunError(202);
  116. end;
  117. {no stack check in system }
  118. {****************************************************************************
  119. Miscelleanious related routines.
  120. ****************************************************************************}
  121. procedure halt(errnum:byte);
  122. begin
  123. asm
  124. movb $0x4c,%ah
  125. movb errnum,%al
  126. call ___SYSCALL
  127. end;
  128. end;
  129. function paramcount:longint;
  130. begin
  131. asm
  132. movl _argc,%eax
  133. decl %eax
  134. leave
  135. ret
  136. end ['EAX'];
  137. end;
  138. function paramstr(l:longint):string;
  139. function args:pointer;
  140. begin
  141. asm
  142. movl _argv,%eax
  143. leave
  144. ret
  145. end ['EAX'];
  146. end;
  147. var p:^Pchar;
  148. begin
  149. if (l>=0) and (l<=paramcount) then
  150. begin
  151. p:=args;
  152. paramstr:=strpas(p[l]);
  153. end
  154. else paramstr:='';
  155. end;
  156. procedure randomize;
  157. var hl:longint;
  158. begin
  159. asm
  160. movb $0x2c,%ah
  161. call ___SYSCALL
  162. movw %cx,-4(%ebp)
  163. movw %dx,-2(%ebp)
  164. end;
  165. randseed:=hl;
  166. end;
  167. {****************************************************************************
  168. Heap management releated routines.
  169. ****************************************************************************}
  170. { this function allows to extend the heap by calling
  171. syscall $7f00 resizes the brk area}
  172. function sbrk(size:longint):longint;
  173. begin
  174. asm
  175. movl size,%edx
  176. movw $0x7f00,%ax
  177. call ___SYSCALL
  178. movl %eax,__RESULT
  179. end;
  180. end;
  181. function getheapstart:pointer;
  182. begin
  183. asm
  184. movl __heap_base,%eax
  185. leave
  186. ret
  187. end ['EAX'];
  188. end;
  189. {$i heap.inc}
  190. {****************************************************************************
  191. Low Level File Routines
  192. ****************************************************************************}
  193. procedure allowslash(p:Pchar);
  194. {Allow slash as backslash.}
  195. var i:longint;
  196. begin
  197. for i:=0 to strlen(p) do
  198. if p[i]='/' then p[i]:='\';
  199. end;
  200. procedure do_close(h:longint);
  201. begin
  202. asm
  203. movb $0x3e,%ah
  204. mov h,%ebx
  205. call ___SYSCALL
  206. end;
  207. end;
  208. procedure do_erase(p:Pchar);
  209. begin
  210. allowslash(p);
  211. asm
  212. movl 8(%ebp),%edx
  213. movb $0x41,%ah
  214. call ___SYSCALL
  215. jnc LERASE1
  216. movw %ax,U_SYSOS2_INOUTRES;
  217. LERASE1:
  218. end;
  219. end;
  220. procedure do_rename(p1,p2:Pchar);
  221. begin
  222. allowslash(p1);
  223. allowslash(p2);
  224. asm
  225. movl 8(%ebp),%edx
  226. movl 12(%ebp),%edi
  227. movb $0x56,%ah
  228. call ___SYSCALL
  229. jnc LRENAME1
  230. movw %ax,U_SYSOS2_INOUTRES;
  231. LRENAME1:
  232. end;
  233. end;
  234. function do_read(h,addr,len:longint):longint;
  235. begin
  236. asm
  237. movl 16(%ebp),%ecx
  238. movl 12(%ebp),%edx
  239. movl 8(%ebp),%ebx
  240. movb $0x3f,%ah
  241. call ___SYSCALL
  242. jnc LDOSREAD1
  243. movw %ax,U_SYSOS2_INOUTRES;
  244. xorl %eax,%eax
  245. LDOSREAD1:
  246. leave
  247. ret $12
  248. end;
  249. end;
  250. function do_write(h,addr,len:longint) : longint;
  251. begin
  252. asm
  253. movl 16(%ebp),%ecx
  254. movl 12(%ebp),%edx
  255. movl 8(%ebp),%ebx
  256. movb $0x40,%ah
  257. call ___SYSCALL
  258. jnc LDOSWRITE1
  259. movw %ax,U_SYSOS2_INOUTRES;
  260. LDOSWRITE1:
  261. movl %eax,-4(%ebp)
  262. end;
  263. end;
  264. function do_filepos(handle:longint):longint;
  265. begin
  266. asm
  267. movw $0x4201,%ax
  268. movl 8(%ebp),%ebx
  269. xorl %edx,%edx
  270. call ___SYSCALL
  271. jnc LDOSFILEPOS
  272. movw %ax,U_SYSOS2_INOUTRES;
  273. xorl %eax,%eax
  274. LDOSFILEPOS:
  275. leave
  276. ret $4
  277. end;
  278. end;
  279. procedure do_seek(handle,pos:longint);
  280. begin
  281. asm
  282. movw $0x4200,%ax
  283. movl 8(%ebp),%ebx
  284. movl 12(%ebp),%edx
  285. call ___SYSCALL
  286. jnc .LDOSSEEK1
  287. movw %ax,U_SYSOS2_INOUTRES;
  288. .LDOSSEEK1:
  289. leave
  290. ret $8
  291. end;
  292. end;
  293. function do_seekend(handle:longint):longint;
  294. begin
  295. asm
  296. movw $0x4202,%ax
  297. movl 8(%ebp),%ebx
  298. xorl %edx,%edx
  299. call ___SYSCALL
  300. jnc .Lset_at_end1
  301. movw %ax,U_SYSOS2_INOUTRES;
  302. xorl %eax,%eax
  303. .Lset_at_end1:
  304. leave
  305. ret $4
  306. end;
  307. end;
  308. function do_filesize(handle:longint):longint;
  309. var aktfilepos:longint;
  310. begin
  311. aktfilepos:=do_filepos(handle);
  312. do_filesize:=do_seekend(handle);
  313. do_seek(handle,aktfilepos);
  314. end;
  315. procedure do_truncate(handle,pos:longint);
  316. begin
  317. asm
  318. movl $0x4200,%eax
  319. movl 8(%ebp),%ebx
  320. movl 12(%ebp),%edx
  321. call ___SYSCALL
  322. jc .LTruncate1
  323. movl 8(%ebp),%ebx
  324. movl 12(%ebp),%edx
  325. movl %ebp,%edx
  326. xorl %ecx,%ecx
  327. movb $0x40,%ah
  328. call ___SYSCALL
  329. jnc .LTruncate2
  330. .LTruncate1:
  331. movw %ax,U_SYSOS2_INOUTRES;
  332. .LTruncate2:
  333. leave
  334. ret $8
  335. end;
  336. end;
  337. procedure do_open(var f;p:pchar;flags:longint);
  338. {
  339. filerec and textrec have both handle and mode as the first items so
  340. they could use the same routine for opening/creating.
  341. when (flags and $10) the file will be append
  342. when (flags and $100) the file will be truncate/rewritten
  343. when (flags and $1000) there is no check for close (needed for textfiles)
  344. }
  345. var oflags:byte;
  346. begin
  347. allowslash(p);
  348. { close first if opened }
  349. if ((flags and $1000)=0) then
  350. begin
  351. case filerec(f).mode of
  352. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  353. fmclosed:;
  354. else
  355. begin
  356. inoutres:=102; {not assigned}
  357. exit;
  358. end;
  359. end;
  360. end;
  361. { reset file handle }
  362. filerec(f).handle:=high(word);
  363. oflags:=2;
  364. { convert filemode to filerec modes }
  365. case (flags and 3) of
  366. 0 : begin
  367. filerec(f).mode:=fminput;
  368. oflags:=0;
  369. end;
  370. 1 : filerec(f).mode:=fmoutput;
  371. 2 : filerec(f).mode:=fminout;
  372. end;
  373. if (flags and $100)<>0 then
  374. begin
  375. filerec(f).mode:=fmoutput;
  376. oflags:=2;
  377. end
  378. else
  379. if (flags and $10)<>0 then
  380. begin
  381. filerec(f).mode:=fmoutput;
  382. oflags:=2;
  383. end;
  384. { empty name is special }
  385. if p[0]=#0 then
  386. begin
  387. case filerec(f).mode of
  388. fminput:filerec(f).handle:=StdInputHandle;
  389. fmappend,fmoutput : begin
  390. filerec(f).handle:=StdOutputHandle;
  391. filerec(f).mode:=fmoutput; {fool fmappend}
  392. end;
  393. end;
  394. exit;
  395. end;
  396. if (flags and $100)<>0 then
  397. {Use create function.}
  398. asm
  399. movb $0x3c,%ah
  400. movl p,%edx
  401. xorw %cx,%cx
  402. call ___SYSCALL
  403. jnc LOPEN1
  404. movw %ax,U_SYSOS2_INOUTRES;
  405. movw $0xffff,%ax
  406. LOPEN1:
  407. movl f,%edx
  408. movw %ax,(%edx)
  409. end
  410. else
  411. {Use open function.}
  412. asm
  413. movb $0x3d,%ah
  414. movb oflags,%al
  415. movl p,%edx
  416. call ___SYSCALL
  417. jnc LOPEN2
  418. movw %ax,U_SYSOS2_INOUTRES;
  419. movw $0xffff,%ax
  420. LOPEN2:
  421. movl f,%edx
  422. movw %ax,(%edx)
  423. end;
  424. if (flags and $10)<>0 then
  425. do_seekend(filerec(f).handle);
  426. end;
  427. {*****************************************************************************
  428. UnTyped File Handling
  429. *****************************************************************************}
  430. {$i file.inc}
  431. {*****************************************************************************
  432. Typed File Handling
  433. *****************************************************************************}
  434. {$i typefile.inc}
  435. {*****************************************************************************
  436. Text File Handling
  437. *****************************************************************************}
  438. {$DEFINE EOF_CTRLZ}
  439. {$i text.inc}
  440. {****************************************************************************
  441. Directory related routines.
  442. ****************************************************************************}
  443. {*****************************************************************************
  444. Directory Handling
  445. *****************************************************************************}
  446. procedure dosdir(func:byte;const s:string);
  447. var buffer:array[0..255] of char;
  448. begin
  449. move(s[1],buffer,length(s));
  450. buffer[length(s)]:=#0;
  451. allowslash(Pchar(@buffer));
  452. asm
  453. leal buffer,%edx
  454. movb 8(%ebp),%ah
  455. call ___SYSCALL
  456. jnc .LDOS_DIRS1
  457. movw %ax,U_SYSOS2_INOUTRES;
  458. .LDOS_DIRS1:
  459. end;
  460. end;
  461. procedure mkdir(const s : string);
  462. begin
  463. DosDir($39,s);
  464. end;
  465. procedure rmdir(const s : string);
  466. begin
  467. DosDir($3a,s);
  468. end;
  469. procedure chdir(const s : string);
  470. begin
  471. DosDir($3b,s);
  472. end;
  473. procedure getdir(drivenr : byte;var dir : string);
  474. {Written by Michael Van Canneyt.}
  475. var temp:array[0..255] of char;
  476. sof:Pchar;
  477. i:byte;
  478. begin
  479. sof:=pchar(@dir[4]);
  480. { dir[1..3] will contain '[drivenr]:\', but is not }
  481. { supplied by DOS, so we let dos string start at }
  482. { dir[4] }
  483. { Get dir from drivenr : 0=default, 1=A etc... }
  484. asm
  485. movb drivenr,%dl
  486. movl sof,%esi
  487. mov $0x47,%ah
  488. call ___SYSCALL
  489. end;
  490. { Now Dir should be filled with directory in ASCIIZ, }
  491. { starting from dir[4] }
  492. dir[0]:=#3;
  493. dir[2]:=':';
  494. dir[3]:='\';
  495. i:=4;
  496. {Conversion to Pascal string }
  497. while (dir[i]<>#0) do
  498. begin
  499. { convert path name to DOS }
  500. if dir[i]='/' then
  501. dir[i]:='\';
  502. dir[0]:=char(i);
  503. inc(i);
  504. end;
  505. { upcase the string (FPKPascal function) }
  506. dir:=upcase(dir);
  507. if drivenr<>0 then { Drive was supplied. We know it }
  508. dir[1]:=char(65+drivenr-1)
  509. else
  510. begin
  511. { We need to get the current drive from DOS function 19H }
  512. { because the drive was the default, which can be unknown }
  513. asm
  514. movb $0x19,%ah
  515. call ___SYSCALL
  516. addb $65,%al
  517. movb %al,i
  518. end;
  519. dir[1]:=char(i);
  520. end;
  521. end;
  522. {****************************************************************************
  523. System unit initialization.
  524. ****************************************************************************}
  525. procedure OpenStdIO(var f:text;mode:word;hdl:longint);
  526. begin
  527. Assign(f,'');
  528. TextRec(f).Handle:=hdl;
  529. TextRec(f).Mode:=mode;
  530. TextRec(f).InOutFunc:=@FileInOutFunc;
  531. TextRec(f).FlushFunc:=@FileInOutFunc;
  532. TextRec(f).Closefunc:=@fileclosefunc;
  533. end;
  534. var pib:Pprocessinfoblock;
  535. tib:Pthreadinfoblock;
  536. begin
  537. {Determine the operating system we are running on.}
  538. asm
  539. movw $0x7f0a,%ax
  540. call ___SYSCALL
  541. test $512,%bx {Bit 9 is OS/2 flag.}
  542. setnzb U_SYSOS2_OS_MODE
  543. test $4096,%bx
  544. jz _noRSX
  545. movb $2,U_SYSOS2_OS_MODE
  546. _noRSX:
  547. end;
  548. {Enable the brk area by initializing it with the initial heap size.}
  549. asm
  550. mov $0x7f01,%ax
  551. movl HEAPSIZE,%edx
  552. addl __heap_base,%edx
  553. call ___SYSCALL
  554. cmpl $-1,%eax
  555. jnz _heapok
  556. pushl $204
  557. call _SYSOS2$$_RUNERROR$WORD
  558. _heapok:
  559. end;
  560. {Now request, if we are running under DOS,
  561. read-access to the first meg. of memory.}
  562. if os_mode in [osDOS,osDPMI] then
  563. asm
  564. mov $0x7f13,%ax
  565. xor %ebx,%ebx
  566. mov $0xfff,%ecx
  567. xor %edx,%edx
  568. call ___SYSCALL
  569. mov %eax,U_SYSOS2_FIRST_MEG
  570. end
  571. else
  572. first_meg:=nil;
  573. {At 0.9.2, case for enumeration does not work.}
  574. case os_mode of
  575. osDOS:
  576. stackbottom:=0; {In DOS mode, heap_brk is also the
  577. stack bottom.}
  578. osOS2:
  579. begin
  580. dosgetinfoblocks(tib,pib);
  581. stackbottom:=longint(tib^.stack);
  582. end;
  583. osDPMI:
  584. stackbottom:=0; {Not sure how to get it, but seems to be
  585. always zero.}
  586. end;
  587. exitproc:=nil;
  588. {Initialize the heap.}
  589. initheap;
  590. { to test stack depth }
  591. loweststack:=maxlongint;
  592. OpenStdIO(Input,fmInput,StdInputHandle);
  593. OpenStdIO(Output,fmOutput,StdOutputHandle);
  594. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  595. { kein Ein- Ausgabefehler }
  596. inoutres:=0;
  597. end.