system.pas 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825
  1. {
  2. $Id$
  3. ****************************************************************************
  4. Free Pascal -- OS/2 runtime library
  5. Copyright (c) 1999-2000 by Florian Klaempfl
  6. Copyright (c) 1999-2000 by Daniel Mantione
  7. Free Pascal is distributed under the GNU Public License v2. So is this unit.
  8. The GNU Public License requires you to distribute the source code of this
  9. unit with any product that uses it. We grant you an exception to this, and
  10. that is, when you compile a program with the Free Pascal Compiler, you do not
  11. need to ship source code with that program, AS LONG AS YOU ARE USING
  12. UNMODIFIED CODE! If you modify this code, you MUST change the next line:
  13. <This an official, unmodified Free Pascal source code file.>
  14. Send us your modified files, we can work together if you want!
  15. Free Pascal is distributed in the hope that it will be useful,
  16. but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  18. Library GNU General Public License for more details.
  19. You should have received a copy of the Library GNU General Public License
  20. along with Free Pascal; see the file COPYING.LIB. If not, write to
  21. the Free Software Foundation, 59 Temple Place - Suite 330,
  22. Boston, MA 02111-1307, USA.
  23. ****************************************************************************}
  24. unit sysos2;
  25. {Changelog:
  26. People:
  27. DM - Daniel Mantione
  28. Date: Description of change: Changed by:
  29. - First released version 0.1. DM
  30. Coding style:
  31. My coding style is a bit unusual for Pascal. Nevertheless I friendly ask
  32. you to try to make your changes not look all to different. In general,
  33. set your IDE to use tab characters, optimal fill on and a tabsize of 4.}
  34. interface
  35. {Link the startup code.}
  36. {$l prt1.oo2}
  37. {$I SYSTEMH.INC}
  38. {$I heaph.inc}
  39. type Tos=(osDOS,osOS2,osDPMI);
  40. var os_mode:Tos;
  41. first_meg:pointer;
  42. type Psysthreadib=^Tsysthreadib;
  43. Pthreadinfoblock=^Tthreadinfoblock;
  44. Pprocessinfoblock=^Tprocessinfoblock;
  45. Tbytearray=array[0..$ffff] of byte;
  46. Pbytearray=^Tbytearray;
  47. Tsysthreadib=record
  48. tid,
  49. priority,
  50. version:longint;
  51. MCcount,
  52. MCforceflag:word;
  53. end;
  54. Tthreadinfoblock=record
  55. pexchain,
  56. stack,
  57. stacklimit:pointer;
  58. tib2:Psysthreadib;
  59. version,
  60. ordinal:longint;
  61. end;
  62. Tprocessinfoblock=record
  63. pid,
  64. parentpid,
  65. hmte:longint;
  66. cmd,
  67. env:Pbytearray;
  68. flstatus,
  69. ttype:longint;
  70. end;
  71. const UnusedHandle=$ffff;
  72. StdInputHandle=0;
  73. StdOutputHandle=1;
  74. StdErrorHandle=2;
  75. FileNameCaseSensitive : boolean = false;
  76. var
  77. { C-compatible arguments and environment }
  78. argc : longint;external name '_argc';
  79. argv : ppchar;external name '_argv';
  80. envp : ppchar;external name '_environ';
  81. implementation
  82. {$I SYSTEM.INC}
  83. procedure DosGetInfoBlocks (var Atib: PThreadInfoBlock;
  84. var Apib: PProcessInfoBlock); cdecl;
  85. external 'DOSCALLS' index 312;
  86. function DosSetRelMaxFH (var ReqCount, CurMaxFH: longint): longint; cdecl;
  87. external 'DOSCALLS' index 382;
  88. {This is the correct way to call external assembler procedures.}
  89. procedure syscall; external name '___SYSCALL';
  90. {***************************************************************************
  91. Runtime error checking related routines.
  92. ***************************************************************************}
  93. {$S-}
  94. procedure st1(stack_size:longint);[public,alias: 'STACKCHECK'];
  95. begin
  96. { called when trying to get local stack }
  97. { if the compiler directive $S is set }
  98. {$ASMMODE DIRECT}
  99. asm
  100. movl stack_size,%ebx
  101. movl %esp,%eax
  102. subl %ebx,%eax
  103. {$ifdef SYSTEMDEBUG}
  104. movl U_SYSOS2_LOWESTSTACK,%ebx
  105. cmpl %eax,%ebx
  106. jb Lis_not_lowest
  107. movl %eax,U_SYSOS2_LOWESTSTACK
  108. Lis_not_lowest:
  109. {$endif SYSTEMDEBUG}
  110. cmpb $2,U_SYSOS2_OS_MODE
  111. jne Lrunning_in_dos
  112. movl U_SYSOS2_STACKBOTTOM,%ebx
  113. jmp Lrunning_in_os2
  114. Lrunning_in_dos:
  115. movl __heap_brk,%ebx
  116. Lrunning_in_os2:
  117. cmpl %eax,%ebx
  118. jae Lshort_on_stack
  119. leave
  120. ret $4
  121. Lshort_on_stack:
  122. end ['EAX','EBX'];
  123. {$ASMMODE ATT}
  124. { this needs a local variable }
  125. { so the function called itself !! }
  126. { Writeln('low in stack ');}
  127. HandleError(202);
  128. end;
  129. {no stack check in system }
  130. {****************************************************************************
  131. Miscellaneous related routines.
  132. ****************************************************************************}
  133. {$asmmode intel}
  134. procedure system_exit; assembler;
  135. asm
  136. mov ah, 04ch
  137. mov al, byte ptr exitcode
  138. call syscall
  139. end;
  140. {$asmmode att}
  141. {$asmmode direct}
  142. function paramcount:longint;assembler;
  143. asm
  144. movl _argc,%eax
  145. decl %eax
  146. end ['EAX'];
  147. function paramstr(l:longint):string;
  148. function args:pointer;assembler;
  149. asm
  150. movl _argv,%eax
  151. end ['EAX'];
  152. var p:^Pchar;
  153. begin
  154. if (l>=0) and (l<=paramcount) then
  155. begin
  156. p:=args;
  157. paramstr:=strpas(p[l]);
  158. end
  159. else paramstr:='';
  160. end;
  161. {$asmmode att}
  162. procedure randomize;
  163. var hl:longint;
  164. begin
  165. asm
  166. movb $0x2c,%ah
  167. call syscall
  168. movw %cx,-4(%ebp)
  169. movw %dx,-2(%ebp)
  170. end;
  171. randseed:=hl;
  172. end;
  173. {****************************************************************************
  174. Heap management releated routines.
  175. ****************************************************************************}
  176. { this function allows to extend the heap by calling
  177. syscall $7f00 resizes the brk area}
  178. function sbrk(size:longint):longint; assembler;
  179. asm
  180. movl size,%edx
  181. movw $0x7f00,%ax
  182. call syscall
  183. end;
  184. {$ASMMODE direct}
  185. function getheapstart:pointer;assembler;
  186. asm
  187. movl __heap_base,%eax
  188. end ['EAX'];
  189. function getheapsize:longint;assembler;
  190. asm
  191. movl HEAPSIZE,%eax
  192. end ['EAX'];
  193. {$ASMMODE ATT}
  194. {$i heap.inc}
  195. {****************************************************************************
  196. Low Level File Routines
  197. ****************************************************************************}
  198. procedure allowslash(p:Pchar);
  199. {Allow slash as backslash.}
  200. var i:longint;
  201. begin
  202. for i:=0 to strlen(p) do
  203. if p[i]='/' then p[i]:='\';
  204. end;
  205. procedure do_close(h:longint);
  206. begin
  207. { Only three standard handles under real OS/2 }
  208. if (h > 4) or
  209. (os_MODE = osOS2) and (h > 2) then
  210. begin
  211. asm
  212. movb $0x3e,%ah
  213. movl h,%ebx
  214. call syscall
  215. end;
  216. end;
  217. end;
  218. procedure do_erase(p:Pchar);
  219. begin
  220. allowslash(p);
  221. asm
  222. movl P,%edx
  223. movb $0x41,%ah
  224. call syscall
  225. jnc .LERASE1
  226. movw %ax,inoutres;
  227. .LERASE1:
  228. end;
  229. end;
  230. procedure do_rename(p1,p2:Pchar);
  231. begin
  232. allowslash(p1);
  233. allowslash(p2);
  234. asm
  235. movl P1, %edx
  236. movl P2, %edi
  237. movb $0x56,%ah
  238. call syscall
  239. jnc .LRENAME1
  240. movw %ax,inoutres;
  241. .LRENAME1:
  242. end;
  243. end;
  244. function do_read(h,addr,len:longint):longint; assembler;
  245. asm
  246. movl len,%ecx
  247. movl addr,%edx
  248. movl h,%ebx
  249. movb $0x3f,%ah
  250. call syscall
  251. jnc .LDOSREAD1
  252. movw %ax,inoutres;
  253. xorl %eax,%eax
  254. .LDOSREAD1:
  255. end;
  256. function do_write(h,addr,len:longint) : longint; assembler;
  257. asm
  258. movl len,%ecx
  259. movl addr,%edx
  260. movl h,%ebx
  261. movb $0x40,%ah
  262. call syscall
  263. jnc .LDOSWRITE1
  264. movw %ax,inoutres;
  265. .LDOSWRITE1:
  266. end;
  267. function do_filepos(handle:longint): longint; assembler;
  268. asm
  269. movw $0x4201,%ax
  270. movl handle,%ebx
  271. xorl %edx,%edx
  272. call syscall
  273. jnc .LDOSFILEPOS
  274. movw %ax,inoutres;
  275. xorl %eax,%eax
  276. .LDOSFILEPOS:
  277. end;
  278. procedure do_seek(handle,pos:longint); assembler;
  279. asm
  280. movw $0x4200,%ax
  281. movl handle,%ebx
  282. movl pos,%edx
  283. call syscall
  284. jnc .LDOSSEEK1
  285. movw %ax,inoutres;
  286. .LDOSSEEK1:
  287. end;
  288. function do_seekend(handle:longint):longint; assembler;
  289. asm
  290. movw $0x4202,%ax
  291. movl handle,%ebx
  292. xorl %edx,%edx
  293. call syscall
  294. jnc .Lset_at_end1
  295. movw %ax,inoutres;
  296. xorl %eax,%eax
  297. .Lset_at_end1:
  298. end;
  299. function do_filesize(handle:longint):longint;
  300. var aktfilepos:longint;
  301. begin
  302. aktfilepos:=do_filepos(handle);
  303. do_filesize:=do_seekend(handle);
  304. do_seek(handle,aktfilepos);
  305. end;
  306. procedure do_truncate(handle,pos:longint); assembler;
  307. asm
  308. (* DOS function 40h isn't safe for this according to EMX documentation
  309. movl $0x4200,%eax
  310. movl 8(%ebp),%ebx
  311. movl 12(%ebp),%edx
  312. call syscall
  313. jc .LTruncate1
  314. movl 8(%ebp),%ebx
  315. movl 12(%ebp),%edx
  316. movl %ebp,%edx
  317. xorl %ecx,%ecx
  318. movb $0x40,%ah
  319. call syscall
  320. *)
  321. movl $0x7F25,%eax
  322. movl Handle,%ebx
  323. movl Pos,%edx
  324. call syscall
  325. inc %eax
  326. movl %ecx, %eax
  327. jnz .LTruncate1
  328. (* File position is undefined after truncation, move to the end. *)
  329. movl $0x4202,%eax
  330. movl Handle,%ebx
  331. movl $0,%edx
  332. call syscall
  333. jnc .LTruncate2
  334. .LTruncate1:
  335. movw %ax,inoutres;
  336. .LTruncate2:
  337. end;
  338. const
  339. FileHandleCount: longint = 20;
  340. function Increase_File_Handle_Count: boolean;
  341. var Err: word;
  342. L1, L2: longint;
  343. begin
  344. if os_mode = osOS2 then
  345. begin
  346. L1 := 10;
  347. if DosSetRelMaxFH (L1, L2) <> 0 then
  348. Increase_File_Handle_Count := false
  349. else
  350. if L2 > FileHandleCount then
  351. begin
  352. FileHandleCount := L2;
  353. Increase_File_Handle_Count := true;
  354. end
  355. else
  356. Increase_File_Handle_Count := false;
  357. end
  358. else
  359. begin
  360. Inc (FileHandleCount, 10);
  361. Err := 0;
  362. asm
  363. movl $0x6700, %eax
  364. movl FileHandleCount, %ebx
  365. call syscall
  366. jnc .LIncFHandles
  367. movw %ax, Err
  368. .LIncFHandles:
  369. end;
  370. if Err <> 0 then
  371. begin
  372. Increase_File_Handle_Count := false;
  373. Dec (FileHandleCount, 10);
  374. end
  375. else
  376. Increase_File_Handle_Count := true;
  377. end;
  378. end;
  379. procedure do_open(var f;p:pchar;flags:longint);
  380. {
  381. filerec and textrec have both handle and mode as the first items so
  382. they could use the same routine for opening/creating.
  383. when (flags and $100) the file will be append
  384. when (flags and $1000) the file will be truncate/rewritten
  385. when (flags and $10000) there is no check for close (needed for textfiles)
  386. }
  387. var Action: longint;
  388. begin
  389. allowslash(p);
  390. { close first if opened }
  391. if ((flags and $10000)=0) then
  392. begin
  393. case filerec(f).mode of
  394. fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
  395. fmclosed:;
  396. else
  397. begin
  398. inoutres:=102; {not assigned}
  399. exit;
  400. end;
  401. end;
  402. end;
  403. { reset file handle }
  404. filerec(f).handle := UnusedHandle;
  405. Action := 0;
  406. { convert filemode to filerec modes }
  407. case (flags and 3) of
  408. 0 : filerec(f).mode:=fminput;
  409. 1 : filerec(f).mode:=fmoutput;
  410. 2 : filerec(f).mode:=fminout;
  411. end;
  412. if (flags and $1000)<>0 then
  413. Action := $50000; (* Create / replace *)
  414. { empty name is special }
  415. if p[0]=#0 then
  416. begin
  417. case FileRec(f).mode of
  418. fminput :
  419. FileRec(f).Handle:=StdInputHandle;
  420. fminout, { this is set by rewrite }
  421. fmoutput :
  422. FileRec(f).Handle:=StdOutputHandle;
  423. fmappend :
  424. begin
  425. FileRec(f).Handle:=StdOutputHandle;
  426. FileRec(f).mode:=fmoutput; {fool fmappend}
  427. end;
  428. end;
  429. exit;
  430. end;
  431. Action := Action or (Flags and $FF);
  432. (* DenyAll if sharing not specified. *)
  433. if Flags and 112 = 0 then
  434. Action := Action or 16;
  435. asm
  436. movl $0x7f2b, %eax
  437. movl Action, %ecx
  438. movl p, %edx
  439. call syscall
  440. cmpl $0xffffffff, %eax
  441. jnz .LOPEN1
  442. movw %cx, InOutRes
  443. movw UnusedHandle, %ax
  444. .LOPEN1:
  445. movl f,%edx
  446. movw %ax,(%edx)
  447. end;
  448. if (InOutRes = 4) and Increase_File_Handle_Count then
  449. (* Trying again after increasing amount of file handles *)
  450. asm
  451. movl $0x7f2b, %eax
  452. movl Action, %ecx
  453. movl p, %edx
  454. call syscall
  455. cmpl $0xffffffff, %eax
  456. jnz .LOPEN2
  457. movw %cx, InOutRes
  458. movw UnusedHandle, %ax
  459. .LOPEN2:
  460. movl f,%edx
  461. movw %ax,(%edx)
  462. end;
  463. { for systems that have more handles }
  464. if FileRec (F).Handle > FileHandleCount then
  465. FileHandleCount := FileRec (F).Handle;
  466. if (flags and $100)<>0 then
  467. begin
  468. do_seekend(filerec(f).handle);
  469. FileRec (F).Mode := fmOutput; {fool fmappend}
  470. end;
  471. end;
  472. {$ASMMODE INTEL}
  473. function do_isdevice (Handle: longint): boolean; assembler;
  474. (*
  475. var HT, Attr: longint;
  476. begin
  477. if os_mode = osOS2 then
  478. begin
  479. if DosQueryHType (Handle, HT, Attr) <> 0 then HT := 1;
  480. end
  481. else
  482. *)
  483. asm
  484. mov ebx, Handle
  485. mov eax, 4400h
  486. call syscall
  487. mov eax, 1
  488. jc @IsDevEnd
  489. test edx, 80h
  490. jnz @IsDevEnd
  491. dec eax
  492. @IsDevEnd:
  493. end;
  494. {$ASMMODE ATT}
  495. {*****************************************************************************
  496. UnTyped File Handling
  497. *****************************************************************************}
  498. {$i file.inc}
  499. {*****************************************************************************
  500. Typed File Handling
  501. *****************************************************************************}
  502. {$i typefile.inc}
  503. {*****************************************************************************
  504. Text File Handling
  505. *****************************************************************************}
  506. {$DEFINE EOF_CTRLZ}
  507. {$i text.inc}
  508. {****************************************************************************
  509. Directory related routines.
  510. ****************************************************************************}
  511. {*****************************************************************************
  512. Directory Handling
  513. *****************************************************************************}
  514. procedure dosdir(func:byte;const s:string);
  515. var buffer:array[0..255] of char;
  516. begin
  517. move(s[1],buffer,length(s));
  518. buffer[length(s)]:=#0;
  519. allowslash(Pchar(@buffer));
  520. asm
  521. leal buffer,%edx
  522. movb func,%ah
  523. call syscall
  524. jnc .LDOS_DIRS1
  525. movw %ax,inoutres;
  526. .LDOS_DIRS1:
  527. end;
  528. end;
  529. procedure mkdir(const s : string);
  530. begin
  531. DosDir($39,s);
  532. end;
  533. procedure rmdir(const s : string);
  534. begin
  535. DosDir($3a,s);
  536. end;
  537. procedure chdir(const s : string);
  538. begin
  539. DosDir($3b,s);
  540. end;
  541. procedure getdir(drivenr : byte;var dir : shortstring);
  542. {Written by Michael Van Canneyt.}
  543. var temp:array[0..255] of char;
  544. sof:Pchar;
  545. i:byte;
  546. begin
  547. sof:=pchar(@dir[4]);
  548. { dir[1..3] will contain '[drivenr]:\', but is not }
  549. { supplied by DOS, so we let dos string start at }
  550. { dir[4] }
  551. { Get dir from drivenr : 0=default, 1=A etc... }
  552. asm
  553. movb drivenr,%dl
  554. movl sof,%esi
  555. mov $0x47,%ah
  556. call syscall
  557. end;
  558. { Now Dir should be filled with directory in ASCIIZ, }
  559. { starting from dir[4] }
  560. dir[0]:=#3;
  561. dir[2]:=':';
  562. dir[3]:='\';
  563. i:=4;
  564. {Conversion to Pascal string }
  565. while (dir[i]<>#0) do
  566. begin
  567. { convert path name to DOS }
  568. if dir[i]='/' then
  569. dir[i]:='\';
  570. dir[0]:=char(i);
  571. inc(i);
  572. end;
  573. { upcase the string (FPC function) }
  574. if not (FileNameCaseSensitive) then dir:=upcase(dir);
  575. if drivenr<>0 then { Drive was supplied. We know it }
  576. dir[1]:=char(65+drivenr-1)
  577. else
  578. begin
  579. { We need to get the current drive from DOS function 19H }
  580. { because the drive was the default, which can be unknown }
  581. asm
  582. movb $0x19,%ah
  583. call syscall
  584. addb $65,%al
  585. movb %al,i
  586. end;
  587. dir[1]:=char(i);
  588. end;
  589. end;
  590. {****************************************************************************
  591. System unit initialization.
  592. ****************************************************************************}
  593. function GetFileHandleCount: longint;
  594. var L1, L2: longint;
  595. begin
  596. L1 := 0; (* Don't change the amount, just check. *)
  597. if DosSetRelMaxFH (L1, L2) <> 0 then GetFileHandleCount := 50
  598. else GetFileHandleCount := L2;
  599. end;
  600. var pib:Pprocessinfoblock;
  601. tib:Pthreadinfoblock;
  602. begin
  603. {Determine the operating system we are running on.}
  604. asm
  605. movl $0,os_mode
  606. movw $0x7f0a,%ax
  607. call syscall
  608. testw $512,%bx {Bit 9 is OS/2 flag.}
  609. setnzb os_mode
  610. testw $4096,%bx
  611. jz .LnoRSX
  612. movl $2,os_mode
  613. .LnoRSX:
  614. end;
  615. {$ASMMODE DIRECT}
  616. {Enable the brk area by initializing it with the initial heap size.}
  617. asm
  618. movw $0x7f01,%ax
  619. movl HEAPSIZE,%edx
  620. addl __heap_base,%edx
  621. call ___SYSCALL
  622. cmpl $-1,%eax
  623. jnz Lheapok
  624. pushl $204
  625. {call RUNERROR$$WORD}
  626. Lheapok:
  627. end;
  628. {$ASMMODE ATT}
  629. {Now request, if we are running under DOS,
  630. read-access to the first meg. of memory.}
  631. if os_mode in [osDOS,osDPMI] then
  632. asm
  633. movw $0x7f13,%ax
  634. xorl %ebx,%ebx
  635. movl $0xfff,%ecx
  636. xorl %edx,%edx
  637. call syscall
  638. movl %eax,first_meg
  639. end
  640. else
  641. begin
  642. first_meg := nil;
  643. (* Initialize the amount of file handles *)
  644. FileHandleCount := GetFileHandleCount;
  645. end;
  646. {At 0.9.2, case for enumeration does not work.}
  647. case os_mode of
  648. osDOS:
  649. stackbottom:=0; {In DOS mode, heap_brk is also the
  650. stack bottom.}
  651. osOS2:
  652. begin
  653. dosgetinfoblocks(tib,pib);
  654. stackbottom:=longint(tib^.stack);
  655. end;
  656. osDPMI:
  657. stackbottom:=0; {Not sure how to get it, but seems to be
  658. always zero.}
  659. end;
  660. exitproc:=nil;
  661. {Initialize the heap.}
  662. initheap;
  663. { ... and exceptions }
  664. InitExceptions;
  665. { to test stack depth }
  666. loweststack:=maxlongint;
  667. OpenStdIO(Input,fmInput,StdInputHandle);
  668. OpenStdIO(Output,fmOutput,StdOutputHandle);
  669. OpenStdIO(StdOut,fmOutput,StdOutputHandle);
  670. OpenStdIO(StdErr,fmOutput,StdErrorHandle);
  671. { no I/O-Error }
  672. inoutres:=0;
  673. end.
  674. {
  675. $Log$
  676. Revision 1.1 2000-10-15 08:19:49 peter
  677. * system unit rename for 1.1 branch
  678. Revision 1.3 2000/09/29 21:49:41 jonas
  679. * removed warnings
  680. Revision 1.2 2000/07/14 10:33:11 michael
  681. + Conditionals fixed
  682. Revision 1.1 2000/07/13 06:31:07 michael
  683. + Initial import
  684. }