123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732 |
- {****************************************************************************
- FPK-Pascal -- OS/2 runtime library
- Copyright (c) 1993,95 by Florian Kl„mpfl
- Copyright (c) 1997 by Dani‰l Mantione
- FPK-Pascal is distributed under the GNU Public License v2. So is this unit.
- The GNU Public License requires you to distribute the source code of this
- unit with any product that uses it. We grant you an exception to this, and
- that is, when you compile a program with the FPK Pascal compiler, you do not
- need to ship source code with that program, AS LONG AS YOU ARE USING
- UNMODIFIED CODE! If you modify this code, you MUST change the next line:
- <This an official, unmodified FPK Pascal source code file.>
- Send us your modified files, we can work together if you want!
- FPK-Pascal is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- Library GNU General Public License for more details.
- You should have received a copy of the Library GNU General Public License
- along with FPK-Pascal; see the file COPYING.LIB. If not, write to
- the Free Software Foundation, 59 Temple Place - Suite 330,
- Boston, MA 02111-1307, USA.
- ****************************************************************************}
- unit sysos2;
- {Changelog:
- People:
- DM - Dani‰l Mantione
- Date: Description of change: Changed by:
- - First released version 0.1. DM
- Coding style:
- My coding style is a bit unusual for Pascal. Nevertheless I friendly ask
- you to try to make your changes not look all to different. In general,
- set your IDE to use tab characters, optimal fill on and a tabsize of 4.}
- {$I os.inc}
- interface
- {Link the startup code.}
- {$l prt1.oo2}
- {$I SYSTEMH.INC}
- {$I heaph.inc}
- type Tos=(osDOS,osOS2,osDPMI);
- var os_mode:Tos;
- first_meg:pointer;
- type Psysthreadib=^Tsysthreadib;
- Pthreadinfoblock=^Tthreadinfoblock;
- Pprocessinfoblock=^Tprocessinfoblock;
- Tbytearray=array[0..$ffff] of byte;
- Pbytearray=^Tbytearray;
- Tsysthreadib=record
- tid,
- priority,
- version:longint;
- MCcount,
- MCforceflag:word;
- end;
- Tthreadinfoblock=record
- pexchain,
- stack,
- stacklimit:pointer;
- tib2:Psysthreadib;
- version,
- ordinal:longint;
- end;
- Tprocessinfoblock=record
- pid,
- parentpid,
- hmte:longint;
- cmd,
- env:Pbytearray;
- flstatus,
- ttype:longint;
- end;
- const UnusedHandle=$ffff;
- StdInputHandle=0;
- StdOutputHandle=1;
- StdErrorHandle=2;
- implementation
- {$I SYSTEM.INC}
- procedure dosgetinfoblocks(var Atib:Pthreadinfoblock;
- var Apib:Pprocessinfoblock);
- external 'DOSCALLS' index 312;
- {This is the correct way to call external assembler procedures.}
- procedure syscall;external name '___SYSCALL';
- {***************************************************************************
- Runtime error checking related routines.
- ***************************************************************************}
- {$S-}
- procedure st1(stack_size:longint);[public,alias: 'STACKCHECK'];
- begin
- { called when trying to get local stack }
- { if the compiler directive $S is set }
- {$ASMMODE DIRECT}
- asm
- movl stack_size,%ebx
- movl %esp,%eax
- subl %ebx,%eax
- {$ifdef SYSTEMDEBUG}
- movl U_SYSOS2_LOWESTSTACK,%ebx
- cmpl %eax,%ebx
- jb Lis_not_lowest
- movl %eax,U_SYSOS2_LOWESTSTACK
- Lis_not_lowest:
- {$endif SYSTEMDEBUG}
- cmpb $2,U_SYSOS2_OS_MODE
- jne Lrunning_in_dos
- movl U_SYSOS2_STACKBOTTOM,%ebx
- jmp Lrunning_in_os2
- Lrunning_in_dos:
- movl __heap_brk,%ebx
- Lrunning_in_os2:
- cmpl %eax,%ebx
- jae Lshort_on_stack
- leave
- ret $4
- Lshort_on_stack:
- end ['EAX','EBX'];
- {$ASMMODE ATT}
- { this needs a local variable }
- { so the function called itself !! }
- { Writeln('low in stack ');}
- HandleError(202);
- end;
- {no stack check in system }
- {****************************************************************************
- Miscelleanious related routines.
- ****************************************************************************}
- procedure halt(errnum:byte);
- begin
- asm
- movb $0x4c,%ah
- movb errnum,%al
- call syscall
- end;
- end;
- {$asmmode direct}
- function paramcount:longint;assembler;
- asm
- movl _argc,%eax
- decl %eax
- end ['EAX'];
- function paramstr(l:longint):string;
- function args:pointer;assembler;
- asm
- movl _argv,%eax
- end ['EAX'];
- var p:^Pchar;
- begin
- if (l>=0) and (l<=paramcount) then
- begin
- p:=args;
- paramstr:=strpas(p[l]);
- end
- else paramstr:='';
- end;
- {$asmmode att}
- procedure randomize;
- var hl:longint;
- begin
- asm
- movb $0x2c,%ah
- call syscall
- movw %cx,-4(%ebp)
- movw %dx,-2(%ebp)
- end;
- randseed:=hl;
- end;
- {****************************************************************************
- Heap management releated routines.
- ****************************************************************************}
- { this function allows to extend the heap by calling
- syscall $7f00 resizes the brk area}
- function sbrk(size:longint):longint;
- begin
- asm
- movl size,%edx
- movw $0x7f00,%ax
- call syscall
- movl %eax,__RESULT
- end;
- end;
- {$ASMMODE direct}
- function getheapstart:pointer;assembler;
- asm
- movl __heap_base,%eax
- end ['EAX'];
- function getheapsize:longint;assembler;
- asm
- movl HEAPSIZE,%eax
- end ['EAX'];
- {$ASMMODE ATT}
- {$i heap.inc}
- {****************************************************************************
- Low Level File Routines
- ****************************************************************************}
- procedure allowslash(p:Pchar);
- {Allow slash as backslash.}
- var i:longint;
- begin
- for i:=0 to strlen(p) do
- if p[i]='/' then p[i]:='\';
- end;
- procedure do_close(h:longint);
- begin
- asm
- movb $0x3e,%ah
- mov h,%ebx
- call syscall
- end;
- end;
- procedure do_erase(p:Pchar);
- begin
- allowslash(p);
- asm
- movl 8(%ebp),%edx
- movb $0x41,%ah
- call syscall
- jnc .LERASE1
- movw %ax,inoutres;
- .LERASE1:
- end;
- end;
- procedure do_rename(p1,p2:Pchar);
- begin
- allowslash(p1);
- allowslash(p2);
- asm
- movl 8(%ebp),%edx
- movl 12(%ebp),%edi
- movb $0x56,%ah
- call syscall
- jnc .LRENAME1
- movw %ax,inoutres;
- .LRENAME1:
- end;
- end;
- function do_read(h,addr,len:longint):longint;
- begin
- asm
- movl 16(%ebp),%ecx
- movl 12(%ebp),%edx
- movl 8(%ebp),%ebx
- movb $0x3f,%ah
- call syscall
- jnc .LDOSREAD1
- movw %ax,inoutres;
- xorl %eax,%eax
- .LDOSREAD1:
- leave
- ret $12
- end;
- end;
- function do_write(h,addr,len:longint) : longint;
- begin
- asm
- movl 16(%ebp),%ecx
- movl 12(%ebp),%edx
- movl 8(%ebp),%ebx
- movb $0x40,%ah
- call syscall
- jnc .LDOSWRITE1
- movw %ax,inoutres;
- .LDOSWRITE1:
- movl %eax,-4(%ebp)
- end;
- end;
- function do_filepos(handle:longint):longint;
- begin
- asm
- movw $0x4201,%ax
- movl 8(%ebp),%ebx
- xorl %edx,%edx
- call syscall
- jnc .LDOSFILEPOS
- movw %ax,inoutres;
- xorl %eax,%eax
- .LDOSFILEPOS:
- leave
- ret $4
- end;
- end;
- procedure do_seek(handle,pos:longint);
- begin
- asm
- movw $0x4200,%ax
- movl 8(%ebp),%ebx
- movl 12(%ebp),%edx
- call syscall
- jnc .LDOSSEEK1
- movw %ax,inoutres;
- .LDOSSEEK1:
- leave
- ret $8
- end;
- end;
- function do_seekend(handle:longint):longint;
- begin
- asm
- movw $0x4202,%ax
- movl 8(%ebp),%ebx
- xorl %edx,%edx
- call syscall
- jnc .Lset_at_end1
- movw %ax,inoutres;
- xorl %eax,%eax
- .Lset_at_end1:
- leave
- ret $4
- end;
- end;
- function do_filesize(handle:longint):longint;
- var aktfilepos:longint;
- begin
- aktfilepos:=do_filepos(handle);
- do_filesize:=do_seekend(handle);
- do_seek(handle,aktfilepos);
- end;
- procedure do_truncate(handle,pos:longint);
- begin
- asm
- movl $0x4200,%eax
- movl 8(%ebp),%ebx
- movl 12(%ebp),%edx
- call syscall
- jc .LTruncate1
- movl 8(%ebp),%ebx
- movl 12(%ebp),%edx
- movl %ebp,%edx
- xorl %ecx,%ecx
- movb $0x40,%ah
- call syscall
- jnc .LTruncate2
- .LTruncate1:
- movw %ax,inoutres;
- .LTruncate2:
- leave
- ret $8
- end;
- end;
- procedure do_open(var f;p:pchar;flags:longint);
- {
- filerec and textrec have both handle and mode as the first items so
- they could use the same routine for opening/creating.
- when (flags and $10) the file will be append
- when (flags and $100) the file will be truncate/rewritten
- when (flags and $1000) there is no check for close (needed for textfiles)
- }
- var oflags:byte;
- begin
- allowslash(p);
- { close first if opened }
- if ((flags and $1000)=0) then
- begin
- case filerec(f).mode of
- fminput,fmoutput,fminout : Do_Close(filerec(f).handle);
- fmclosed:;
- else
- begin
- inoutres:=102; {not assigned}
- exit;
- end;
- end;
- end;
- { reset file handle }
- filerec(f).handle:=high(word);
- oflags:=2;
- { convert filemode to filerec modes }
- case (flags and 3) of
- 0 : begin
- filerec(f).mode:=fminput;
- oflags:=0;
- end;
- 1 : filerec(f).mode:=fmoutput;
- 2 : filerec(f).mode:=fminout;
- end;
- if (flags and $100)<>0 then
- begin
- filerec(f).mode:=fmoutput;
- oflags:=2;
- end
- else
- if (flags and $10)<>0 then
- begin
- filerec(f).mode:=fmoutput;
- oflags:=2;
- end;
- { empty name is special }
- if p[0]=#0 then
- begin
- case filerec(f).mode of
- fminput:filerec(f).handle:=StdInputHandle;
- fmappend,fmoutput : begin
- filerec(f).handle:=StdOutputHandle;
- filerec(f).mode:=fmoutput; {fool fmappend}
- end;
- end;
- exit;
- end;
- if (flags and $100)<>0 then
- {Use create function.}
- asm
- movb $0x3c,%ah
- movl p,%edx
- xorw %cx,%cx
- call syscall
- jnc .LOPEN1
- movw %ax,inoutres;
- movw $0xffff,%ax
- .LOPEN1:
- movl f,%edx
- movw %ax,(%edx)
- end
- else
- {Use open function.}
- asm
- movb $0x3d,%ah
- movb oflags,%al
- movl p,%edx
- call syscall
- jnc .LOPEN2
- movw %ax,inoutres;
- movw $0xffff,%ax
- .LOPEN2:
- movl f,%edx
- movw %ax,(%edx)
- end;
- if (flags and $10)<>0 then
- do_seekend(filerec(f).handle);
- end;
- function do_isdevice(handle:longint):boolean;
- begin
- do_isdevice:=(handle<=5);
- end;
- {*****************************************************************************
- UnTyped File Handling
- *****************************************************************************}
- {$i file.inc}
- {*****************************************************************************
- Typed File Handling
- *****************************************************************************}
- {$i typefile.inc}
- {*****************************************************************************
- Text File Handling
- *****************************************************************************}
- {$DEFINE EOF_CTRLZ}
- {$i text.inc}
- {****************************************************************************
- Directory related routines.
- ****************************************************************************}
- {*****************************************************************************
- Directory Handling
- *****************************************************************************}
- procedure dosdir(func:byte;const s:string);
- var buffer:array[0..255] of char;
- begin
- move(s[1],buffer,length(s));
- buffer[length(s)]:=#0;
- allowslash(Pchar(@buffer));
- asm
- leal buffer,%edx
- movb 8(%ebp),%ah
- call syscall
- jnc .LDOS_DIRS1
- movw %ax,inoutres;
- .LDOS_DIRS1:
- end;
- end;
- procedure mkdir(const s : string);
- begin
- DosDir($39,s);
- end;
- procedure rmdir(const s : string);
- begin
- DosDir($3a,s);
- end;
- procedure chdir(const s : string);
- begin
- DosDir($3b,s);
- end;
- procedure getdir(drivenr : byte;var dir : shortstring);
- {Written by Michael Van Canneyt.}
- var temp:array[0..255] of char;
- sof:Pchar;
- i:byte;
- begin
- sof:=pchar(@dir[4]);
- { dir[1..3] will contain '[drivenr]:\', but is not }
- { supplied by DOS, so we let dos string start at }
- { dir[4] }
- { Get dir from drivenr : 0=default, 1=A etc... }
- asm
- movb drivenr,%dl
- movl sof,%esi
- mov $0x47,%ah
- call syscall
- end;
- { Now Dir should be filled with directory in ASCIIZ, }
- { starting from dir[4] }
- dir[0]:=#3;
- dir[2]:=':';
- dir[3]:='\';
- i:=4;
- {Conversion to Pascal string }
- while (dir[i]<>#0) do
- begin
- { convert path name to DOS }
- if dir[i]='/' then
- dir[i]:='\';
- dir[0]:=char(i);
- inc(i);
- end;
- { upcase the string (FPKPascal function) }
- dir:=upcase(dir);
- if drivenr<>0 then { Drive was supplied. We know it }
- dir[1]:=char(65+drivenr-1)
- else
- begin
- { We need to get the current drive from DOS function 19H }
- { because the drive was the default, which can be unknown }
- asm
- movb $0x19,%ah
- call syscall
- addb $65,%al
- movb %al,i
- end;
- dir[1]:=char(i);
- end;
- end;
- {****************************************************************************
- System unit initialization.
- ****************************************************************************}
- var pib:Pprocessinfoblock;
- tib:Pthreadinfoblock;
- begin
- {Determine the operating system we are running on.}
- asm
- movw $0x7f0a,%ax
- call syscall
- testw $512,%bx {Bit 9 is OS/2 flag.}
- setnzl os_mode
- testw $4096,%bx
- jz .LnoRSX
- movl $2,os_mode
- .LnoRSX:
- end;
- {$ASMMODE DIRECT}
- {Enable the brk area by initializing it with the initial heap size.}
- asm
- movw $0x7f01,%ax
- movl HEAPSIZE,%edx
- addl __heap_base,%edx
- call ___SYSCALL
- cmpl $-1,%eax
- jnz Lheapok
- pushl $204
- {call RUNERROR$$WORD}
- Lheapok:
- end;
- {$ASMMODE ATT}
- {Now request, if we are running under DOS,
- read-access to the first meg. of memory.}
- if os_mode in [osDOS,osDPMI] then
- asm
- movw $0x7f13,%ax
- xorl %ebx,%ebx
- movl $0xfff,%ecx
- xorl %edx,%edx
- call syscall
- movl %eax,first_meg
- end
- else
- first_meg:=nil;
- {At 0.9.2, case for enumeration does not work.}
- case os_mode of
- osDOS:
- stackbottom:=0; {In DOS mode, heap_brk is also the
- stack bottom.}
- osOS2:
- begin
- dosgetinfoblocks(tib,pib);
- stackbottom:=longint(tib^.stack);
- end;
- osDPMI:
- stackbottom:=0; {Not sure how to get it, but seems to be
- always zero.}
- end;
- exitproc:=nil;
- {Initialize the heap.}
- initheap;
- { to test stack depth }
- loweststack:=maxlongint;
- OpenStdIO(Input,fmInput,StdInputHandle);
- OpenStdIO(Output,fmOutput,StdOutputHandle);
- OpenStdIO(StdOut,fmOutput,StdOutputHandle);
- OpenStdIO(StdErr,fmOutput,StdErrorHandle);
- { kein Ein- Ausgabefehler }
- inoutres:=0;
- end.
|