1: /* webcpp - driver.cpp
     2:  * Copyright (C)2001-2003 Jeffrey Bakker
     3: 
     4:  * This program is free software; you can redistribute it and/or modify
     5:  * it under the terms of the GNU General Public License as published by
     6:  * the Free Software Foundation; either version 2 of the License, or
     7:  * (at your option) any later version.
     8: 
     9:  * This program is distributed in the hope that it will be useful,
    10:  * but WITHOUT ANY WARRANTY; without even the implied warranty of
    11:  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    12:  * GNU General Public License for more details.
    13: 
    14:  * You should have received a copy of the GNU General Public License
    15:  * along with this program; if not, write to the Free Software
    16:  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
    17:    ___________________________________ .. .
    18:  */
    19: 
    20: 
    21: #include "deflangs.h" 
    22: #include "driver.h" 
    23: 
    24: #include <ctime> 
    25: #include <iomanip> 
    26: using namespace std;
    27: 
    28: Driver::Driver() {lang = NULL;}
    29: Driver::~Driver(){clean();}
    30: 
    31: // toggle/set an option --------------------------------------------------------
    32: bool Driver::switch_parser(string arg) {
    33: 
    34: 	if (arg.substr(0,3) == "-x=") {
    35: 		cerr << checkExt("." + arg.substr(3)) << " type forced.\n";
    36: 		prep_files(iFile,oFile,0x66);
    37: 	} else if (arg.substr(0,3) == "-c=") {
    38: 		lang->Scs2.setFile(arg.substr(3));
    39: 	} else if (arg.substr(0,3) == "-C=") {
    40: 		lang->toggleExtcss();
    41: 		lang->Scs2.setFile(arg.substr(3));
    42: 	} else if (arg.substr(0,3) == "-i=") {
    43: 		lang->Scs2.setPicture(arg.substr(3));
    44: 	} else if (arg.substr(0,3) == "-t=") {
    45: 		lang->toggleBigtab();
    46: 		lang->setTabWidth(arg.substr(3));
    47: 	} else if (arg.substr(0,3) == "-w=") {
    48: 		lang->toggleNumber();
    49: 		lang->toggleAnchor();
    50: 		lang->toggleHypinc();
    51: 		lang->toggleWebcpp();
    52: 		lang->Scs2.setFile(arg.substr(3));
    53: 	} else if (arg.substr(0,3) == "-W=") {
    54: 		lang->toggleNumber();
    55: 		lang->toggleAnchor();
    56: 		lang->toggleHypinc();
    57: 		lang->toggleWebcpp();
    58: 		lang->toggleExtcss();
    59: 		lang->Scs2.setFile(arg.substr(3));
    60: 	} else if (arg == "--external-css" || arg == "-X") {
    61: 		lang->toggleExtcss();
    62: 	} else if (arg == "--superinclude" || arg == "-H") {
    63: 		lang->toggleHypinc();
    64: 		lang->toggleFollow();
    65: 	} else if (arg == "--hyperinclude" || arg == "-h") {
    66: 		lang->toggleHypinc();
    67: 	} else if (arg == "--anchor-lines" || arg == "-a") {
    68: 		lang->toggleAnchor();
    69: 	} else if (arg == "--line-numbers" || arg == "-l") {
    70: 		lang->toggleNumber();
    71: 	} else if (arg == "--tabs-spaces"  || arg == "-t") {
    72: 		lang->toggleBigtab();
    73: 	} else if (arg == "--made-with"    || arg == "-m") {
    74: 		lang->toggleWebcpp();
    75: 	} else if (arg == "--the-works"    || arg == "-w") {
    76: 		lang->toggleNumber();
    77: 		lang->toggleAnchor();
    78: 		lang->toggleHypinc();
    79: 		lang->toggleWebcpp();
    80: 	} else {
    81: 		help(HELP_DEFAULT);
    82: 		return false;
    83: 	}
    84: 
    85: 	return true;
    86: }
    87: // print help ----------------------------------------------------------------
    88: void Driver::help(char mode) {
    89: 
    90: 	string Usage;
    91: 
    92: 	Usage = "\
    93: Usage: $ webcpp <infile> <outfile> [options...]\n\
    94: \n\
    95: Options:\n\
    96:   -c=<scheme>        Use a webcpp colour scheme.\n\
    97:   -w=<scheme>        The works, same as -m -l -a -h -c=<scheme>.\n\
    98:   -i=<filename>      Use an image for the background.\n\
    99:   -t=<width>         Convert tabs to spaces using the specified width.\n\
   100:   -x=<extension>     Force the filetype for syntax highlighting.\n\
   101: \n\
   102:   -X,--external-css  Generate an external stylesheet.\n\
   103:   -l,--line-numbers  Print the line numbers in the left margin.\n\
   104:   -a,--anchor-lines  Create anchors to line numbers.\n\
   105:   -h,--hyperinclude  Create hyperlinks to #include statements.\n\
   106:   -H,--superinclude  Hyperinclude that recursively generates files.\n\
   107:   -t,--tabs-spaces   Convert tabs to spaces, default width is 8.\n\
   108:   -m,--made-with     Show made with webcpp footer.\n\
   109:   -A,--auto          Automatic naming in place of the output file.\n\
   110:   - ,--pipe          Use STDIN or STDOUT in place of the filename.\n\
   111: \n\
   112:  Type `webcpp --languages` to see supported languages and filetypes.\n";
   113: 
   114: 
   115: 	string Langs = "\
   116: Ada95\t\t*.adb,*.ads,*.ali\n\
   117: Assembly\t*.asm,*.s\n\
   118: Asp\t\t*.asp,*.asa\n\
   119: Basic\t\t*.bas\n\
   120: C#\t\t*.cs\n\
   121: C Source\t*.c,*.rc\n\
   122: C++ Source\t*.cc,*.cpp,*.cxx\n\
   123: C/C++ Header\t*.h,*.hh,*.hpp,*.hxx\n\
   124: Objective-C\t*.m\n\
   125: DOS Batch\t*.bat,*.cmd\n\
   126: EMF\t\t*.emf\n\
   127: Euphoria\t*.e,*.eu,*.ex\n\
   128: Fortran\t\t*.f,*.f77,*.f90,*.for,*.ftn\n\
   129: Haskell\t\t*.hs,*.lhs\n\
   130: Java\t\t*.java\n\
   131: JavaScript\t*.js\n\
   132: Markup\t\t*.htm,*.html,*.shtml,*.sgml,*.xml\n\
   133: Modula2\t\t*.def,*.mod\n\
   134: Nasa CLIPS\t*.clp\n\
   135: NVidia Cg\t*.cg\n\
   136: Pascal\t\t*.pas\n\
   137: Perl\t\t*.cgi,*.pl,*.plx,*.plex,*.pm\n\
   138: PHP\t\t*.inc,*.php,*.php3,*.php4\n\
   139: Power Builder\t*.pbl,*.pbr\n\
   140: Python\t\t*.py,*.pyw\n\
   141: RenderMan\t*.rib,*.sl\n\
   142: Ruby\t\t*.rb\n\
   143: SQL\t\t*.sql\n\
   144: Tcl\t\t*.tcl,*.tk\n\
   145: Unix shell\t*.sh\n\
   146: UnrealScript\t*.uc\n\
   147: VHDL\t\t*.v,*.vhd,*.vhdl\n\
   148: Don't see your favorite language listed here?\n\
   149: Try http://webcpp.sourceforge.net/languages.php\n";
   150: 
   151: 	cerr	<< "Web C Plus Plus v0.8.0  "
   152: 		<< "Copyright (C)2001-2003 Jeffrey Bakker\n"
   153: 		<< "Released February 6th 2003, "
   154: 		<< "Compiled " << __DATE__ << " at " << __TIME__ << "\n\n"
   155: 		<< ((mode == HELP_LANGUAGES)?Langs:Usage);
   156: 
   157: }
   158: // determines the filetype for syntax highlighting ----------------------------
   159: char Driver::getExt(string filename)
   160: {
   161: 	int dot;
   162: 	char ext;
   163: 
   164: 	string extension = "";
   165: 	dot = filename.rfind(".");
   166: 
   167: 	if(dot != -1) {
   168: 		extension = filename.substr(dot+1, filename.size() - dot);
   169: 	}
   170: 	for(int i=0; i < extension.size(); i++) {
   171: 		extension[i]=tolower(extension[i]);
   172: 	}
   173: 
   174: 	if     (extension ==  "adb") {ext =     ADA_FILE;}
   175: 	else if(extension ==  "ads") {ext =     ADA_FILE;}
   176: 	else if(extension ==  "ali") {ext =     ADA_FILE;}
   177: 	else if(extension ==  "asm") {ext =     ASM_FILE;}
   178: 	else if(extension ==  "asp") {ext =     ASP_FILE;}
   179: 	else if(extension ==  "asa") {ext =     ASP_FILE;}
   180: 	else if(extension ==    "s") {ext =     ASM_FILE;}
   181: 	else if(extension ==  "bas") {ext =   BASIC_FILE;}
   182: 	else if(extension ==  "bat") {ext =   BATCH_FILE;}
   183: 	else if(extension ==  "cmd") {ext =   BATCH_FILE;}
   184: 	else if(extension ==    "c") {ext =       C_FILE;}
   185: 	else if(extension ==   "rc") {ext =       C_FILE;}
   186: 	else if(extension ==   "cc") {ext =     CPP_FILE;}
   187: 	else if(extension ==  "cpp") {ext =     CPP_FILE;}
   188: 	else if(extension ==  "coo") {ext =     CPP_FILE;}
   189: 	else if(extension ==  "c++") {ext =     CPP_FILE;}
   190: 	else if(extension ==  "cxx") {ext =     CPP_FILE;}
   191: 	else if(extension ==    "h") {ext =     CPP_FILE;}
   192: 	else if(extension ==   "hh") {ext =     CPP_FILE;}
   193: 	else if(extension ==  "hpp") {ext =     CPP_FILE;}
   194: 	else if(extension ==  "hxx") {ext =     CPP_FILE;}
   195: 	else if(extension ==   "cg") {ext =      CG_FILE;}
   196: 	else if(extension ==  "clp") {ext =   CLIPS_FILE;}
   197: 	else if(extension ==   "cs") {ext =  CSHARP_FILE;}
   198: 	else if(extension ==    "m") {ext =    OBJC_FILE;}
   199: 	else if(extension ==  "emf") {ext =     EMF_FILE;}
   200: 	else if(extension ==    "e") {ext =    U4EA_FILE;}
   201: 	else if(extension ==   "eu") {ext =    U4EA_FILE;}
   202: 	else if(extension ==   "ex") {ext =    U4EA_FILE;}
   203: 	else if(extension ==    "f") {ext = FORTRAN_FILE;}
   204: 	else if(extension ==  "for") {ext = FORTRAN_FILE;}
   205: 	else if(extension ==  "ftn") {ext = FORTRAN_FILE;}
   206: 	else if(extension ==  "f77") {ext = FORTRAN_FILE;}
   207: 	else if(extension ==  "f90") {ext = FORTRAN_FILE;}
   208: 	else if(extension ==   "hs") {ext = HASKELL_FILE;}
   209: 	else if(extension ==  "lhs") {ext = HASKELL_FILE;}
   210: 	else if(extension == "shtm") {ext =    HTML_FILE;}
   211: 	else if(extension == "html") {ext =    HTML_FILE;}
   212: 	else if(extension ==  "htm") {ext =    HTML_FILE;}
   213: 	else if(extension ==  "xml") {ext =    HTML_FILE;}
   214: 	else if(extension == "sgml") {ext =    HTML_FILE;}
   215: 	else if(extension == "java") {ext =    JAVA_FILE;}
   216: 	else if(extension ==   "js") {ext = JSCRIPT_FILE;}
   217: 	else if(extension ==  "def") {ext =  MODULA_FILE;}
   218: 	else if(extension ==  "mod") {ext =  MODULA_FILE;}
   219: 	else if(extension ==  "pas") {ext =  PASCAL_FILE;}
   220: 	else if(extension ==  "cgi") {ext =    PERL_FILE;}
   221: 	else if(extension == "plex") {ext =    PERL_FILE;}
   222: 	else if(extension ==  "plx") {ext =    PERL_FILE;}
   223: 	else if(extension ==   "pl") {ext =    PERL_FILE;}
   224: 	else if(extension ==   "pm") {ext =    PERL_FILE;}
   225: 	else if(extension ==  "inc") {ext =     PHP_FILE;}
   226: 	else if(extension == "php4") {ext =     PHP_FILE;}
   227: 	else if(extension == "php3") {ext =     PHP_FILE;}
   228: 	else if(extension ==  "php") {ext =     PHP_FILE;}
   229: 	else if(extension ==  "pbl") {ext =     PB6_FILE;}
   230: 	else if(extension ==  "pbr") {ext =     PB6_FILE;}
   231: 	else if(extension ==  "pyw") {ext =  PYTHON_FILE;}
   232: 	else if(extension ==   "py") {ext =  PYTHON_FILE;}
   233: 	else if(extension ==   "sl") {ext =  RENDER_FILE;}
   234: 	else if(extension ==  "rib") {ext =  RENDER_FILE;}
   235: 	else if(extension ==   "rb") {ext =    RUBY_FILE;}
   236: 	else if(extension ==  "sql") {ext =     SQL_FILE;}
   237: 	else if(extension ==   "sh") {ext =   SHELL_FILE;}
   238: 	else if(extension ==  "tcl") {ext =     TCL_FILE;}
   239: 	else if(extension ==   "tk") {ext =     TCL_FILE;}
   240: 	else if(extension ==   "uc") {ext = USCRIPT_FILE;}
   241: 	else if(extension ==    "v") {ext =    VHDL_FILE;}
   242: 	else if(extension == "vhdl") {ext =    VHDL_FILE;}
   243: 	else if(extension ==  "vhd") {ext =    VHDL_FILE;}
   244: 
   245: 	else ext = TEXT_FILE;
   246: 	return ext;
   247: }
   248: // determines the language for syntax highlighting ----------------------------
   249: string Driver::checkExt(string filename) {
   250: 
   251:  clean();
   252: 
   253:  char filetype = getExt(filename);
   254: 
   255:  switch(filetype) {
   256:   case (ADA_FILE)     : lang = new LangAda95;      return "Ada file";
   257:   case (ASM_FILE)     : lang = new LangAssembler;  return "Assembly file";
   258:   case (ASP_FILE)     : lang = new LangAsp;        return "ASP file";
   259:   case (BASIC_FILE)   : lang = new LangBasic;      return "Basic file";
   260:   case (BATCH_FILE)   : lang = new LangBatch;      return "DOS Batch file";
   261:   case (C_FILE)       : lang = new LangC;          return "'C' file";
   262:   case (CPP_FILE)     : lang = new LangCPlusPlus;  return "C++ file";
   263:   case (CG_FILE)      : lang = new LangCg;         return "NVIDIA Cg file";
   264:   case (CLIPS_FILE)   : lang = new LangClips;      return "NASA CLIPS file";
   265:   case (CSHARP_FILE)  : lang = new LangCSharp;     return "C-Sharp file";
   266:   case (OBJC_FILE)    : lang = new LangObjectiveC; return "Objective-C file";
   267:   case (EMF_FILE)     : lang = new LangEmf;        return "MicroEmacs macro file";
   268:   case (U4EA_FILE)    : lang = new LangEuphoria;   return "Euphoria file";
   269:   case (FORTRAN_FILE) : lang = new LangFortran;    return "Fortran file";
   270:   case (HASKELL_FILE) : lang = new LangHaskell;    return "Haskell file";
   271:   case (HTML_FILE)    : lang = new LangHtml;       return "Markup file";
   272:   case (JAVA_FILE)    : lang = new LangJava;       return "Java file";
   273:   case (JSCRIPT_FILE) : lang = new LangJScript;    return "Java script";
   274:   case (MODULA_FILE)  : lang = new LangModula2;    return "Modula file";
   275:   case (PASCAL_FILE)  : lang = new LangPascal;     return "Pascal file";
   276:   case (PERL_FILE)    : lang = new LangPerl;       return "Perl script";
   277:   case (PHP_FILE)     : lang = new LangPhp;        return "PHP script";
   278:   case (PB6_FILE)     : lang = new LangPBuilder;   return "Power Builder file";
   279:   case (PYTHON_FILE)  : lang = new LangPython;     return "Python script";
   280:   case (RUBY_FILE)    : lang = new LangRuby;       return "Ruby script";
   281:   case (RENDER_FILE)  : lang = new LangRenderMan;  return "RenderMan file";
   282:   case (SQL_FILE)     : lang = new LangSQL;        return "SQL script";
   283:   case (SHELL_FILE)   : lang = new LangShell;      return "UNIX shell script";
   284:   case (TCL_FILE)     : lang = new LangTcl;        return "Tcl script";
   285:   case (USCRIPT_FILE) : lang = new LangUScript;    return "UnrealScript";
   286:   case (VHDL_FILE)    : lang = new LangVHDL;       return "VHDL file";
   287:   default             : lang = new LangText;       return "Text file";
   288:  }
   289: }
   290: //-----------------------------------------------------------------------------
   291: // prepare input and output files ---------------------------------------------
   292: bool Driver::prep_files(string ifile, string ofile, char over) {
   293: 
   294: 	if(ofile == "--auto" || ofile == "-A") {ofile = ifile + ".html";}
   295: 
   296: 	iFile = ifile;
   297: 	oFile = ofile;
   298: 
   299: 	if(ifile == "-" || ifile == "--pipe") {lang->IO.toggleImode();}
   300: 	else if(!lang->IO.openR(ifile))    {return false;}
   301: 
   302: 	if(ofile == "-" || ofile == "--pipe") {lang->IO.toggleOmode();}
   303: 	else if(!lang->IO.open(ofile,over)) {return false;}
   304: 	//over?FORCE_OVERWRITE:MODE_WRITE)
   305: 	return true;
   306: }
   307: // returns the filename without the full path ---------------------------------
   308: string Driver::getTitle() {
   309: 
   310: 	int slash = iFile.rfind(DIRECTORY_SLASH);
   311: 	if(slash == -1) {
   312: 		return iFile;
   313: 	}
   314: 	return iFile.substr(slash+1);
   315: }
   316: // run the webcpp engine ------------------------------------------------------
   317: void Driver::drive() {
   318: 
   319: 	clock_t time_beg,time_end,time_dif;
   320: 	time_beg = clock();
   321: 
   322: 	// get the filesize
   323: 	ifstream Count;
   324: 	string tmp;
   325: 	int percent = 0;
   326: 
   327: 	Count.open(iFile.data());
   328: 	while (Count) {
   329: 		getline(Count,tmp);
   330: 		percent++;
   331: 	}
   332: 	percent--;
   333: 	Count.close();
   334: 	// to compare against progress
   335: 
   336: 	lang->begHtml(getTitle());
   337: 	lang->doParsing();
   338: 	while(lang->IO.ifile && cin) {
   339: 		lang->doParsing();
   340: 
   341: 		if( ((lang->getLineCount()*100)/percent) < 101 ) {
   342: 
   343: 			cerr << '\r';
   344: 
   345: 			if(!lang->IO.isIredir()) {
   346: 
   347: 				cerr	<< ((lang->getLineCount() * 100) / percent)
   348: 					<< "% Complete ";
   349: 			}
   350: 			cerr << "@ line " << lang->getLineCount()-1;
   351: 		}
   352: 	}
   353: 	lang->endHtml();
   354: 
   355: 	time_end = clock();
   356: 	time_dif = time_end - time_beg;
   357: 
   358: 	cerr << " took " << setprecision(3)
   359: 			 << (double) time_dif / CYCLE_SPEED << " seconds.\n";
   360: 
   361: 	lang->IO.close();
   362: }
   363: //-----------------------------------------------------------------------------
   364: void Driver::makeIndex(string prefix) {
   365: 
   366: 	CFfile Index;
   367: 	if(!Index.openR("webcppbatch.txt")){return;}
   368: 	if(!Index.openW(prefix + "files.html",true)){return;}
   369: 
   370: 	string file;
   371: 	Theme theme;
   372: 
   373: 	Index	<< "<html>\n<head>\n<title>source index</title>\n"
   374: 		<< "<style type=\"text/css\">\n\n"
   375: 		<< theme.getCSSdata() << "</style>\n"
   376: 		<< "</head>\n<body>\n\n";
   377: 
   378: 	getline(Index.ifile,file);
   379: 	while(Index.ifile) {
   380: 
   381: 		file = "<a href=\"" + file + ".html\">" + file + "</a>";
   382: 
   383: 		Index << file << "<br>\n";
   384: 		getline(Index.ifile,file);
   385: 	}
   386: 
   387: 	Index << "\n</body>\n</html>";
   388: }
   389: //-----------------------------------------------------------------------------
   390: void Driver::clean() {
   391: 
   392: 	if( lang != NULL ) {
   393: 		delete lang;
   394: 		lang = NULL;
   395: 	}
   396: }
   397: //-----------------------------------------------------------------------------
   398: 



w e b c p p
web c plus plus