sysos2.pas 17 KB

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