//***************************************************************************** //****************** TFC.CC: Text Format Conversion Utility ******************* //***************************************************************************** //************************** 1991 by M.Hofmann **************************** //***************************************************************************** //*** 18.01.1994 21:34:18 //*** How To Compile: //*** Use C++ Compiler! //*** IBM-DOS: Compile with TINY-model //*** Borland-C: bcc -mt -O -G -lt -Z -d -w tfc.cc //*** UNIX: GNU-C++: g++ -O2 -m486 -o /usr/bin/tfc tfc.cc //*** VMS: DEC-CXX: cxx /DEFINE=VMS /OPTIMIZE tfc.cc #define TFC #ifdef __TURBOC__ #ifndef __TINY__ #error compile only with tiny model !! #endif #else #ifdef VMS #define unlink(a) remove(a) #else #include #endif #endif // Include standard header files #include #include #include #include //***************************************************************************** //******** Messages and error messages **************************************** //***************************************************************************** char license_msg[] = { "This program is free software; you can redistribute it and/or modify\n" "it under the terms of the GNU General Public License as published by\n" "the Free Software Foundation; either version 2 of the License, or\n" "(at your option) any later version.\n\n" "This program is distributed in the hope that it will be useful,\n" "but WITHOUT ANY WARRANTY; without even the implied warranty of\n" "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n" "GNU General Public License for more details.\n\n" "You should have received a copy of the GNU General Public License\n" "along with this program; if not, write to the Free Software\n" "Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\n\n"}; char help_msg[] = { "\n TFC converts text files between various file formats \n\n" " Syntax: TFC [-ADELPUVX?] [-T [n]] [-N [n]] input_file [output_file]\n\n" " -u : DOS -> Unix: Replace all CR/LF with LF, delete Ctrl-Z\n" " -d : Unix -> Dos: Replace all LF with CR/LF\n" " -a : DOS -> ASCII: Change DOS-Format to 7 Bit-ASCII-Format\n" " -n [n]: Number lines: Number output lines. n: start line number\n" " -t [n]: Expand tabs: Convert tabs to spaces. n: tab spacing (default 8)\n" " -v : Text -> LaTeX: Generate a LaTeX verbatim list\n" " -x : DOS -> LaTeX: Convert DOS special characters to LaTeX format\n" " -p : par mode Check parentheses\n\n" " -l : license Show software license\n" " -q : quiet: No output on screen during operation\n\n" " This is free software, and you are welcome to redistribute it\n" " under certain conditions; type `tfc -l' for details.\n" " If ouput_file is omitted, output is sent to input_file. This overwrites\n" " input_file, so be careful! Return Code: 0 on success\n"}; #define MsgTitle1 "\nTFC: Text Format Conversion Utility\n" #define MsgTitle2 "Version 1.3 Copyright " __DATE__ " by M.Hofmann\n" #define MsgOk "\nProgram completed with no errors\n\n" #define MsgOpenF "\n\nOpening files:\n" #define MsgIFile "\n Input file ======> (buffer length: %4XH) %s" #define MsgOFile "\n Output file ====> (buffer length: %4XH) %s" #define MsgRen "\n Output file will be renamed to %s after completion" #define MsgConv "\n\n\nConverting data:\n\n" #define MsgLComp "\r %i lines completed" #define MsgOpenPar "WARNING: Unequal number of parentheses found (%i more '%c' than '%c')...\x07\n" #define MsgOddQuot "WARNING: Odd number of \x22 detected...\x07\n" #define ErrNoArg "Wrong number of arguments" #define ErrNoOpt "Unknown Option specified" #define ErrNoInFile "Can't open input file" #define ErrNoInName "No input file name specified" #define ErrNoOutFile "Can't open output file" #define ErrClFile "Can't close files" #define ErrReadF "Error reading file" #define ErrWrtF "Error writing file" #define ErrNoRename "Can't rename file" //***************************************************************************** //******** Some useful definitions ******************************************** //***************************************************************************** #define true (-1) #define false (0) typedef unsigned char byte; // 8 bits typedef unsigned int word; // 16 bits //***************************************************************************** //******* Variables *********************************************************** //***************************************************************************** // Input / Output files char iname[100],oname[100]; FILE *ifile, *ofile; int renflag = false; // Line / column counting int lstart = 1; int lcount = 0; // actual line of output text int pos = 0; // actual column of output text // Flags for operation modes int unixmode = false; // Flags for conversion modes int dosmode = false; int texlistmode = false; int nummode = false; int ascmode = false; int texmode = false; int qmode = false; int parmode = false; int tabmode = false; int tabdist = 8; // Conversion tables char dos2unix[256][10]; char dos2tex[256][10]; char cr_str[10]; // String with proper CR/ CR/LF sequence // Other global variables int parenum = 0, pargnum = 0, parrnum = 0; // number of open braces int quotenum = 0; // number of double quotes (") //***************************************************************************** //******* Input / Output functions ******************************************** //***************************************************************************** void ExitErr(char *errmsg,int ErrNum) /*** Show an error message and quit program ***/ { fflush (stdout); fprintf (stderr, "\n\nError: %s !!!\n\n", errmsg); fprintf (stderr, "Aborting program (ERC>0)....\n\n"); fprintf (stderr, "Syntax: TFC [-ADELPUVX?] [-T [n]] [-N [n]] input_file [output_file]\n"); fprintf (stderr, " TFC -? for help\n\n"); exit(ErrNum); } void title() /*** Print title ***/ { if (!qmode) { printf (MsgTitle1); // Print title printf (MsgTitle2); } } void help() /*** Print Help page and exit ***/ { printf(help_msg); exit(0); } void license() /*** Print license and exit ***/ { printf("\n\nLICENSE:\n\n%s", license_msg); exit(0); } //***************************************************************************** //****** File I/O ************************************************************* //***************************************************************************** void fileo(char *iname, char *oname) /*** Open files iname and oname for reading and writing. If oname=="", ***/ /*** write to file temp and rename temp to iname when closing files ***/ { renflag = (oname[0]==0); if (renflag) strcpy(oname, "temp"); if (!qmode) { printf (MsgOpenF); printf (MsgIFile MsgOFile,20000,iname,20000,oname); if (renflag) printf (MsgRen, iname); } else { printf ("TFC: %s \t %s", iname, oname); if (renflag) printf (" --> %s", iname); printf ("\n"); } if ((ifile=fopen(iname,"rb"))==NULL) ExitErr(ErrReadF,1); if ((ofile=fopen(oname,"wb"))==NULL) ExitErr(ErrWrtF,1); setvbuf(ifile,NULL,_IOFBF,20000); // Faster with buffers setvbuf(ofile,NULL,_IOFBF,20000); } void filec() /*** Close files and replace input file if inputfile=outputfile ***/ { if (fclose(ofile)) ExitErr(ErrClFile,1); if (fclose(ifile)) ExitErr(ErrClFile,1); if (renflag) { if (0!=unlink(iname)) ExitErr(ErrNoRename,1); if (0!=rename(oname,iname)) ExitErr(ErrNoRename,1); } } void fp(byte c) /*** Write byte c to outputfile. Handle CR / LF ***/ { switch (c) { case '\n' : if (EOF==fputs(cr_str,ofile)) ExitErr(ErrWrtF,1); pos = 0; lcount++; break; case 13 : break; default : if (EOF==fputc(c,ofile)) ExitErr(ErrWrtF,1); pos++; break; } } void fps(char *s) /*** Write string s to outputfile ***/ { while(*s) fp(*s++); } //***************************************************************************** //****** System Initialization ************************************************ //***************************************************************************** void setuptables() /*** Setup translation tables ***/ { int i; for (i=0; i<127; i++) { sprintf (dos2unix[i], "%c",i); sprintf (dos2unix[i+128],"_"); sprintf (dos2tex[i], "%c",i); sprintf (dos2tex[i+128], "_"); } strcpy (dos2unix[148], "oe"); strcpy (dos2unix[132], "ae"); strcpy (dos2unix[129], "ue"); strcpy (dos2unix[153], "Oe"); strcpy (dos2unix[142], "Ae"); strcpy (dos2unix[154], "Ue"); strcpy (dos2unix[225], "ss"); strcpy (dos2tex[ 21], "\\s{}"); strcpy (dos2tex[135], "\\c{c}"); strcpy (dos2tex[160], "\\'a"); strcpy (dos2tex[133], "\\`a"); strcpy (dos2tex[131], "\\^a"); strcpy (dos2tex[130], "\\'e"); strcpy (dos2tex[136], "\\^e"); strcpy (dos2tex[137], "\x22""e"); strcpy (dos2tex[138], "\\`e"); strcpy (dos2tex[147], "\\^o"); strcpy (dos2tex[163], "\\'u"); strcpy (dos2tex[151], "\\`u"); strcpy (dos2tex[150], "\\^u"); strcpy (dos2tex[139], "\x22""i"); strcpy (dos2tex[140], "\\^i"); strcpy (dos2tex[148], "\x22""o"); strcpy (dos2tex[132], "\x22""a"); strcpy (dos2tex[129], "\x22""u"); strcpy (dos2tex[153], "\x22""O"); strcpy (dos2tex[142], "\x22""A"); strcpy (dos2tex[154], "\x22""U"); strcpy (dos2tex[164], "\\~n"); strcpy (dos2tex[165], "\\~N"); strcpy (dos2tex[168], "?`"); strcpy (dos2tex[173], "!`"); strcpy (dos2tex[225], "\x22""s"); strcpy (dos2tex[224], "$\\alpha$"); strcpy (dos2tex[248], "$^0$"); // Determine proper LF sequence (DOS needs CR/LF) #ifdef __MSDOS__ // strcpy (cr_str,"\x0D\x0A"); #else strcpy (cr_str,"\x0A"); #endif if (dosmode) strcpy (cr_str,"\x0D\x0A"); if (unixmode) strcpy (cr_str,"\x0A"); } //***************************************************************************** //******* Translate Input File ************************************************ //***************************************************************************** void convchar(int c) /*** Translates the character c and writes it to the output file ***/ { // Check for ASCII Control codes (c<20h) if (unixmode && c==26) return; if (tabmode && c==9) { do { fp (' '); } while (pos % tabdist); return; } // Check brace level if (parmode) { switch(c) { case 34 : quotenum++;break; /* " */ case 40 : parrnum++;break; /* ( */ case 41 : parrnum--;break; /* ) */ case 91 : parenum++;break; /* [ */ case 93 : parenum--;break; /* ] */ case 123 : pargnum++;break; /* { */ case 125 : pargnum--;break; /* } */ } /* while */ } // ASCII-Translation ? if (ascmode) { fps (dos2unix[c]); return; } // TeX-Translation ? if (texmode) { fps (dos2tex[c]); return; } // No Translation ! fp(c); } void convtext() { int register c = 0; char s[10]; if (!qmode) printf (MsgConv); // print message if (texlistmode) { // if Latex List mode: print start commands fps ("%***\n"); fps ("%*** File: "); fps (iname); fps ("\n%*** Formatted for: LaTeX by TFC V1.3 ("__DATE__")\n%***\n"); fps ("{\\scriptsize\n\\begin{verbatim}\n"); lstart-=lcount; } while (EOF!=(c=fgetc(ifile))) { if (c==26) break; // Start of a new line ? if (pos==0) { if (!((lcount-1) % 64) && !qmode) // Print line number printf(MsgLComp,lcount); if (nummode) { // Number lines in output file sprintf(s,"%5i: ",lcount+lstart); fps(s); } } // Translate and output character convchar (c); } /* while */ // Ok, the whole file was translated. Print messages to user if (!qmode) { printf(MsgLComp,lcount); printf ("\n\n"); } if (ferror(ifile)) ExitErr(ErrReadF,1); if (texlistmode) // End of LaTeX environment fps ("\\end{verbatim}\n}"); if (parmode) { if (quotenum % 2) printf (MsgOddQuot); // Even Number of quotes? if (pargnum>0) printf (MsgOpenPar, pargnum,'{','}'); // All Braces closed? if (pargnum<0) printf (MsgOpenPar,-pargnum,'}','{'); if (parenum>0) printf (MsgOpenPar, parenum,'[',']'); if (parenum<0) printf (MsgOpenPar,-parenum,']','['); if (parrnum>0) printf (MsgOpenPar, parrnum,'(',')'); if (parrnum<0) printf (MsgOpenPar,-parrnum,')','('); } } //***************************************************************************** //****** Main program ********************************************************* //***************************************************************************** int main (int argc, char *argv[]) { int i, j; char c; iname[0] = oname[0] = '\0'; // No filenames so far // Scan input line for (i=1; i 0 && 0 != (c=toupper(argv[i][j])); j++) { switch(c) { case ('U') : unixmode = true; break; case ('D') : dosmode = true; break; case ('A') : ascmode = true; break; case ('P') : parmode = true; break; case ('Q') : qmode = true; break; case ('V') : texlistmode = true; break; case ('X') : texmode = true; break; case ('H') : case ('?') : title();help(); break; case ('L') : title();license(); break; case ('N') : nummode = true; if (1 == sscanf (argv[i+1], "%d", &lstart)) { i++; j = -1; } break; case ('T') : tabmode = true; if (1 == sscanf (argv[i+1], "%d", &tabdist)) { i++; j = -1; } break; default : title(); ExitErr(ErrNoOpt,1); } /* switch */ } } else { // Seems to be a file name if (iname[0]==0) { strcpy(iname,argv[i]); } else { if (oname[0]!=0) ExitErr(ErrNoArg,1); strcpy(oname,argv[i]); } } /* if */ } /* for */ // Print Title title(); // Print title message // Check parameters and options if (!iname[0]) ExitErr(ErrNoInName,1); // Initialize system setuptables(); // Convert text file fileo(iname,oname); // Open files convtext(); // Convert input file filec(); // Close file // No error occurred: Prepare for exit if (!qmode) printf (MsgOk); exit(0); }