sysos2.pas 18 KB

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