sysos2.pas 14 KB

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