summaryrefslogtreecommitdiff
path: root/tools.pas
diff options
context:
space:
mode:
Diffstat (limited to 'tools.pas')
-rw-r--r--tools.pas274
1 files changed, 274 insertions, 0 deletions
diff --git a/tools.pas b/tools.pas
new file mode 100644
index 0000000..0a6feb1
--- /dev/null
+++ b/tools.pas
@@ -0,0 +1,274 @@
+unit tools;
+
+{$mode objfpc}{$H+}
+
+interface
+
+uses
+ Classes, SysUtils, Process, lowlevelunit, regExpr;
+
+type
+ tStringlistBArray = array[boolean] of tStringlist;
+ tSummenDatei = record
+ name: string;
+ inhalt: tStringlistBArray;
+ end;
+
+function anzCs(c: char; s: string): longint;
+function notQuotedPos(was,worin: string): longint;
+function unescapedpos(was,worin: string): integer;
+procedure testeObBefehlLokal(bef, ordner: string; lokTest: tRegExpr);
+function extrahiereAlleDateien(woraus: string): tMyStringList;
+
+// Routinen für sha512-Prüfsummen
+
+function testeSummen(sumNam: string): tStringlistBArray;
+function dateienMitGueltigerSumme(sumNam: string): tStringList;
+
+implementation
+
+function anzCs(c: char; s: string): longint;
+var i: longint;
+begin
+ result:=0;
+ for i:=1 to length(s) do
+ if s[i]=c then
+ inc(result);
+end;
+
+function notQuotedPos(was,worin: string): longint;
+begin
+ result:=0;
+ repeat
+ if pos(was,copy(worin,result+1,length(worin)-result))=0 then begin
+ result:=0;
+ exit;
+ end;
+ result:=result+pos(was,copy(worin,result+1,length(worin)-result));
+ if not odd(anzCs('"',copy(worin,1,result-1))) then
+ exit;
+ until false;
+end;
+
+function unescapedpos(was,worin: string): integer;
+var Ebene: longint;
+begin
+ result:=0;
+ Ebene:=0;
+ while pos(was,copy(worin,result+1,length(worin)))>0 do begin
+ repeat
+ result:=result+1;
+ case worin[result] of
+ '{': inc(Ebene);
+ '}': dec(Ebene);
+ end;
+ until (result>=length(worin)) or ((copy(worin,result,length(was))=was) and (Ebene=0));
+ if
+ ((result=1) or ((worin[result-1]<>'\') and (worin[result-1]<>was))) and
+ ((result=length(worin)) or (worin[result+1]<>was)) and
+ (copy(worin,result,length(was))=was) then exit;
+ end;
+ result:=0;
+end;
+
+procedure testeObBefehlLokal(bef, ordner: string; lokTest: tRegExpr);
+var
+ exe,args,regex,oBef,s: string;
+ dateien,sl,relZeil: tMyStringlist;
+ i,j: longint;
+ re: tRegExpr;
+begin
+ oBef:=bef;
+
+ while notQuotedPos(';',bef)>0 do begin
+ testeObBefehlLokal(trim(leftStr(bef,notQuotedPos(';',bef))),ordner,lokTest);
+ delete(bef,1,notQuotedPos(';',bef));
+ bef:=trim(bef);
+ end;
+
+ args:='';
+ repeat
+ exe:=leftstr(bef,notQuotedPos(' ',bef)-1);
+ delete(bef,1,length(exe));
+ if exe='cat' then begin
+ args:=args+' '+trim(leftStr(bef,notQuotedPos('|',bef)-1));
+ delete(bef,1,notQuotedPos('|',bef));
+ end;
+ bef:=trim(bef);
+ until (notQuotedPos('=',bef)=0) and (exe<>'do') and (exe<>'cat');
+
+ delete(args,1,1);
+ exe:=extractfilename(exe);
+
+ if exe='gnuplot' then begin
+ // set output "~/Dokumente/Erich_Masterarbeit/Bilder/gnuplot/Energiescan.tex"
+ regex:='^ *set +output +';
+ re:=tRegExpr.create;
+ re.Expression:='"[^"]*/[^"]*"';
+ end
+ else if exe='epost' then begin
+ // Datei:
+ regex:='^ *(Datei|Legende): *';
+ re:=tRegExpr.create;
+ re.Expression:='[^ :]*/[^ ]*';
+ end
+ else if exe='math' then begin
+ // das wird vmtl. schwer zu überprüfen, außer man nimmt Muster,
+ // die generisch auf Pfade passen, aber dann erwischt man auch den Input mit ...
+ regex:='^([^"]*"[^"]*")*[^"]*"([^"]*/)+[^"]*"';
+ re:=tRegExpr.create;
+ re.Expression:='"[^"]*/[^"]*"';
+ end
+ else exit;
+
+ // folgende Executables sind unkritisch, da der Name des Outputs i.d.R. direkt
+ // vom Namen des Inputs abhängt bzw. per Kommandozeilenparameter übergeben
+ // wird (und nicht in einer Datei steht):
+ //
+ // 'convert'
+ // 'epstopdf'
+ // 'latexmk'
+ // 'mpost'
+ // 'pdflatex'
+
+ dateien:=extrahiereAlleDateien(args+' '+bef);
+ if dateien.count = 0 then
+ writeln('*** Warnung: Hier ist ein Befehl ohne offensichtliche input-Dateien! ('''+oBef+''')!');
+
+ sl:=tMyStringlist.create;
+ relZeil:=tMyStringlist.create;
+ for i:=0 to dateien.count-1 do begin
+ sl.loadFromFile(dateien[i]);
+ sl.grep(regex);
+ relZeil.addStrings(sl);
+ end;
+ sl.free;
+ dateien.free;
+
+ for i:=0 to relZeil.count-1 do begin
+ re.InputString:=relZeil[i];
+ if re.SubExprMatchCount=0 then
+ writeln('*** Warnung: Hier ist eine Zeile in der Optionsdatei, die keine passende Inputdatei benennt, es aber sollte! ('''+relZeil[i]+''')!');
+ for j:=0 to re.SubExprMatchCount-1 do begin
+ s:=trim(re.Match[j]);
+ if (leftStr(s,1)='"') and (rightStr(s,1)='"') then begin
+ delete(s,1,1);
+ delete(s,length(s),1);
+ end;
+ if not lokTest.Exec(s) then begin
+ writeln('*** FEHLER: '''+relZeil[i]+''' in Befehl '''+oBef+''' hat Lokalitätstest nicht bestanden! ('+lokTest.Expression+')');
+ halt(1);
+ end;
+ end;
+ end;
+ re.free;
+ relZeil.free;
+end;
+
+function extrahiereAlleDateien(woraus: string): tMyStringList;
+var
+ s: string;
+begin
+ result:=tMyStringlist.create;
+ woraus:=woraus+' ';
+ while notQuotedPos(' ',woraus)>0 do begin
+ s:=leftStr(woraus,notQuotedPos(' ',woraus));
+ delete(woraus,1,length(s));
+ s:=trim(s);
+ if fileexists(s) then
+ result.add(s);
+ end;
+end;
+
+// Routinen für sha512-Prüfsummen
+
+var
+ Summenvorrat: array of tSummenDatei;
+
+function testeSummen(sumNam: string): tStringlistBArray;
+var p: tProcess;
+ rb,i: longint;
+ s: string;
+ erg: tStringlist;
+ gut: boolean;
+const leseHappen=65536;
+begin
+ for i:=0 to length(Summenvorrat)-1 do
+ if Summenvorrat[i].name=sumNam then begin
+ for gut:=false to true do begin
+ result[gut]:=tStringlist.create;
+ result[gut].text:=Summenvorrat[i].inhalt[gut].text;
+ end;
+ exit;
+ end;
+
+ p:=tProcess.create(nil);
+ p.Executable:='/usr/bin/sha512sum';
+ p.Parameters.add('-c');
+ p.Parameters.add(sumNam);
+ p.Options:=p.Options + [poUsePipes];
+ p.Execute;
+ rb:=0;
+ s:='';
+ while p.Running do begin
+ if p.Output.NumBytesAvailable=0 then sleep(10)
+ else begin
+ setlength(s,rb+leseHappen);
+ rb:=rb+p.Output.Read(s[rb+1],leseHappen);
+ end;
+ end;
+ if p.Output.NumBytesAvailable>0 then begin
+ setlength(s,rb+leseHappen);
+ rb:=rb+p.Output.Read(s[rb+1],leseHappen);
+ end;
+ p.free;
+ setlength(s,rb);
+ erg:=tStringlist.create;
+ erg.text:=s;
+ s:='';
+ for gut:=false to true do begin
+ result[gut]:=tStringlist.create;
+ rb:=0;
+ for i:=0 to erg.count-1 do
+ if not gut xor (rightStr(erg[i],4)=': OK') then begin
+ result[gut].add(leftStr(erg[i],pos(':',erg[i])-1));
+ inc(rb);
+ end;
+ end;
+ erg.free;
+
+ setlength(Summenvorrat,length(Summenvorrat)+1);
+ with Summenvorrat[length(Summenvorrat)-1] do begin
+ name:=sumNam;
+ for gut:=false to true do begin
+ inhalt[gut]:=tStringlist.create;
+ inhalt[gut].text:=result[gut].text;
+ end;
+ end;
+end;
+
+function dateienMitGueltigerSumme(sumNam: string): tStringList;
+var
+ sums: tStringlistBArray;
+begin
+ sums:=testeSummen(sumNam);
+ result:=sums[true];
+ sums[false].free;
+end;
+
+var
+ i: longint;
+
+initialization
+ setlength(Summenvorrat,0);
+
+finalization
+ for i:=0 to length(Summenvorrat)-1 do
+ with Summenvorrat[i] do begin
+ name:='';
+ inhalt[false].free;
+ inhalt[true].free;
+ end;
+ setlength(Summenvorrat,0);
+end.
+