sysos2.pas 17 KB

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