#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <shlwapi.h>
/* Dieses Programm wandelt Spaces zu Tabulatoren und umgekehrt.
* Nachlaufende Leerzeichen und Tabulatoren am Zeilenende werden entfernt.
* Variable Tab-Weite, UTF-8
+0208xx Behalte Datei-Zeit im Überschreibmodus
*/
int NoSubst=0;
char LiteralChar='"';
char CommentChar='/';
void Usage() {
printf(
"Spc2Tab [01/11] (haftmann#software ++FREEWARE++)\n"
"Substitute tabs for spaces (and vice versa) where appropriate\n\n"
"Usage:\n"
" spc2tab [switches] [file ...]\n"
" replace <file> with - or pipe to stdout - a new-tabbed file.\n"
" /Txx tabsize in+out, /TIxx tabsize in, /TOxx tabsize out (1=spaces only)\n"
" /Lc set literal string delimiter, /P pipe to stdout (don''t overwrite)\n"
" /Nxx no TAB subst for *single* spaces beyond column xx, defaults to 1\n"
" /Cc set comment char to prevent *single* space interpretation before that\n"
" Standards are both tab sizes =8, string delimiter=\"'\", comment char=\"{\"\n"
"Examples:\n"
" spc2tab -c; x.asm insert tabs into spaced (hard to edit) ASM file\n"
" spc2tab -ti4 *.c* *.h Make VC sources readable\n"
" spc2tab -to1 x.txt remove all tabs, assuming tabsize = 8\n"
" spc2tab -l' -c{ -p x.pas>y.pas don't overwrite source\n");
exit(0);
}
void error(const char *msg) {
printf("spc2tab: error: %s\n",msg);
exit(1);
}
int DivMul(int a, int b) {
return a-a%b; // auf durch 8 teilbare Spalten
}
struct TEXT{
FILE*f;
int col;
// char TabSize;
bool utf8;
bool literal;
char TabSize;
void open(const TCHAR*n, int m, const char*msg);
void close();
void put(char c); // nur Ausgabe
void set(int c); // nur Ausgabe: setzt Spalte durch Ausgabe von Tabs und Leerzeichen
bool get(char&c); // nur Eingabe
void Advance(char c); // beides
}itext,otext;
void TEXT::open(const TCHAR*n, int m, const char*msg){
switch (m) {
case 0: f=(FILE*)n; break;
case 1: f=_tfopen(n,TEXT("r")); break;
case 2: f=_tfopen(n,TEXT("w")); break;
}
if (!f) error(msg);
col=0; literal=0; utf8=false;
char bom[3];
if (m==1
&& fread(bom,3,1,f)==1
&& bom[0]==0xEF
&& bom[1]==0xBB
&& bom[2]==0xBF) utf8=true;
rewind(f);
}
void TEXT::close() {
fclose(f);
f=0;
}
void TEXT::Advance(char c) {
// col je nach Zeichen um 1 oder zum nächsten Tabulatorschritt vorrücken,
// die Spaltenzählung beginnt mit Spalte 0
if (c==LiteralChar) literal=!literal; // Texte werden nie getabt
switch (c) {
case 9: col=DivMul(col,TabSize)+TabSize; break;
case 10:
case 13: col=0; literal=false; break;
default: if (!utf8 || -64<=c) col++; // Nächste Spalte
}
}
void TEXT::put(char c) {
putc(c,f);
Advance(c);
}
void TEXT::set(int c) {
if (TabSize>1) while (col<DivMul(c,TabSize)) {
if (col==c-1 && col>=NoSubst) put(' ');
else put(9);
}
while (col<c) put(' ');
}
bool TEXT::get(char&c) {
int i=fgetc(f);
if (i<0) return false;
c=(char)i;
Advance(c);
return true;
}
void spc2tab() {
char c;
while (itext.get(c)) {
if (itext.literal || c!=' ' && c!=9) {
// Leerzeichen und eingehende Tabs zurückhalten, aber bei allen anderen
// Zeichen die Ausgabe von Tabs und Leerzeichen nachholen
otext.set(itext.col-1);
otext.put(c);
}
}
}
EXTERN_C void mainCRTStartup() {
bool overwrite=true;
TCHAR *arg,*end;
itext.TabSize=otext.TabSize=8;
arg=GetCommandLine();
arg=PathGetArgs(arg);
if (!*arg) Usage();
for (;*arg;arg=end) {
end=PathGetArgs(arg);
if (*end) end[-1]=0;
PathUnquoteSpaces(arg);
if (!*arg) break;
switch (arg[0]) {
case '/':
case '-': switch ((TCHAR)CharLower((LPTSTR)arg[1])) {
case 'h':
case '?': Usage();
case 'p': {
if (overwrite) {
// outfile=stdout;
// if ioresult<>0 then error("can't create temp file");
overwrite=false;
}else error("superfluous option P");
};
case 't': {
switch ((TCHAR)CharLower((LPTSTR)arg[2])) {
case 'i': itext.TabSize=_ttoi(arg+3); break;
case 'o': otext.TabSize=_ttoi(arg+3); break;
default: itext.TabSize=otext.TabSize=_ttoi(arg+2);
};
if (itext.TabSize<1 || otext.TabSize<1) error("invalid tabsize");
}break;
case 'n': {
NoSubst=_ttoi(arg+2)-1;
if (NoSubst<0) error("invalid margin");
}break;
case 'l': LiteralChar=(char)arg[2]; break;
case 'c': CommentChar=(char)arg[2]; break;
default: error("invalid switch");
}break;
default: {
TCHAR ifname[MAX_PATH],ofname[MAX_PATH];
lstrcpyn(ifname,arg,MAX_PATH);
LPTSTR n=PathFindFileName(ifname);
WIN32_FIND_DATA fd;
HANDLE fh=FindFirstFile(ifname,&fd);
if (fh) {
do{
lstrcpyn(n,fd.cFileName,ifname+MAX_PATH-n);
itext.open(ifname,1,"can't open input file");
if (overwrite) {
lstrcpyn(ofname,ifname,MAX_PATH);
lstrcpyn(ofname+(n-ifname),TEXT("SPC2TAB$.$$$"),ifname+MAX_PATH-n); // Gleicher Pfad
otext.open(ofname,2,"can't create temp file");
}
// Dateien geöffnet zur Verarbeitung
spc2tab();
itext.close();
otext.close();
if (overwrite) {
FILETIME t[3];
HANDLE h=CreateFile(ifname,0,0,0,OPEN_EXISTING,0,0);
if (h!=INVALID_HANDLE_VALUE) {
GetFileTime(h,t+0,t+1,t+2);
CloseHandle(h);
h=CreateFile(ofname,GENERIC_WRITE,0,0,OPEN_EXISTING,0,0);
if (h!=INVALID_HANDLE_VALUE) {
SetFileTime(h,t+0,t+1,t+2);
CloseHandle(h);
}
}
// Nun ggf. überschreiben
DeleteFile(ifname);
if (!MoveFile(ofname,ifname)) error("can't replace input file");
}
}while(FindNextFile(fh,&fd));
FindClose(fh);
}else error("no match");
}
}
}
}
Detected encoding: ANSI (CP1252) | 4
|
|