sysos2.pas 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790
  1. {****************************************************************************
  2. Free Pascal -- OS/2 runtime library
  3. Copyright (c) 1999-2000 by Florian Kl„mpfl
  4. Copyright (c) 1999-2000 by Daniel Mantione
  5. Free 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 Free 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 Free Pascal source code file.>
  12. Send us your modified files, we can work together if you want!
  13. Free 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 Free 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 - Daniel 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); cdecl;
  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 system_exit;
  130. begin
  131. asm
  132. movb $0x4c,%ah
  133. movb exitcode,%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. { Only three standard handles under real OS/2 }
  207. if (h > 4) or
  208. (os_MODE = osOS2) and (h > 2) then
  209. begin
  210. asm
  211. movb $0x3e,%ah
  212. mov h,%ebx
  213. call syscall
  214. end;
  215. end;
  216. end;
  217. procedure do_erase(p:Pchar);
  218. begin
  219. allowslash(p);
  220. asm
  221. movl 8(%ebp),%edx
  222. movb $0x41,%ah
  223. call syscall
  224. jnc .LERASE1
  225. movw %ax,inoutres;
  226. .LERASE1:
  227. end;
  228. end;
  229. procedure do_rename(p1,p2:Pchar);
  230. begin
  231. allowslash(p1);
  232. allowslash(p2);
  233. asm
  234. movl 8(%ebp),%edx
  235. movl 12(%ebp),%edi
  236. movb $0x56,%ah
  237. call syscall
  238. jnc .LRENAME1
  239. movw %ax,inoutres;
  240. .LRENAME1:
  241. end;
  242. end;
  243. function do_read(h,addr,len:longint):longint;
  244. begin
  245. asm
  246. movl 16(%ebp),%ecx
  247. movl 12(%ebp),%edx
  248. movl 8(%ebp),%ebx
  249. movb $0x3f,%ah
  250. call syscall
  251. jnc .LDOSREAD1
  252. movw %ax,inoutres;
  253. xorl %eax,%eax
  254. .LDOSREAD1:
  255. leave
  256. ret $12
  257. end;
  258. end;
  259. function do_write(h,addr,len:longint) : longint;
  260. begin
  261. asm
  262. movl 16(%ebp),%ecx
  263. movl 12(%ebp),%edx
  264. movl 8(%ebp),%ebx
  265. movb $0x40,%ah
  266. call syscall
  267. jnc .LDOSWRITE1
  268. movw %ax,inoutres;
  269. .LDOSWRITE1:
  270. movl %eax,-4(%ebp)
  271. end;
  272. end;
  273. function do_filepos(handle:longint):longint;
  274. begin
  275. asm
  276. movw $0x4201,%ax
  277. movl 8(%ebp),%ebx
  278. xorl %edx,%edx
  279. call syscall
  280. jnc .LDOSFILEPOS
  281. movw %ax,inoutres;
  282. xorl %eax,%eax
  283. .LDOSFILEPOS:
  284. leave
  285. ret $4
  286. end;
  287. end;
  288. procedure do_seek(handle,pos:longint);
  289. begin
  290. asm
  291. movw $0x4200,%ax
  292. movl 8(%ebp),%ebx
  293. movl 12(%ebp),%edx
  294. call syscall
  295. jnc .LDOSSEEK1
  296. movw %ax,inoutres;
  297. .LDOSSEEK1:
  298. leave
  299. ret $8
  300. end;
  301. end;
  302. function do_seekend(handle:longint):longint;
  303. begin
  304. asm
  305. movw $0x4202,%ax
  306. movl 8(%ebp),%ebx
  307. xorl %edx,%edx
  308. call syscall
  309. jnc .Lset_at_end1
  310. movw %ax,inoutres;
  311. xorl %eax,%eax
  312. .Lset_at_end1:
  313. leave
  314. ret $4
  315. end;
  316. end;
  317. function do_filesize(handle:longint):longint;
  318. var aktfilepos:longint;
  319. begin
  320. aktfilepos:=do_filepos(handle);
  321. do_filesize:=do_seekend(handle);
  322. do_seek(handle,aktfilepos);
  323. end;
  324. procedure do_truncate(handle,pos:longint);
  325. begin
  326. asm
  327. movl $0x4200,%eax
  328. movl 8(%ebp),%ebx
  329. movl 12(%ebp),%edx
  330. call syscall
  331. jc .LTruncate1
  332. movl 8(%ebp),%ebx
  333. movl 12(%ebp),%edx
  334. movl %ebp,%edx
  335. xorl %ecx,%ecx
  336. movb $0x40,%ah
  337. call syscall
  338. jnc .LTruncate2
  339. .LTruncate1:
  340. movw %ax,inoutres;
  341. .LTruncate2:
  342. leave
  343. ret $8
  344. end;
  345. end;
  346. procedure do_open(var f;p:pchar;flags:longint);
  347. {
  348. filerec and textrec have both handle and mode as the first items so
  349. they could use the same routine for opening/creating.
  350. when (flags and $100) the file will be append
  351. when (flags and $1000) the file will be truncate/rewritten
  352. when (flags and $10000) there is no check for close (needed for textfiles)
  353. }
  354. var oflags:byte;
  355. begin
  356. allowslash(p);
  357. { close first if opened }
  358. if ((flags and $10000)=0) then
  359. begin
  360. case filerec(f).mode of
  361. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  362. fmclosed:;
  363. else
  364. begin
  365. inoutres:=102; {not assigned}
  366. exit;
  367. end;
  368. end;
  369. end;
  370. { reset file handle }
  371. filerec(f).handle:=high(word);
  372. oflags:=2;
  373. { convert filemode to filerec modes }
  374. case (flags and 3) of
  375. 0 : begin
  376. filerec(f).mode:=fminput;
  377. oflags:=0;
  378. end;
  379. 1 : filerec(f).mode:=fmoutput;
  380. 2 : filerec(f).mode:=fminout;
  381. end;
  382. if (flags and $1000)<>0 then
  383. begin
  384. filerec(f).mode:=fmoutput;
  385. oflags:=2;
  386. end
  387. else
  388. if (flags and $100)<>0 then
  389. begin
  390. filerec(f).mode:=fmoutput;
  391. oflags:=2;
  392. end;
  393. { empty name is special }
  394. if p[0]=#0 then
  395. begin
  396. case FileRec(f).mode of
  397. fminput :
  398. FileRec(f).Handle:=StdInputHandle;
  399. fminout, { this is set by rewrite }
  400. fmoutput :
  401. FileRec(f).Handle:=StdOutputHandle;
  402. fmappend :
  403. begin
  404. FileRec(f).Handle:=StdOutputHandle;
  405. FileRec(f).mode:=fmoutput; {fool fmappend}
  406. end;
  407. end;
  408. exit;
  409. end;
  410. if (flags and $1000)<>0 then
  411. {Use create function.}
  412. asm
  413. movb $0x3c,%ah
  414. movl p,%edx
  415. xorw %cx,%cx
  416. call syscall
  417. jnc .LOPEN1
  418. movw %ax,inoutres;
  419. movw $0xffff,%ax
  420. .LOPEN1:
  421. movl f,%edx
  422. movw %ax,(%edx)
  423. end
  424. else
  425. {Use open function.}
  426. asm
  427. movb $0x3d,%ah
  428. movb oflags,%al
  429. movl p,%edx
  430. call syscall
  431. jnc .LOPEN2
  432. movw %ax,inoutres;
  433. movw $0xffff,%ax
  434. .LOPEN2:
  435. movl f,%edx
  436. movw %ax,(%edx)
  437. end;
  438. if (flags and $100)<>0 then
  439. do_seekend(filerec(f).handle);
  440. end;
  441. function do_isdevice(handle:longint):boolean;
  442. begin
  443. do_isdevice:=(handle<=5);
  444. end;
  445. {*****************************************************************************
  446. UnTyped File Handling
  447. *****************************************************************************}
  448. {$i file.inc}
  449. {*****************************************************************************
  450. Typed File Handling
  451. *****************************************************************************}
  452. {$i typefile.inc}
  453. {*****************************************************************************
  454. Text File Handling
  455. *****************************************************************************}
  456. {$DEFINE EOF_CTRLZ}
  457. {$i text.inc}
  458. {****************************************************************************
  459. Directory related routines.
  460. ****************************************************************************}
  461. {*****************************************************************************
  462. Directory Handling
  463. *****************************************************************************}
  464. procedure dosdir(func:byte;const s:string);
  465. var buffer:array[0..255] of char;
  466. begin
  467. move(s[1],buffer,length(s));
  468. buffer[length(s)]:=#0;
  469. allowslash(Pchar(@buffer));
  470. asm
  471. leal buffer,%edx
  472. movb 8(%ebp),%ah
  473. call syscall
  474. jnc .LDOS_DIRS1
  475. movw %ax,inoutres;
  476. .LDOS_DIRS1:
  477. end;
  478. end;
  479. procedure mkdir(const s : string);
  480. begin
  481. DosDir($39,s);
  482. end;
  483. procedure rmdir(const s : string);
  484. begin
  485. DosDir($3a,s);
  486. end;
  487. procedure chdir(const s : string);
  488. begin
  489. DosDir($3b,s);
  490. end;
  491. procedure getdir(drivenr : byte;var dir : shortstring);
  492. {Written by Michael Van Canneyt.}
  493. var temp:array[0..255] of char;
  494. sof:Pchar;
  495. i:byte;
  496. begin
  497. sof:=pchar(@dir[4]);
  498. { dir[1..3] will contain '[drivenr]:\', but is not }
  499. { supplied by DOS, so we let dos string start at }
  500. { dir[4] }
  501. { Get dir from drivenr : 0=default, 1=A etc... }
  502. asm
  503. movb drivenr,%dl
  504. movl sof,%esi
  505. mov $0x47,%ah
  506. call syscall
  507. end;
  508. { Now Dir should be filled with directory in ASCIIZ, }
  509. { starting from dir[4] }
  510. dir[0]:=#3;
  511. dir[2]:=':';
  512. dir[3]:='\';
  513. i:=4;
  514. {Conversion to Pascal string }
  515. while (dir[i]<>#0) do
  516. begin
  517. { convert path name to DOS }
  518. if dir[i]='/' then
  519. dir[i]:='\';
  520. dir[0]:=char(i);
  521. inc(i);
  522. end;
  523. { upcase the string (FPC function) }
  524. dir:=upcase(dir);
  525. if drivenr<>0 then { Drive was supplied. We know it }
  526. dir[1]:=char(65+drivenr-1)
  527. else
  528. begin
  529. { We need to get the current drive from DOS function 19H }
  530. { because the drive was the default, which can be unknown }
  531. asm
  532. movb $0x19,%ah
  533. call syscall
  534. addb $65,%al
  535. movb %al,i
  536. end;
  537. dir[1]:=char(i);
  538. end;
  539. end;
  540. {****************************************************************************
  541. System unit initialization.
  542. ****************************************************************************}
  543. var pib:Pprocessinfoblock;
  544. tib:Pthreadinfoblock;
  545. begin
  546. {Determine the operating system we are running on.}
  547. asm
  548. movl $0,os_mode
  549. movw $0x7f0a,%ax
  550. call syscall
  551. testw$512,%bx {Bit 9 is OS/2 flag.}
  552. setnzb os_mode
  553. testw $4096,%bx
  554. jz .LnoRSX
  555. movl $2,os_mode
  556. .LnoRSX:
  557. end;
  558. {$ASMMODE DIRECT}
  559. {Enable the brk area by initializing it with the initial heap size.}
  560. asm
  561. movw $0x7f01,%ax
  562. movl HEAPSIZE,%edx
  563. addl __heap_base,%edx
  564. call ___SYSCALL
  565. cmpl $-1,%eax
  566. jnz Lheapok
  567. pushl $204
  568. {call RUNERROR$$WORD}
  569. Lheapok:
  570. end;
  571. {$ASMMODE ATT}
  572. {Now request, if we are running under DOS,
  573. read-access to the first meg. of memory.}
  574. if os_mode in [osDOS,osDPMI] then
  575. asm
  576. movw $0x7f13,%ax
  577. xorl %ebx,%ebx
  578. movl $0xfff,%ecx
  579. xorl %edx,%edx
  580. call syscall
  581. movl %eax,first_meg
  582. end
  583. else
  584. first_meg:=nil;
  585. {At 0.9.2, case for enumeration does not work.}
  586. case os_mode of
  587. osDOS:
  588. stackbottom:=0; {In DOS mode, heap_brk is also the
  589. stack bottom.}
  590. osOS2:
  591. begin
  592. dosgetinfoblocks(tib,pib);
  593. stackbottom:=longint(tib^.stack);
  594. end;
  595. osDPMI:
  596. stackbottom:=0; {Not sure how to get it, but seems to be
  597. always zero.}
  598. end;
  599. exitproc:=nil;
  600. {Initialize the heap.}
  601. initheap;
  602. { ... and exceptions }
  603. InitExceptions;
  604. { to test stack depth }
  605. loweststack:=maxlongint;
  606. OpenStdIO(Input,fmInput,StdInputHandle);
  607. OpenStdIO(Output,fmOutput,StdOutputHandle);
  608. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  609. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  610. { no I/O-Error }
  611. inoutres:=0;
  612. end.
  613. {
  614. $Log$
  615. Revision 1.25 2000-02-09 12:39:11 peter
  616. * halt moved to system.inc
  617. Revision 1.24 2000/01/20 23:38:02 peter
  618. * support fm_inout as stdoutput for assign(f,'');rewrite(f,1); becuase
  619. rewrite opens always with filemode 2
  620. Revision 1.23 2000/01/16 23:10:15 peter
  621. * handle check fixed
  622. Revision 1.22 2000/01/16 22:25:38 peter
  623. * check handle for file closing
  624. Revision 1.21 2000/01/09 20:45:58 hajny
  625. * FPK changed to FPC
  626. Revision 1.20 2000/01/07 16:41:50 daniel
  627. * copyright 2000
  628. Revision 1.19 2000/01/07 16:32:33 daniel
  629. * copyright 2000 added
  630. Revision 1.18 2000/01/02 17:45:25 hajny
  631. * cdecl added for doscalls routines
  632. Revision 1.17 1999/09/10 15:40:35 peter
  633. * fixed do_open flags to be > $100, becuase filemode can be upto 255
  634. Revision 1.16 1999/06/01 13:23:16 peter
  635. * fixes to work with the new makefile
  636. * os2 compiles now correct under linux
  637. Revision 1.15 1999/05/17 21:52:44 florian
  638. * most of the Object Pascal stuff moved to the system unit
  639. }