home *** CD-ROM | disk | FTP | other *** search
- (*
- (* :Program. DoVer.mod
- ** :Contents. search $VER and copy them to filecomment
- ** :Author. Bert Jahn
- ** :EMail. jah@fh-zwickau.de
- ** :Address. Franz-Liszt-Straße 16, Rudolstadt, 07404, Germany
- ** :History. V0.1 24.01.95 Beta
- ** V1.0 06.03.95
- ** V1.1 13.11.95 minor changes
- ** 26.11.95 changes in GetResidentID.asm
- ** released on aminet
- ** 16.12.95 added PREPEND,APPEND
- ** V1.2 released on aminet
- ** 23.12.95 added CONVERTDATE
- ** V1.3 released on aminet
- ** 07.03.96 added SHORT
- ** V1.4 released on aminet
- ** 15.09.96 complete new parsing of version string
- ** new option FMT/K to set version format from commandline
- ** option SHORT removed because now obsolete
- ** searchloop optimized a bit
- ** 17.09.96 CONVERTDATE removed, it's now automatically done if FMT is specified
- ** V1.5 released on aminet
- ** 28.09.96 min length for formats ("FMT=") added
- ** added multiple files as argument ("FILE/A/M")
- ** V1.6 released on aminet
- ** 14.06.97 month as string compare is now case insensitive
- ** V1.7 released on aminet
- ** 27.06.97 selectable fillchar implemented
- ** V1.8 released on aminet
- ** :Copyright. Public Domain
- ** :Language. Oberon
- ** :Translator. Amiga Oberon 3.11 (Includes 40.15)
- *)
- *)
-
- (* $ClearVars+ *) (* important; all other switches should turned off *)
-
- MODULE DoVer;
-
- IMPORT
- SYS := SYSTEM,
- d := Dos,
- ds := DosSupport,
- e := Exec,
- str := Strings,
- xfd := XFDmaster,
- xfds := XFDsupport;
-
- CONST
- version = "$VER: DoVer V1.8 (27.06.97) by Bert Jahn";
- template = "FILE/A/M,FMT/K,DEFAULT/K,FORCE/S,APPEND/S,PREPEND/S,QUIET/S,NOCOMM/S";
-
- TYPE
- Args = STRUCT (dummy: d.ArgsStruct)
- file : d.ArgStringArray; (* Files to scan *)
- fmt : d.ArgString; (* version format *)
- default : d.ArgString; (* default string for SetComment *)
- force : d.ArgBool; (* overwrite old comment *)
- append : d.ArgBool; (* append ver onto end of any exist filenote *)
- prepend : d.ArgBool; (* add ver onto start of any exist filenote *)
- quiet : d.ArgBool; (* be quiet, only errmsg output *)
- nocomm : d.ArgBool; (* don't set comment *)
- END;
-
- VAR
- rd : d.RDArgsPtr; (* for ReadArgs *)
- args : Args;
- buffer : ARRAY 256 OF CHAR; (* the comment *)
- f : xfds.FileDescr;
- fileadr : e.LSTRPTR;
- i : INTEGER;
-
-
-
- (* copy string filtered to arrayofchar *)
- (* src sourcestring
- dest space for deststring; LEN(dest) must valid ! *)
- PROCEDURE ParseString(src: e.LSTRPTR; VAR dest: ARRAY OF CHAR);
- VAR
- s,d,e,z : LONGINT;
- name,ver,date,ext : ARRAY 128 OF CHAR;
- day,mon,year,t : INTEGER;
- c : CHAR;
- fc : CHAR; (* fillchar *)
- TYPE
- MonthType = ARRAY 12 OF ARRAY 4 OF CHAR;
- CONST
- month = MonthType ("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"); (* english *)
- monthg = MonthType ("JAN","FEB","MÄR","APR","MAI","JUN","JUL","AUG","SEP","OKT","NOV","DEZ"); (* german *)
-
- (* transform string(date) to integer, returns endpos of int *)
- PROCEDURE Str2Int(VAR x: INTEGER):BOOLEAN;
- BEGIN
- x := 0;
- LOOP
- c := date[s];
- IF (c>='0') & (c<='9') THEN
- x := 10 * x + ORD(c) - ORD('0');
- INC(s);
- ELSE
- IF x=0 THEN
- RETURN FALSE;
- ELSE
- RETURN TRUE;
- END;
- END;
- END;
- END Str2Int;
-
- (* append one character to dest[], returns true if buffer is full *)
- PROCEDURE CatChar(ch: CHAR): BOOLEAN;
- BEGIN
- IF d >= LEN(dest)-1 THEN
- IF e # 0 THEN (* buffer full -> seems it's a text file *)
- d := e; (* use earlier LF for terminating *)
- ELSE
- d := LEN(dest)-1
- END;
- RETURN TRUE;
- ELSE
- IF (d#0) OR (ch#' ') THEN (* to overread the first space *)
- dest[d] := ch;
- INC(d);
- END;
- RETURN FALSE;
- END;
- END CatChar;
-
- (* append an integer value as ascii to string *)
- PROCEDURE AppendInt(VAR s:ARRAY OF CHAR; i:INTEGER; min:LONGINT);
- VAR
- b : ARRAY 5 OF INTEGER; (* max 5 digits ! *)
- c : INTEGER;
- BEGIN
- c := 0;
- REPEAT
- b[c] := i MOD 10;
- i := i DIV 10;
- INC(c);
- UNTIL i = 0;
- WHILE min>c DO (* prepend SPACE's if required *)
- str.AppendChar(s,' ');
- DEC(min);
- END;
- REPEAT
- DEC(c);
- str.AppendChar(s,CHR(ORD('0')+b[c]));
- UNTIL c = 0;
- END AppendInt;
-
- (* append string to string with minimum length *)
- PROCEDURE AppendStr(VAR s1:ARRAY OF CHAR; VAR s2:ARRAY OF CHAR; min:LONGINT);
- VAR
- l : LONGINT;
- BEGIN
- l := str.Length(s2);
- WHILE min>l DO
- str.AppendChar(s1,fc);
- DEC(min);
- END;
- str.Append(s1,s2);
- END AppendStr;
-
-
- BEGIN
- (* first remove all control codes and find end of string *)
- LOOP
- CASE src[s] OF
- 0X : EXIT; (* end reached *)
- | 1X .. 8X : ; (* ignore *)
- | 9X : IF CatChar(' ') THEN EXIT END; (* tabulator -> space *)
- | 0AX : IF CatChar(' ') THEN EXIT END; IF (e = 0) THEN e := d; END; (* save pos of LF terminating *)
- | 0BX..1FX : ; (* ignore *)
- | 0A0X : IF CatChar(' ') THEN EXIT END; (* whitespace -> space *)
- ELSE IF CatChar(src[s]) THEN EXIT END; (* copy *)
- END;
- INC(s);
- END;
- dest[d] := 0X; (* terminate buffer *)
-
- (* check for users format *)
- IF args.fmt = NIL THEN RETURN END;
-
- (* now split the string off *)
- s:=0;
- (* get name *)
- d:=0;
- WHILE ( (d<LEN(name)-1) AND (dest[s]#0X) AND (dest[s]#' ') ) DO
- name[d]:=dest[s];
- INC(d); INC(s);
- END;
- name[d]:=0X;
- (* get version *)
- WHILE ( (dest[s]=' ') OR (dest[s]='v') OR (dest[s]='V') ) DO INC(s); END;
- d:=0;
- WHILE ( (d<LEN(ver)-1) AND (dest[s]#0X) AND (dest[s]#' ') ) DO
- ver[d]:=dest[s];
- INC(d); INC(s);
- END;
- ver[d]:=0X;
- (* get date *)
- WHILE dest[s]=' ' DO INC(s); END;
- d:=0;
- WHILE ( (d<LEN(date)-1) AND (dest[s]#0X) AND ~((date[0]='(') AND (date[d-1]=')')) AND ~((date[0]#'(') AND (dest[s]=' ')) ) DO
- date[d]:=dest[s];
- INC(d); INC(s);
- END;
- date[d]:=0X;
- (* get extra *)
- WHILE dest[s]=' ' DO INC(s); END;
- d:=0;
- WHILE ( (d<LEN(ext)-1) AND (dest[s]#0X) ) DO
- ext[d]:=dest[s];
- INC(d); INC(s);
- END;
- ext[d]:=0X;
-
- (* decode the datestamp *)
- s := 0;
- WHILE (date[s]='(') OR (date[s]=' ') DO INC(s); END;
- IF ~ Str2Int(day) THEN
- (* Dec 1 1992 *)
- t := 0;
- WHILE t<12 DO
- IF (date[s]=month[t][0]) AND (date[s+1]=month[t][1]) AND (date[s+2]=month[t][2]) THEN mon:=t+1; END;
- INC(t);
- END;
- IF mon # 0 THEN
- WHILE (date[s]#0X) AND ((date[s]<'0') OR (date[s]>'9')) DO INC(s); END;
- IF Str2Int(day) THEN END;
- IF date[s]=' ' THEN INC(s); END;
- END;
- ELSE
- (* 1.12.92 *)
- IF date[s]#0X THEN INC(s) END;
- IF ~ Str2Int(mon) THEN
- (* 1-Dec-92 *)
- t := 0;
- WHILE t<12 DO
- IF (CAP(date[s])=month[t][0]) AND (CAP(date[s+1])=CAP(month[t][1])) AND (CAP(date[s+2])=CAP(month[t][2])) THEN mon:=t+1; END;
- INC(t);
- END;
- IF mon = 0 THEN
- (* 1-Dez-92 german *)
- t := 0;
- WHILE t<12 DO
- IF (str.CapIntl(date[s])=monthg[t][0]) AND (str.CapIntl(date[s+1])=monthg[t][1]) AND (str.CapIntl(date[s+2])=monthg[t][2]) THEN mon:=t+1; END;
- INC(t);
- END;
- END;
- END;
- WHILE (date[s]#0X) AND ((date[s]<'0') OR (date[s]>'9')) DO INC(s); END;
- END;
- IF (day # 0 ) AND (mon # 0) THEN
- IF Str2Int(year) THEN
- IF day > 31 THEN t:=day;day:=year;year:=t; END; (* swap day - year *)
- IF year > 99 THEN DEC(year,1900); END; (* 1992 *)
- IF year > 99 THEN DEC(year,100); END; (* 2010 *)
- END;
- END;
-
- IF (ver[0]>='0') AND (ver[0]<='9') AND (day>0) AND (day<=31) AND (mon>0) AND (mon<=12) AND (year<100) THEN
- (* build final version string *)
- dest[0] := 0X;
- t := 0;
- WHILE args.fmt^[t] # 0X DO
- IF args.fmt^[t] = '%' THEN
- c := args.fmt^[t+1];
- IF (c='0') THEN fc:=c; ELSE fc:=' '; END;
- s := 0;
- WHILE (c>='0') AND (c<='9') DO
- s := 10 * s + ORD(c) - ORD('0');
- INC(t);
- c := args.fmt^[t+1];
- END;
- CASE args.fmt^[t+1] OF
- 'n' : AppendStr(dest,name,s);
- | 'v' : AppendStr(dest,ver,s);
- | 'd' : AppendInt(dest,day,s);
- | 'm' : AppendInt(dest,mon,s);
- | 'M' : AppendStr(dest,month[mon-1],s);
- | 'y' : AppendInt(dest,year,s);
- | 'Y' : IF year >= 78 THEN
- AppendInt(dest,year+1900,s);
- ELSE
- AppendInt(dest,year+2000,s);
- END;
- | 'e' : AppendStr(dest,ext,s);
- | '%' : str.AppendChar(dest,'%');
- | 0X : DEC(t);
- ELSE ;
- END;
- INC(t);
- ELSE
- str.AppendChar(dest,args.fmt^[t]);
- END;
- INC(t);
- END;
- END;
-
- END ParseString;
-
-
-
- (* relocate the file if possible and search for resident structure *)
- PROCEDURE CheckResident(VAR src: ARRAY OF CHAR; srclen: LONGINT; VAR dest: ARRAY OF CHAR): BOOLEAN;
- VAR
- str : e.LSTRPTR;
- bptr : e.BPTR;
- ret : BOOLEAN;
- xerr : e.UWORD;
-
- (* Sorry, I failed to write this in Oberon ! *)
- (* searchs for resident structure and return address of idstring if found *)
- (* see GetResidentID.asm for source *)
- PROCEDURE GetResidentID {"_GetResidentID"} (segment {8}:e.BPTR): e.APTR;
- (* $JOIN GetResidentID.o *)
-
- BEGIN
- (* $IFNOT ClearVars *) ret := FALSE; (* $END *)
- IF (srclen >= 3) & (src[3] = 0F3X) THEN (* is't an executable ? *)
- IF xfd.base # NIL THEN
- xerr := xfd.Relocate(srclen,xfd.relDefault,SYS.ADR(src),bptr);
- IF xerr # xfd.errOk THEN
- d.PrintF("relocating error: %s\n",xfd.GetErrorText(xerr));
- ELSE
- str := GetResidentID(bptr);
- IF str # NIL THEN
- ParseString(str,dest); (* no sizecheck because possible string outside first segment ... *)
- ret := TRUE;
- END;
- d.UnLoadSeg(bptr);
- END
- END;
- END;
- RETURN ret;
- END CheckResident;
-
-
-
- (* search the VerString in "src" and copy them to "dest" if found *)
- (* "srclen" is used instead of LEN(src) so "src" can be "e.LSTRPTR^" or "e.APTR^" *)
- PROCEDURE CheckVerStr(VAR src: ARRAY OF CHAR; srclen: LONGINT; VAR dest: ARRAY OF CHAR): BOOLEAN;
- VAR
- ret : BOOLEAN; (* RETURN Code *)
- a : LONGINT; (* offsets in array *)
- BEGIN
- (* $IFNOT ClearVars *) ret := FALSE; a := 0; (* $END *)
- DEC(srclen,6); (* opt *)
- WHILE (~ ret) & (a < srclen) DO
- IF src[a]="$" THEN
- INC(a);
- IF (src[a]="V") OR (src[a]="v") THEN
- INC(a);
- IF (src[a]="E") OR (src[a]="e") THEN
- INC(a);
- IF (src[a]="R") OR (src[a]="r") THEN
- INC(a);
- IF (src[a]=":") THEN ret := TRUE; END;
- END
- END
- END
- ELSE
- INC(a);
- END;
- END;
- IF ret THEN
- INC(a);
- ParseString(SYS.ADR(src[a]),dest);
- END;
- RETURN ret;
- END CheckVerStr;
-
-
-
- (* set the file comment *)
- PROCEDURE SetComment(VAR comment: ARRAY OF CHAR);
- VAR
- lock : d.FileLockPtr;
- fib : d.FileInfoBlockPtr;
- set : BOOLEAN;
- cmt : ARRAY 79 OF CHAR;
- BEGIN
- IF args.nocomm = 0 THEN
- (* $IFNOT ClearVars *) set := FALSE; (* $END *)
- cmt[0] := 0X; str.Append(cmt,comment);
- IF args.force # 0 THEN
- set := TRUE;
- ELSE
- lock := d.Lock(args.file[i]^,d.accessRead);
- IF lock = NIL THEN
- ds.PrintFault;
- ELSE
- NEW(fib);
- IF fib = NIL THEN
- ds.PrintMemErr;
- ELSE
- IF ~ d.Examine(lock,fib^) THEN
- ds.PrintFault;
- ELSE
- IF args.append # 0 THEN
- cmt[0] := 0X; str.Append(cmt,fib.comment);
- str.Append(cmt," ");
- str.Append(cmt,comment);
- set:=TRUE;
- ELSIF args.prepend #0 THEN
- str.Append(cmt," ");
- str.Append(cmt,fib.comment); set:=TRUE;
- ELSIF fib.comment[0] = 0X THEN
- set := TRUE;
- END;
- END;
- DISPOSE(fib);
- END;
- d.UnLock(lock);
- END
- END;
- IF set THEN
- IF ~ d.SetComment(args.file[i]^,cmt) THEN ds.PrintFault; END;
- END
- END
- END SetComment;
-
-
-
- PROCEDURE PrintMsg(str: e.LSTRPTR);
- BEGIN
- IF args.quiet = 0 THEN
- d.PrintF("%s\t- %s\n",args.file[i],str);
- END
- END PrintMsg;
-
-
-
- (* main *)
- BEGIN
- SYS.SETREG(8,SYS.ADR(version)); (* that the version string will linked *)
- IF d.base.lib.version < 37 THEN
- HALT(20);
- ELSE
- rd := d.ReadArgs(template,args,NIL);
- IF rd = NIL THEN
- ds.PrintFault;
- ELSE
- IF args.force + args.append + args.prepend < -1 THEN (* it's not fine but works *)
- d.PrintF("only one of FORCE APPEND PREPEND can specified\n");
- ELSE
- WHILE args.file[i] # NIL DO
- f.name := args.file[i];
- f.passwd := NIL; (* no passwd support *)
- IF xfds.LoadFile(f) THEN
- fileadr := f.address;
- IF CheckVerStr(fileadr^,f.size,buffer) OR CheckResident(fileadr^,f.size,buffer) THEN
- PrintMsg(SYS.ADR(buffer));
- SetComment(buffer);
- ELSE
- PrintMsg(SYS.ADR("No VersionString found"));
- IF args.default # NIL THEN
- SetComment(args.default^);
- END
- END;
- xfds.UnLoadFile(f);
- END;
- INC(i);
- END;
- END;
- d.FreeArgs(rd);
- END
- END
- END DoVer.
-
-