|
Hauptseite - Welches System? - Hardware - Software - Textverarbeitung - |
Internet MausNet Programmieren Verweise Über |
Beispiele zu Algorithmen - Beispiele zur Betriebssystemprogrammierung - Beispiele zu diversen Protokollen - Diverse andere Beispiele
Die folgenden Beispiele zeigen eine mögliche Implementierung des ARGV-Verfahrens. Die Beispiele verwenden allerdings keine weiterführenden Bibliotheksfunktionen. Sie greifen direkt über die Basepage des Programms auf das Environment zu.
Die Beispiele definieren für das Auswerten und für das Erstellen einer erweiterten Kommandozeile folgende Funktionen:
int argc;char *argv[]; Xargv(&argc,&argv);Wenn es erweiterte Parameter gibt, enthält argc die Anzahl der Parameter, ansonsten -1. Für argv wird Speicher alloziert und die Zeiger auf die Parameter werden umkopiert. Werden keine Parameter übergeben, wird (**argv) auf NULL gesetzt.
int argc;char *argv[]; Xargv(&argc,&argv);Wenn es erweiterte Parameter gibt, enthält argc die Anzahl der Parameter, ansonsten -1. Für argv wird Speicher alloziert und die Zeiger auf die Parameter werden umkopiert. Werden keine Parameter übergeben, wird argv auf NULL gesetzt.
| Sprache | C | Pascal | Modula |
|---|---|---|---|
| Schnittstelle | argv.h | argv.inc | argv.def |
| Implementierung | argv.c | argv.pas | argv.mod |
#ifndef ARGV #define ARGV int Xargv(int *argc,char ***argv); void XargvEnd(char ***argv); char *DoXargv(int argc,char **argv); void DoXargvEnd(char **env); #endif
#include#include #include #include #include #include "argv.h" static DTA _mydta; static char *get_argv(void) { char *c; c=_BasPag->p_env; while (*c) { if (!strncmp(c,"ARGV=",5)) { *c=0; return(c+5); } else c+=strlen(c)+1; } return(NULL); } int Xargv(int *argc,char ***argv) { char *env,*startpar,*argv_value,*s; unsigned int idx; Fsetdta(&_mydta); /* damit 1. Fsfirst nicht Komandozeile ueberschreibt */ if (_BasPag->p_cmdlin[0]!=127) /* Flag fuer Verwendung von ARGV */ { *argc=-1; *argv=NULL; return(0); } else { /* Zeiger auf Env-Var merken */ argv_value=env=get_argv(); if (env==NULL) { /* ARGV steht nicht im Environment */ *argc=-1; *argv=NULL; return(0); } else { /* auf extended ARGV testen */ if (strncmp(argv_value,"NULL:",5)) argv_value=NULL; else argv_value+=5; /* zu argv[0] gehen */ while (*env++) ; /* Parameterstart */ startpar=env; /* Parameter zaehlen */ *argc=0; while (*env) { (*argc)++; while (*env++) ; } /* Speicher fuer neuen Argumment-Vektor */ *argv=malloc((*argc+1)*sizeof(char *)); env=startpar; *argc=0; while (*env) { (*argv)[(*argc)++]=env; while (*env++) ; } (*argv)[*argc]=NULL; /* Leere Argumente vernichten */ if (argv_value) { idx=0; while ((*argv_value) && (idx<*argc)) { idx=0; for (s=argv_value;*s && *s!=',';) { if (!isdigit(*s)) idx=*argc+1; else { idx*=10; idx+=*s++ - '0'; } } if (*s==',') s+=1; argv_value=s; if (idx<*argc) (*argv)[idx][0]='\0'; } } return(1); } } } void XargvEnd(char ***argv) { if (*argv!=NULL) { free(*argv); *argv=NULL; } } static size_t size_env(void) { char *c; size_t Size; Size=0; c=_BasPag->p_env; /* aufsummieren der Laengen der Environment-Strings */ while (*c) { if (!strncmp(c,"ARGV=",5)) /* ARGV als Variable wird entfernt (muž sowieso letzte sein!) */ *c=0; else { Size+=strlen(c)+1; c+=strlen(c)+1; } } /* Die abschliessende Null als Environment-Ende wird nicht mitgezaehlt */ return(Size); } char *DoXargv(int argc,char **argv) { size_t OldSizeEnv,ArgvSize,Len; int i,Leer; char *NewEnv,*Lauf,XargVar[255],Buf[20],*Ort; strcpy(XargVar,"ARGV=NULL:"); OldSizeEnv=size_env(); /* Groesse des alten environments */ /* zusaetzliche Groesse fuer Parameter ermitteln */ ArgvSize=0; Leer=0; if (argc>0) { for (i=0;i p_env,OldSizeEnv); Lauf=NewEnv+OldSizeEnv; /* Kommandozeilenparameter anhaengen */ if (argc>0) { strcpy(Lauf,XargVar); if (!Leer) { /* keine Nullparameter -> "NULL:" loeschen */ XargVar[5]=' '; XargVar[6]=0; Ort=Lauf+5; } else Ort=Lauf+strlen(XargVar)-1; Lauf=Ort+1; for (i=0;i
argv.inc
function cmd_xargv:integer; external; procedure cmd_getxargv(n:integer;var arg:string); external; procedure make_xargv(var env:long_integer;argc:integer;argv:long_integer); external; procedure end_xargv(var env:long_integer); external;
argv.pas
{$M+.I-} (* Zur Geschwindigkeitsoptimierung alle Ueberpruefungen ausschalten. *) (* Pointerueberpruefung ausschalten, da Basepage nicht im Heap liegt! *) {$C-,D-,P-,R-,T-} program argv; {$I GEMDOS.PAS} {$E+} function cmd_xargv:integer; type onechar=array[1..2] of char; var bp:BasPagPtr; cptr,copy:record case boolean of true: (adr:long_integer); false:(ptr:^onechar); end; VarName:string[5]; Anz,i:integer; begin basepage(bp); if (bp^.p_cmdlin[0]<>chr(127)) then (* Flag fuer Verwendung von ARGV *) cmd_xargv:=0 else begin Anz:=0; cptr.adr:=bp^.p_env; while (cptr.ptr^[1]<>chr(0)) do begin copy.adr:=cptr.adr; VarName:=''; for i:=1 to 5 do begin VarName:=concat(VarName,copy.ptr^[1]); copy.adr:=copy.adr+1; end; if (VarName='ARGV=') then begin (* Parameter z„hlen *) (* ersten Parameter suchen *) while (cptr.ptr^[1]<>chr(0)) do cptr.adr:=cptr.adr+1; cptr.adr:=cptr.adr+1; (* 1. Parameter (oder 0) *) while (cptr.ptr^[1]<>chr(0)) do begin Anz:=Anz+1; (* Parameter berlesen *) while (cptr.ptr^[1]<>chr(0)) do cptr.adr:=cptr.adr+1; cptr.adr:=cptr.adr+1; (* naechster Parameter (oder 0) *) end; end else begin (* naechste Environmentvariable *) while (cptr.ptr^[1]<>chr(0)) do cptr.adr:=cptr.adr+1; cptr.adr:=cptr.adr+1; (* 1. Byte der naechsten Variable (oder 0) *) end; end; cmd_xargv:=Anz; end; end; procedure cmd_getxargv(n:integer;var arg:string); type onechar=array[1..2] of char; var bp:BasPagPtr; cptr,copy:record case boolean of true: (adr:long_integer); false:(ptr:^onechar); end; VarName:string[5]; i:integer; Fertig,Leer:boolean; begin basepage(bp); Fertig:=false; cptr.adr:=bp^.p_env; while (not fertig) do begin copy.adr:=cptr.adr; VarName:=''; for i:=1 to 5 do begin VarName:=concat(VarName,copy.ptr^[1]); copy.adr:=copy.adr+1; end; if (VarName='ARGV=') then begin (* prfen, ob Parameter leer sein soll *) VarName:=''; copy.adr:=cptr.adr+5; for i:=1 to 5 do begin VarName:=concat(VarName,copy.ptr^[1]); copy.adr:=copy.adr+1; end; if (VarName='NULL:') then begin (* Es gibt leere Parameter *) cptr.adr:=cptr.adr+10; Leer:=false; while (cptr.ptr^[1]<>chr(0)) do begin copy.adr:=cptr.adr; VarName:=''; while (copy.ptr^[1]<>',') do begin VarName:=concat(VarName,copy.ptr^[1]); copy.adr:=copy.adr+1; end; readv(VarName,i); Leer:=Leer or (i=n); cptr.adr:=copy.adr+1; end; end else Leer:=false; (* ersten Parameter suchen *) while (cptr.ptr^[1]<>chr(0)) do cptr.adr:=cptr.adr+1; cptr.adr:=cptr.adr+1; (* 1. Parameter *) (* die ersten n-1 Parameter berlesen *) for i:=1 to (n-1) do begin while (cptr.ptr^[1]<>chr(0)) do cptr.adr:=cptr.adr+1; cptr.adr:=cptr.adr+1; end; arg:=''; if not Leer then while (cptr.ptr^[1]<>chr(0)) do begin arg:=concat(arg,cptr.ptr^[1]); cptr.adr:=cptr.adr+1; end; fertig:=true; end else begin (* naechste Environmentvariable *) while (cptr.ptr^[1]<>chr(0)) do cptr.adr:=cptr.adr+1; cptr.adr:=cptr.adr+1; (* 1. Byte der naechsten Variable (oder 0) *) end; end; end; procedure make_xargv(var env:long_integer;argc:integer;argv:long_integer); var OldSizeEnv,ArgvSize,Len,i:integer; NewEnv,Lauf,Ort:long_integer; Str:record case boolean of true: (adr:long_integer); false:(ptr:^string); end; XargVar:string[255]; Buf:string[20]; Leer:boolean; bp:BasPagPtr; function size_env:integer; type onechar=array[1..2] of char; var bp:BasPagPtr; cptr,copy:record case boolean of true: (adr:long_integer); false:(ptr:^onechar); end; i:integer; VarName:string[5]; begin basepage(bp); cptr.adr:=bp^.p_env; while (cptr.ptr^[1]<>chr(0)) do begin copy.adr:=cptr.adr; VarName:=''; for i:=1 to 5 do begin VarName:=concat(VarName,copy.ptr^[1]); copy.adr:=copy.adr+1; end; if (VarName='ARGV=') then cptr.ptr^[1]:=chr(0) else begin (* Environment-Variable berlesen *) while (cptr.ptr^[1]<>chr(0)) do cptr.adr:=cptr.adr+1; cptr.adr:=cptr.adr+1; end; end; (* Die abschliessende Null als Environment-Ende wird nicht mitgez„hlt *) size_env:=cptr.adr-bp^.p_env; end; procedure memcpy(dest,src:long_integer;anz:integer); type onebyte=array[1..2] of byte; var LaufS,LaufD:record case boolean of true :(adr:long_integer); false:(ptr:^onebyte); end; i:integer; begin LaufS.adr:=src; LaufD.adr:=dest; for i:=1 to anz do begin LaufD.ptr^[1]:=LaufS.ptr^[1]; LaufS.adr:=LaufS.adr+1; LaufD.adr:=LaufD.adr+1; end; end; procedure strcpy(dest:long_integer;src:string); type onebyte=array[1..2] of byte; var Lauf:record case boolean of true :(adr:long_integer); false:(ptr:^onebyte); end; i:integer; begin Lauf.adr:=dest; for i:=1 to length(src) do begin Lauf.ptr^[1]:=ord(src[i]); Lauf.adr:=Lauf.adr+1; end; Lauf.ptr^[1]:=0; end; procedure cpyarg(var dest:long_integer;src:long_integer); type onebyte=array[1..2] of byte; var Lauf:record case boolean of true :(adr:long_integer); false:(ptr:^onebyte); end; StrPtr:record case boolean of true: (adr:long_integer); false:(ptr:^string); end; i:integer; begin Lauf.adr:=dest; StrPtr.adr:=src; for i:=1 to length(StrPtr.ptr^) do begin Lauf.ptr^[1]:=ord(StrPtr.ptr^[i]); Lauf.adr:=Lauf.adr+1; end; Lauf.ptr^[1]:=0; dest:=dest+length(StrPtr.ptr^)+1; end; procedure SetzNull(dest:long_integer); type onebyte=array[1..2] of byte; var Lauf:record case boolean of true :(adr:long_integer); false:(ptr:^onebyte); end; begin Lauf.adr:=dest; Lauf.ptr^[1]:=0; end; begin XargVar:='ARGV=NULL:'; OldSizeEnv:=size_env; (* Gr”že des alten environments *) (* zus„tzliche Gr”že fr Parameter ermitteln *) ArgvSize:=0; Leer:=false; if (argc>0) then begin Str.adr:=argv; for i:= 1 to argc do begin Len:=length(Str.ptr^); if (Len=0) then begin ArgvSize:=ArgvSize+2; (* XARGV-Konvention! Leerzeichen + Null *) (* Wert von ARGV um Position von Nullparmeter erweitern *) writev(Buf,i); XargVar:=concat(XargVar,Buf,','); Leer:=true; end else ArgvSize:=ArgvSize+Len+1; Str.adr:=Str.adr+4; end; ArgvSize:=ArgvSize+7; (* "ARGV" plus Nullbytes *) end; NewEnv:=Malloc(OldSizeEnv+ArgvSize); if (NewEnv<>0) then begin (* Zuerst altes Environment kopieren *) basepage(bp); memcpy(NewEnv,bp^.p_env,OldSizeEnv); Lauf:=NewEnv+OldSizeEnv; (* Kommandozeilenparameter anh„ngen *) if (argc>0) then begin if (not Leer) then begin (* keine Nullparameter -> "NULL:" l”schen *) XargVar[6]:=' '; XargVar[0]:=chr(6); Ort:=Lauf+5; end else Ort:=Lauf+length(XargVar)-1; strcpy(Lauf,XargVar); Lauf:=Ort+1; for i:=1 to argc do cpyarg(Lauf,argv); SetzNull(Ort); end; SetzNull(Lauf); (* Ende des Environments markieren *) end; env:=NewEnv; end; procedure end_xargv(var env:long_integer); var erg:long_integer; begin if env<>0 then begin erg:=Mfree(env); env:=0; end; end; begin end.
argv.def
DEFINITION MODULE Argv; FROM SYSTEM IMPORT ADDRESS; FROM Strings IMPORT String; TYPE ArgPtr=POINTER TO String; PROCEDURE GetArgv(VAR argc:INTEGER; VAR argv:ARRAY OF CHAR); PROCEDURE GetXargv(VAR argc:INTEGER;VAR argv:ADDRESS):BOOLEAN; PROCEDURE GetXargvEnd(VAR argv:ADDRESS); PROCEDURE DoXargv(VAR env:ADDRESS;argv:ARRAY OF ArgPtr); PROCEDURE DoXargvEnd(VAR env:ADDRESS); END Argv.
argv.mod
IMPLEMENTATION MODULE Argv; FROM SYSTEM IMPORT ADDRESS,ADR,BYTE,LONG,SHORT; FROM GEMDOS IMPORT SetDTA; FROM GEMX IMPORT BasePage,BasePagePtr; FROM Storage IMPORT ALLOCATE,DEALLOCATE; FROM Strings IMPORT String,Length,Concat; TYPE DTA=RECORD reserviert:ARRAY[0..21] OF BYTE; zeit:INTEGER; datum:INTEGER; groesse:LONGINT; name:String; END; VAR mydta:DTA; PROCEDURE GetArgv(VAR argc:INTEGER;VAR argv:ARRAY OF CHAR); TYPE EnvFeld=ARRAY[0..255] OF CHAR; VAR index:INTEGER; Dummy:ADDRESS; Env:POINTER TO EnvFeld; BEGIN (* Da Recordkomponente vom Typ LONGINT *) (* -> Typwandlung in Zeiger auf Feld *) Dummy:=BasePagePtr^.EnvPtr; Env:=Dummy; (* Anzahl der Eintraege holen *) argc:=ORD(Env^[0]); index:=1; (* Argumentstring kopieren *) REPEAT argv[index]:=Env^[index+1]; index:=index+1; UNTIL argv[index-1]=0C; END GetArgv; PROCEDURE GetXargv(VAR argc:INTEGER;VAR argv:ADDRESS):BOOLEAN; VAR Dummy:ADDRESS; Env,Startpar,ArgvValue,s:POINTER TO CHAR; idx:INTEGER; PROCEDURE AddOffs(VAR ptr:ADDRESS;Offs:LONGINT); VAR Lp:POINTER TO LONGINT; BEGIN Lp^:=ADR(ptr); Lp^:=Lp^+Offs; END AddOffs; PROCEDURE strncmp(a:ADDRESS;b:String;Anz:INTEGER):BOOLEAN; VAR i:INTEGER; Erg:BOOLEAN; Dum:POINTER TO String; BEGIN Dum:=a; Erg:=TRUE; FOR i:=0 TO Anz-1 DO Erg:=Erg AND (Dum^[i]=b[i]); END; RETURN Erg; END strncmp; PROCEDURE GetArgv(Env:ADDRESS):ADDRESS; TYPE CPtr=POINTER TO CHAR; VAR c:CPtr; d:ADDRESS; PROCEDURE ptrncmp(c:CPtr;b:String;Anz:INTEGER):BOOLEAN; VAR i:INTEGER; Erg:BOOLEAN; DumA:ADDRESS; DumS:POINTER TO String; BEGIN DumA:=c; DumS:=DumA; Erg:=TRUE; FOR i:=0 TO Anz-1 DO Erg:=Erg AND (DumS^[i]=b[i]); END; RETURN Erg; END ptrncmp; PROCEDURE strlen(c:CPtr):LONGINT; VAR DumA:ADDRESS; DumS:POINTER TO String; BEGIN DumA:=c; DumS:=DumA; RETURN LONG(Length(DumS^)+1); END strlen; BEGIN c:=Env; WHILE (c^#0C) DO IF (NOT ptrncmp(c,'ARGV=',5)) THEN c^:=0C; d:=c; RETURN d+5D; ELSE d:=c; AddOffs(d,strlen(c)); c:=d; END; END; RETURN 0D; END GetArgv; PROCEDURE IsGleich(VAR a:ADDRESS;b:LONGINT):BOOLEAN; VAR Lp:POINTER TO LONGINT; BEGIN Lp:=ADR(a); RETURN Lp^=b; END IsGleich; PROCEDURE SetAdr(dest:ADDRESS;Offs:INTEGER;Wert:ADDRESS); VAR Ort:ADDRESS; Op:POINTER TO ADDRESS; BEGIN Ort:=dest; AddOffs(Ort,LONG((Offs-1)*4)); Op:=Ort; Op^:=Wert; END SetAdr; PROCEDURE DelArg(dest:ADDRESS;Offs:INTEGER); VAR Ort:ADDRESS; Op:POINTER TO String; BEGIN Ort:=dest; AddOffs(Ort,LONG((Offs-1)*4)); Op:=Ort; Op^[0]:=0C; END DelArg; BEGIN (* Da Recordkomponente vom Typ LONGINT *) (* -> Typwandlung in Zeiger auf Feld *) Dummy:=BasePagePtr^.EnvPtr; SetDTA(ADR(mydta)); (* damit 1. Fsfirst nicht Komandozeile ueberschreibt *) IF (BasePagePtr^.CmdLine[0]#CHR(127)) THEN (* Flag fuer Verwendung von ARGV *) argc:=-1; argv:=0D; RETURN FALSE; ELSE (* Zeiger auf Env-Var merken *) ArgvValue:=GetArgv(Dummy); Env:=ArgvValue; IF (IsGleich(Env,0D)) THEN (* ARGV steht nicht im Environment *) argc:=-1; argv:=0D; RETURN FALSE; ELSE (* auf extended ARGV testen *) IF (strncmp(ArgvValue,'NULL:',5)) THEN ArgvValue:=NIL; ELSE AddOffs(ArgvValue,5D); END; (* zu argv[0] gehen *) WHILE (Env^#0C) DO AddOffs(Env,1D); END; (* Parameterstart *) Startpar:=Env; (* Parameter zaehlen *) argc:=0; WHILE (Env^#0C) DO argc:=argc+1; WHILE (Env^#0C) DO AddOffs(Env,1D); END; END; (* Speicher fuer neuen Argumment-Vektor *) ALLOCATE(argv,(argc+1)*4); Env:=Startpar; argc:=0; WHILE (Env^#0C) DO SetAdr(argv,argc,Env); argc:=argc+1; WHILE (Env^#0C) DO AddOffs(Env,1D); END; END; SetAdr(argv,argc,0D); (* Leere Argumente vernichten *) IF (ArgvValue#NIL) THEN idx:=0; WHILE ((ArgvValue^#0C) AND (idxCHR('9')) THEN idx:=argc+1; ELSE idx:=idx*10; idx:=idx+ORD(s^)-ORD('0'); AddOffs(s,1D); END; END; IF (s^=',') THEN AddOffs(s,1D); END; ArgvValue:=s; IF (idx 0) THEN FOR i:=1 TO HIGH(argv) DO Len:=Length(argv[i]^); IF (Len=0) THEN ArgvSize:=ArgvSize+2; (* XARGV-Konvention! Leerzeichen + Null *) (* Wert von ARGV um Position von Nullparmeter erweitern *) writev(Buf,i); Concat(XargVar,Buf,XargVar); Buf:=','; Concat(XargVar,Buf,XargVar); Leer:=TRUE; ELSE ArgvSize:=ArgvSize+Len+1; END; END; ArgvSize:=ArgvSize+7; (* "ARGV" plus Nullbytes *) END; ALLOCATE(NewEnv,OldSizeEnv+ArgvSize); IF (NewEnv<>NIL) THEN (* Zuerst altes Environment kopieren *) memcpy(NewEnv,BasePagePtr^.EnvPtr,OldSizeEnv); lptr:=ADR(Lauf); dptr:=ADR(NewEnv); lptr^:=dptr^+LONG(OldSizeEnv); (* Kommandozeilenparameter anhaengen *) IF (HIGH(argv)>0) THEN IF (NOT Leer) THEN (* keine Nullparameter -> "NULL:" loeschen *) XargVar[5]:=' '; XargVar[9]:=0C; dptr:=ADR(Ort); lptr:=ADR(Lauf); dptr^:=lptr^+5D; ELSE dptr:=ADR(Ort); lptr:=ADR(Lauf); dptr^:=lptr^+LONG(Length(XargVar))-1D; END; strcpy(Lauf,XargVar); dptr:=ADR(Ort); lptr:=ADR(Lauf); lptr^:=dptr^+1D; FOR i:=1 TO HIGH(argv) DO CopyArg(Lauf,argv[i]); END; SetzNull(Ort); END; SetzNull(Lauf); (* Ende des Environments markieren *) END; env:=NewEnv; END DoXargv; PROCEDURE DoXargvEnd(VAR env:ADDRESS); BEGIN IF env<>NIL THEN DEALLOCATE(env); env:=NIL; END; END DoXargvEnd; END Argv.
![]()
English version not yet available.
Änderungen und Irrtümer vorbehalten. Letzte Änderung:
09 Oktober 2004.
Home - Mail an den Webmaster - Impressum