Source file: /~heha/hsn/nice_rc.zip/src/spc2tab.cpp

#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
Wrong umlauts? - Assume file is ANSI (CP1252) encoded