home *** CD-ROM | disk | FTP | other *** search
- Program simrazor;
- { Shortens a MailMerge export of a SimIBM database index file by removing }
- { unwanted fields, or parts thereof. }
- { Optionally, merges multiple input files. }
- { Specify parameters on command line; call without parameters for help. }
- { FreeWare by TapirSoft Gisbert W.Selke, Dec 89 }
- { This programme comes as is; no guarantees whatsoever! }
-
- { Compiled under MS DOS 3.3, using TurboPascal 5.5 }
-
- { DEFINE DEBUG } { $DEFINE while debugging }
-
- {$A+,B-,D+,E+,F-,I-,L+,N-,O-,V-}
- {$IFDEF DEBUG }
- {$R+,S+ }
- {$ELSE }
- {$R-,S- }
- {$ENDIF }
-
- {$M 65520,0,400000 }
-
- Const progname = 'SIMRAZOR';
- version = '1.3';
- copyright = 'FreeWare (c) TapirSoft Gisbert W.Selke, Dec 89';
- bufsize = 64000;
- maxlength = 50; { maximum field length in input files }
- maxinfields = 10; { number of fields in input files }
- maxinfiles = 5; { maximum number of input files }
- maxoutfields = 15; { max number of output fields }
- fieldnum : Array [1..maxinfields] Of boolean =
- (False,False,False,True,True,True,True,False,False,False);
- { False = ASCII; True = numeric }
-
- Type buffer = Array [1..bufsize] Of byte; { i/o buffer }
- bufptr = ^buffer;
- name = string[80]; { file name }
- tentry = string[maxlength]; { single field }
- entry = Array [1..maxinfields] Of tentry;{ input record }
- extry = Array [1..maxoutfields] Of tentry;{ output record }
-
- Var fout : text; { output file }
- outname : name; { name of output file }
- outbufptr: bufptr; { output buffer }
- fin : Array [1..maxinfiles] Of text; { input files }
- inname : Array [1..maxinfiles] Of name; { names of input files }
- inbufptr : Array [1..maxinfiles] Of bufptr;{ input buffers }
- e : Array [1..maxinfiles] Of extry; { current input records }
- eoff : Array [1..maxinfiles] Of boolean;{ input eof flags }
- ctout : longint; { count of output records }
- ctin : Array [1..maxinfiles] Of longint;{ counts of input records }
- outfld : Array [1..maxoutfields] Of byte;{ pointers to output fields }
- outlen : Array [1..maxoutfields] Of integer;{ lengths of output fields }
- ninfiles : byte; { number of input files }
- noutfields : byte; { number of output fields }
- choose : byte; { pointer to record for output}
- nopen : byte; { number of open input files }
- i : byte;
-
- Function ReadKey : Char;
- { read a char from StdIn without echoing; don't need CRT unit for this! }
- Inline($B4/$07/ {Mov ah, 7}
- $CD/$21); {Int $21}
-
- Function yesnoq : boolean;
- { get a yes-or-no answer }
- Var ch : char;
- Begin { yesnoq }
- Repeat
- ch := UpCase(ReadKey);
- Until ch In ['Y','J','1','N','0'];
- writeln(ch);
- yesnoq := ch In ['Y','J','1'];
- End; { yesnoq }
-
- Procedure abort(errmsg : string; code : byte);
- { abort with error message }
- Begin { abort }
- writeln;
- writeln(errmsg);
- Halt(code);
- End; { abort }
-
- Procedure usage;
- { show usage info and die }
- Begin { usage }
- writeln('Shorten a SimIBM index file by removing unwanted fields.');
- writeln('Optionally merge sorted files.');
- writeln;
- writeln('This programme may be used and copied freely,');
- writeln('but it comes with no guarantees whatsoever.');
- writeln;
- writeln('Usage: SIMRAZOR /F<field>... /I<inname>... /O<outname>');
- writeln(' where <field> is one of A..J, optionally followed by');
- writeln(' a maximum field length (negative length to start from');
- writeln(' the right) (up to ',maxoutfields,' /F options allowed),');
- writeln(' <inname> is an input file name (up to ',maxinfiles,
- ' allowed),');
- writeln(' and <outname> is the output file name.');
- writeln(' (Default extension for files: IDX)');
- writeln(' A = disk; B = directory; C = file name; D = version;');
- writeln(' E = size; F = type; G = date; H = description;');
- writeln(' I = first part of dir; J = second part of directory.');
- writeln;
- writeln('Example:');
- writeln('SIMRAZOR /FI-1 /FJ11 /FC /FE6 /FG /FH /ISIMIBM.IDX ',
- '/OSIMSHORT.IDX');
- Halt(1);
- End; { usage }
-
- Procedure getoneline(Var f : text; Var fieldout : extry);
- { get one line and clean it up }
-
- Var i, k, nf, len : byte;
- exquote : boolean;
- lin : string;
- fields : entry;
-
- Procedure cleanse;
- { perform the cleaning }
- Var i, k, l : byte;
- isquote : boolean;
- Begin { cleanse }
- For i := 1 To noutfields Do
- Begin { check all fields to be output }
- k := outfld[i];
- fieldout[i] := fields[k];
- If k = 9 Then
- Begin { special check for part 1 of dir field: maybe add a blank }
- If fieldout[i] = 'MSDOS' Then fieldout[i] := 'MSDOS ';
- End;
- l := Length(fieldout[i]);
- If l >= 2 Then
- Begin { quoted field }
- isquote := (fieldout[i][1] = '"') And (fieldout[i][l] = '"');
- If isquote Then
- Begin
- fieldout[i] := Copy(fieldout[i],2,l-2);
- l := l - 2;
- End;
- End
- Else isquote := False;
- If l > Abs(outlen[i]) Then
- Begin { input field too long }
- If fieldnum[k] Then
- Begin { numeric field }
- fieldout[i] := '';
- For l := 1 To outlen[i] Do fieldout[i] := fieldout[i] + '9';
- End
- Else
- Begin { ASCII field }
- If outlen[i] >= 0 Then Delete(fieldout[i],Succ(outlen[i]),255)
- Else Delete(fieldout[i],1,l+outlen[i]);
- End;
- End;
- If isquote Then fieldout[i] := '"' + fieldout[i] + '"';
- End;
- End; { cleanse }
-
- Begin { getoneline }
- readln(f,lin);
- len := Length(lin);
- For i := 1 To maxinfields Do fields[i] := '';
- nf := 0;
- i := 1;
- exquote := True;
- While (nf < maxinfields) And (i < len) Do
- Begin
- k := i;
- Repeat
- If lin[i] = '"' Then exquote := Not exquote;
- Inc(i);
- Until (i > len) Or ((lin[i] = ',') And exquote);
- Inc(nf);
- fields[nf] := Copy(lin,k,i-k);
- Inc(i);
- End;
- i := Pos('.',fields[2]);
- fields[Pred(maxinfields)] := Copy(fields[2],2,i-2); { part 1 of dir }
- If (fields[2] <> '') And (fields[2][1] = '"') Then
- Delete(fields[Pred(maxinfields)],1,1);
- fields[maxinfields] := Copy(fields[2],Succ(i),Length(fields[2])-i-1);
- If (fields[2] <> '') And { part 2 of dir }
- (fields[2][Length(fields[2])] = '"') Then
- Delete(fields[maxinfields],Length(fields[maxinfields]),1);
- cleanse;
- End; { getoneline }
-
- Procedure getnextline;
- { get next line from input file(s) }
- Var i, k : byte;
- Begin { getnextline }
- For i := 1 To ninfiles Do
- Begin { read input lines, where necessary and possible }
- If (e[i,1] = '') And (Not eoff[i]) Then
- Begin
- getoneline(fin[i],e[i]);
- If IOResult <> 0 Then abort('Error reading from ' + inname[i] +
- ' - abort!',31);
- Inc(ctin[i]);
- eoff[i] := EoF(fin[i]);
- If eoff[i] Then Dec(nopen);
- End;
- End;
- choose := 1;
- For i := 2 To ninfiles Do
- Begin { find out which of the input record to take next }
- If e[i,1] <> '' Then
- Begin { non-empty record }
- k := 0;
- While k < noutfields Do
- Begin { scan fields in output order }
- Inc(k);
- If e[choose,k] < e[i,k] Then k := noutfields { old guess was better }
- Else
- Begin
- If e[choose,k] > e[i,k] Then
- Begin { new candidate is better }
- choose := i;
- k := noutfields;
- End;
- End;
- End;
- End;
- End;
- End; { getnextline }
-
- Procedure init;
- { scan command line parameters }
- Var temp : string;
- ival : longint;
- icod : integer;
- i : byte;
- Begin { init }
- ninfiles := 0;
- noutfields := 0;
- outname := '';
- For i := 1 To ParamCount Do
- Begin { scan all parameters }
- temp := ParamStr(i);
- If temp = '?' Then usage;
- If (Length(temp) <= 2) Or ((temp[1] <> '/') And (temp[1] <> '-')) Then
- abort('Unknown command line switch ' + temp,2);
- For icod := 1 To Length(temp) Do temp[icod] := UpCase(temp[icod]);
- Case temp[2] Of
- 'F' : Begin { output field spec }
- If noutfields >= maxoutfields Then
- abort('Too many output fields specified',5);
- If (temp[3] < 'A') Or (temp[3] > 'J') Then
- abort('Unknown output field spec in '+ temp,3);
- Inc(noutfields);
- outfld[noutfields] := Ord(temp[3]) - 64;
- If Length(temp) > 3 Then
- Begin { get output field length }
- {$R- } Val(Copy(temp,4,255),ival,icod);
- {$IFDEF DEBUG } {$R+ } {$ENDIF }
- If (icod <> 0) Or (Abs(ival) > 255) Then
- abort('Illegal output field width in ' + temp,4);
- outlen[noutfields] := ival;
- End
- Else outlen[noutfields] := 255;
- End;
- 'I' : Begin { input file name }
- If ninfiles >= maxinfiles Then
- abort('Too many input files',6);
- Inc(ninfiles);
- If Pos('.',temp) = 0 Then temp := temp + '.IDX';
- inname[ninfiles] := Copy(temp,3,255);
- End;
- 'O' : Begin { output file name }
- If outname <> '' Then
- abort('More than one output file',7);
- If Pos('.',temp) = 0 Then temp := temp + '.IDX';
- outname := Copy(temp,3,255);
- End;
- '?', 'H' : usage; { help screen }
- Else abort('Unknown command line switch ' + temp,2);
- End;
- End;
- If noutfields = 0 Then abort('No output fields specified',8);
- If ninfiles = 0 Then abort('No input files specified',9);
- If outname = '' Then abort('No output file specified',10);
- End; { init }
-
- Procedure openfiles;
- { open all files, initialize buffers and records }
- Var savfm, i : byte;
- Begin { openfiles }
- nopen := 0;
- savfm := FileMode;
- FileMode := 0;
- For i := 1 To ninfiles Do
- Begin { open all input files }
- Assign(fin[i],inname[i]);
- If MaxAvail > bufsize Then
- Begin { set aside input buffer, if room available }
- New(inbufptr[i]);
- SetTextBuf(fin[i],inbufptr[i]^);
- End;
- Reset(fin[i]);
- If IOResult <> 0 Then abort('Cannot open ' +inname[i]+ ' for input.',21);
- ctin[i] := 0; { number of records read from this file }
- e[i,1] := ''; { 'no current record from file i' }
- eoff[i] := EoF(fin[i]); { eof status }
- If Not eoff[i] Then Inc(nopen);
- End;
- FileMode := savfm;
- Assign(fout,outname);
- If MaxAvail > bufsize Then
- Begin { set aside output buffer, if room available }
- New(outbufptr);
- SetTextBuf(fout,outbufptr^);
- End;
- Reset(fout);
- If IOResult = 0 Then
- Begin
- write('Output file ',outname,' already exists. Continue? (y/n) ');
- If Not yesnoq Then abort('Existing output file not overwritten.',23);
- Close(fout);
- End;
- Rewrite(fout);
- If IOResult <> 0 Then abort('Cannot open ' + outname + ' for output.',22);
- ctout := 0;
- End; { openfiles }
-
- Begin { main }
- writeln(progname,' ',version,' - ',copyright);
- writeln;
- writeln('Entia non sunt multiplicanda praeter necessitatem.');
- writeln;
- If ParamCount = 0 Then usage;
- init;
- openfiles;
- While nopen > 0 Do
- Begin { while there are records left, process them }
- getnextline;
- Inc(ctout);
- If Lo(ctout) = 0 Then
- Begin { consolate user }
- write(#13,ctout);
- For i := 1 To ninfiles Do write('/',ctin[i]);
- End;
- For i := 1 To Pred(noutfields) Do write(fout,e[choose,i],',');
- writeln(fout,e[choose,noutfields]); { that did the trick }
- If IOResult <> 0 Then abort('Error writing to ' + outname + ' - abort!',32);
- e[choose,1] := ''; { mark this record 'done' }
- End;
- For i := 1 To ninfiles Do Close(fin[i]);
- Close(fout);
- write(#13,ctout);
- For i := 1 To ninfiles Do write('/',ctin[i]);
- writeln(' records processed.');
- { let DOS deallocate buffers }
- End.
-