"Fossies" - the Fresh Open Source Software Archive

Member "highlight-3.57-x64/src/cli/main.cpp" (12 May 2020, 28366 Bytes) of package /windows/www/highlight-3.57-x64.zip:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. See also the last Fossies "Diffs" side-by-side code changes report for "main.cpp": 3.56_vs_3.57.

    1 /***************************************************************************
    2                           main.cpp  -  description
    3                              -------------------
    4     begin                : Die Apr 23 22:16:35 CEST 2002
    5     copyright            : (C) 2002-2018 by Andre Simon
    6     email                : a.simon@mailbox.org
    7 
    8    Highlight is a universal source code to HTML converter. Syntax highlighting
    9    is formatted by Cascading Style Sheets. It's possible to easily enhance
   10    highlight's parsing database.
   11 
   12  ***************************************************************************/
   13 
   14 
   15 /*
   16 This file is part of Highlight.
   17 
   18 Highlight is free software: you can redistribute it and/or modify
   19 it under the terms of the GNU General Public License as published by
   20 the Free Software Foundation, either version 3 of the License, or
   21 (at your option) any later version.
   22 
   23 Highlight is distributed in the hope that it will be useful,
   24 but WITHOUT ANY WARRANTY; without even the implied warranty of
   25 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
   26 GNU General Public License for more details.
   27 
   28 You should have received a copy of the GNU General Public License
   29 along with Highlight.  If not, see <http://www.gnu.org/licenses/>.
   30 */
   31 
   32 #include <memory>
   33 #include <algorithm>
   34 #include <Diluculum/LuaState.hpp>
   35 
   36 #include "main.h"
   37 #include "../include/datadir.h"
   38 #include "syntaxreader.h"
   39 
   40 #define MAX_LINE__WIDTH       80
   41 
   42 using namespace std;
   43 
   44 void HLCmdLineApp::printVersionInfo()
   45 {
   46     cout << "\n highlight version "
   47          << HIGHLIGHT_VERSION
   48          << "\n Copyright (C) 2002-2020 Andre Simon <a dot simon at mailbox.org>"
   49          << "\n\n Argparser class"
   50          << "\n Copyright (C) 2006-2008 Antonio Diaz Diaz <ant_diaz at teleline.es>"
   51          << "\n\n Artistic Style Classes (3.1)"
   52          << "\n Copyright (C) 2006-2018 by Jim Pattee <jimp03 at email.com>"
   53          << "\n Copyright (C) 1998-2002 by Tal Davidson"
   54          << "\n\n Diluculum Lua wrapper (1.0)"
   55          << "\n Copyright (C) 2005-2013 by Leandro Motta Barros"
   56          << "\n\n xterm 256 color matching functions"
   57          << "\n Copyright (C) 2006 Wolfgang Frisch <wf at frexx.de>"
   58 
   59          << "\n\n This software is released under the terms of the GNU General "
   60          << "Public License."
   61          << "\n For more information about these matters, see the file named "
   62          << "COPYING.\n\n";
   63 }
   64 
   65 void HLCmdLineApp::printBadInstallationInfo()
   66 {
   67     cerr << "highlight: Data directory not found ("<<DataDir::LSB_DATA_DIR<<")."
   68          " Bad installation or wrong "<< OPT_DATADIR << " parameter."
   69          << "\n\nCopy the highlight files into one of the directories listed "
   70          << "in INSTALL.\nYou may also set the data directory with "
   71          << OPT_DATADIR << ".\n";
   72 }
   73 
   74 int HLCmdLineApp::printInstalledFiles(const string& where, const string& wildcard, const string& kind, const string& option, const string& categoryFilterList)
   75 {
   76     vector <string> filePaths;
   77     string searchDir = where + wildcard;
   78 
   79     bool directoryOK = Platform::getDirectoryEntries ( filePaths, searchDir, true );
   80     if ( !directoryOK ) {
   81         cerr << "highlight: Could not access directory "
   82              <<  searchDir
   83              << ", aborted.\n";
   84         return EXIT_FAILURE;
   85     }
   86 
   87     sort ( filePaths.begin(), filePaths.end() );
   88     string suffix, desc;
   89     Diluculum::LuaValueMap categoryMap;
   90     cout << "\nInstalled " << kind << "s";
   91     
   92     if (categoryFilterList.size())
   93         cout << " matching \""<<categoryFilterList<<"\"";
   94     
   95     cout << " (located in " << where << "):\n\n";
   96     int matchedFileCnt=0;
   97     std::set<string> categoryNames;
   98     std::set<string> categoryFilters;
   99 
  100     istringstream valueStream;
  101     string catFilter;
  102     valueStream.str ( StringTools::change_case ( categoryFilterList,StringTools::CASE_LOWER ) );
  103     while ( getline ( valueStream, catFilter, ';' ) ) {
  104         categoryFilters.insert ( catFilter );
  105     }
  106             
  107     for ( unsigned int i=0; i< filePaths.size(); i++ ) {
  108         try {
  109             Diluculum::LuaState ls;
  110             highlight::SyntaxReader::initLuaState(ls, filePaths[i],"");
  111             ls.doFile(filePaths[i]);
  112             desc = ls["Description"].value().asString();
  113             
  114             suffix = ( filePaths[i] ).substr ( where.length() ) ;
  115             suffix = suffix.substr ( 1, suffix.length()- wildcard.length() );
  116 
  117             unsigned int filterOKCnt=categoryFilters.size();
  118             if (ls["Categories"].value() !=Diluculum::Nil){
  119                 filterOKCnt=0;
  120 
  121                 categoryMap = ls["Categories"].value().asTable();
  122                 
  123                 //TODO: negation
  124                 for(Diluculum::LuaValueMap::const_iterator it = categoryMap.begin(); it != categoryMap.end(); ++it)
  125                 {
  126                     categoryNames.insert(it->second.asString());
  127                     if (categoryFilters.size() && categoryFilters.count(it->second.asString())) {
  128                         ++filterOKCnt;
  129                     }
  130                 }     
  131             }
  132            
  133             if (filterOKCnt!=categoryFilters.size() && categoryFilters.size() ) continue;
  134             
  135             matchedFileCnt++;
  136             if (kind=="langDef") {
  137                 cout << setw ( 30 ) <<setiosflags ( ios::left ) <<desc<<": "<<suffix;
  138             
  139                 int extCnt=0;
  140                 for (StringMap::iterator it=dataDir.assocByExtension.begin(); it!=dataDir.assocByExtension.end(); it++) {
  141                     if (it->second==suffix ) {
  142                         cout << ((++extCnt==1)?" ( ":" ")<<it->first;
  143                     }
  144                 }
  145                 cout << ((extCnt)?" )":"");
  146             } else {
  147                 cout << setw ( 30 ) <<setiosflags ( ios::left ) <<suffix<<": "<<desc;
  148             
  149             }
  150             cout << endl;
  151         } catch (std::runtime_error &error) {
  152             cout << "Failed to read '" << filePaths[i] << "': " << error.what() << endl;
  153         }
  154     }
  155     
  156     if (!matchedFileCnt) {
  157         cout <<"No files found." << endl;
  158     } else {
  159         
  160         if (!categoryFilters.size()){
  161             cout << "\nFound "<<kind<<" categories:\n\n";
  162             for (std::set<string>::iterator it=categoryNames.begin(); it!=categoryNames.end(); ++it)
  163                 std::cout << *it<< ' ';
  164             cout << "\n";
  165         }
  166         
  167         cout <<"\nUse name of the desired "<<kind
  168             << " with --" << option << ". Filter categories with --list-cat." << endl;
  169             
  170         if (kind=="theme") {
  171             cout <<"\nAdd base16/ prefix to apply a Base16 theme." << endl;
  172         }
  173         
  174         printConfigInfo();
  175     }
  176     
  177     return EXIT_SUCCESS;
  178 }
  179 
  180 void HLCmdLineApp::printDebugInfo ( const highlight::SyntaxReader *lang,
  181                                     const string & langDefPath )
  182 {
  183     if (!lang) return;
  184     
  185     map <int, string> HLStateMap;
  186     
  187     cerr << "\nLoading language definition:\n" << langDefPath;
  188     cerr << "\n\nDescription: " << lang->getDescription();
  189     Diluculum::LuaState* luaState=lang->getLuaState();
  190     if (luaState) {
  191         cerr << "\n\nLUA GLOBALS:\n" ;
  192         Diluculum::LuaValueMap::iterator it;
  193         Diluculum::LuaValueMap glob =luaState->globals();
  194         string elemName;
  195         for(it = glob.begin(); it != glob.end(); it++) {
  196             Diluculum::LuaValue first = it->first;
  197             Diluculum::LuaValue second = it->second;
  198             elemName = first.asString();
  199             std::cerr << elemName<<": ";
  200             switch (second.type()) {
  201             case  LUA_TSTRING:
  202                 cerr << "string [ "<<second.asString()<<" ]";
  203                 break;
  204             case  LUA_TNUMBER:
  205                 cerr << "number [ "<<second.asNumber()<<" ]";
  206                 if (elemName.find("HL_")==0 && elemName.find("HL_FORMAT")==string::npos)
  207                     HLStateMap[second.asNumber()] = elemName;
  208                 break;
  209             case  LUA_TBOOLEAN:
  210                 cerr << "boolean [ "<<second.asBoolean()<<" ]";
  211                 break;
  212             default:
  213                 cerr << second.typeName();
  214             }
  215             cerr << endl;
  216         }
  217 
  218     }
  219     
  220     highlight::RegexElement *re=NULL;
  221     for ( unsigned int i=0; i<lang->getRegexElements().size(); i++ )
  222     {
  223         if (i==0)
  224              cerr << "\nREGEX:\n";
  225    
  226         re = lang->getRegexElements() [i];
  227         cerr << "State "<<re->open<< " ("<< HLStateMap[re->open]<<  "):\t"<<re->pattern <<"\n";
  228     }
  229     
  230     highlight::KeywordMap::iterator it;
  231     highlight::KeywordMap keys=lang->getKeywords();
  232     for ( it=keys.begin(); it!=keys.end(); it++ ) {
  233         if (it==keys.begin())
  234             cerr << "\nKEYWORDS:\n";
  235     
  236         cerr << " "<< it->first << "("<< it->second << ")";
  237     }
  238     cerr <<"\n\n";
  239 }
  240 
  241 void HLCmdLineApp::printConfigInfo ( )
  242 {
  243     cout << "\nConfig file search directories:\n";
  244     dataDir.printConfigPaths();
  245     cout << "\nFiletype config file:\n"<<dataDir.getFiletypesConfPath ( "filetypes" ) <<"\n";
  246     cout << endl;
  247 #ifdef HL_DATA_DIR
  248     cout << "Compiler directive HL_DATA_DIR = " <<HL_DATA_DIR<< "\n";
  249 #endif
  250 #ifdef HL_CONFIG_DIR
  251     cout << "Compiler directive HL_CONFIG_DIR = " <<HL_CONFIG_DIR<< "\n";
  252 #endif
  253     cout << endl;
  254 }
  255 
  256 int HLCmdLineApp::getNumDigits ( int i )
  257 {
  258     int res=0;
  259     while ( i ) {
  260         i/=10;
  261         ++res;
  262     }
  263     return res;
  264 }
  265 
  266 void HLCmdLineApp::printProgressBar ( int total, int count )
  267 {
  268     if ( !total ) return;
  269     int p=100*count / total;
  270     int numProgressItems=p/10;
  271     cout << "\r[";
  272     for ( int i=0; i<10; i++ ) {
  273         cout << ( ( i<numProgressItems ) ?"#":" " );
  274     }
  275     cout<< "] " <<setw ( 3 ) <<p<<"%, "<<count << " / " << total << "  " <<flush;
  276     if ( p==100 ) {
  277         cout << endl;
  278     }
  279 }
  280 
  281 void HLCmdLineApp::printCurrentAction ( const string&outfilePath,
  282                                         int total, int count, int countWidth )
  283 {
  284     cout << "Writing file "
  285          << setw ( countWidth ) << count
  286          << " of "
  287          << total
  288          << ": "
  289          << outfilePath
  290          << "\n";
  291 }
  292 
  293 void HLCmdLineApp::printIOErrorReport ( unsigned int numberErrorFiles,
  294                                         vector<string> & fileList,
  295                                         const string &action, const string &streamName  )
  296 {
  297     
  298     
  299     cerr << "highlight: Could not "
  300          << action
  301          << " file"
  302          << ( ( numberErrorFiles>1 ) ?"s":"" ) <<":\n";
  303     
  304     if (numberErrorFiles==1 && fileList[0].size()==0){
  305         cerr<<streamName<<"\n";
  306     }
  307     else {
  308         copy ( fileList.begin(), fileList.end(), ostream_iterator<string> ( cerr, "\n" ) );
  309     }
  310     
  311     if ( fileList.size() < numberErrorFiles ) {
  312         cerr << "... ["
  313              << ( numberErrorFiles - fileList.size() )
  314              << " of "
  315              << numberErrorFiles
  316              << " failures not shown, use --"
  317              << OPT_VERBOSE
  318              << " switch to print all failures]\n";
  319     }
  320 }
  321 
  322 vector <string> HLCmdLineApp::collectPluginPaths(const vector<string>& plugins)
  323 {
  324     vector<string> absolutePaths;
  325     for (unsigned int i=0; i<plugins.size(); i++) {
  326         if (Platform::fileExists(plugins[i])) {
  327             absolutePaths.push_back(plugins[i]);
  328         } else {
  329             absolutePaths.push_back(dataDir.getPluginPath(plugins[i]+".lua"));
  330         }
  331     }
  332     return absolutePaths;
  333 }
  334 
  335 int HLCmdLineApp::run ( const int argc, const char*argv[] )
  336 {
  337     CmdLineOptions options ( argc, argv );
  338 
  339     // set data directory path, where /langDefs and /themes reside
  340     string dataDirPath = ( options.getDataDir().empty() ) ?  Platform::getAppPath() :options.getDataDir();
  341 
  342     if ( options.printVersion() ) {
  343         printVersionInfo();
  344         return EXIT_SUCCESS;
  345     }
  346 
  347     dataDir.initSearchDirectories ( dataDirPath );
  348 
  349     if ( options.printHelp() ) {
  350         Help::printHelp(options.getHelpTopic());
  351         return EXIT_SUCCESS;
  352     }
  353 
  354     if ( options.printConfigInfo() ) {
  355         printConfigInfo ( );
  356         return EXIT_SUCCESS;
  357     }
  358 
  359     //call before printInstalledLanguages!
  360     dataDir.loadFileTypeConfig ( "filetypes" );
  361 
  362     string scriptKind=options.getListScriptKind();
  363     if (scriptKind.length()) {
  364         if ( scriptKind.find("theme")==0 ) {
  365             return printInstalledFiles(dataDir.getThemePath(""), "*.theme", "theme", OPT_STYLE, options.getCategories());
  366         }
  367         else if ( scriptKind.find("plug")==0 ) {
  368             return printInstalledFiles(dataDir.getPluginPath(""), "*.lua", "plug-in", OPT_PLUGIN, options.getCategories());
  369         }
  370         else if (  scriptKind.find("lang")==0 ) {
  371             return printInstalledFiles(dataDir.getLangPath(""), "*.lang", "langDef", OPT_SYNTAX, options.getCategories());
  372         } else {
  373             cerr << "highlight: Unknown script type '"<< scriptKind << "'. Apply one of 'themes', 'langs' or 'plug-ins'.\n";
  374             return EXIT_FAILURE;
  375         }
  376     }
  377 
  378     const vector <string> inFileList=options.getInputFileNames();
  379 
  380     if ( options.enableBatchMode() && inFileList[0].empty() ) {
  381         return EXIT_FAILURE;
  382     }
  383 
  384     string themePath=options.getAbsThemePath().empty() ? dataDir.getThemePath ( options.getThemeName(), options.useBase16Theme() ): options.getAbsThemePath();
  385     
  386     unique_ptr<highlight::CodeGenerator> generator ( highlight::CodeGenerator::getInstance ( options.getOutputType() ) );
  387 
  388     generator->setHTMLAttachAnchors ( options.attachLineAnchors() );
  389     generator->setHTMLOrderedList ( options.orderedList() );
  390     generator->setHTMLInlineCSS ( options.inlineCSS() );
  391     generator->setHTMLEnclosePreTag ( options.enclosePreTag() );
  392     generator->setHTMLAnchorPrefix ( options.getAnchorPrefix() );
  393     generator->setHTMLClassName ( options.getClassName() );
  394 
  395     generator->setLATEXReplaceQuotes ( options.replaceQuotes() );
  396     generator->setLATEXNoShorthands ( options.disableBabelShorthands() );
  397     generator->setLATEXPrettySymbols ( options.prettySymbols() );
  398     generator->setLATEXBeamerMode ( options.enableBeamerMode() );
  399     
  400     generator->setRTFPageSize ( options.getPageSize() );
  401     generator->setRTFCharStyles ( options.includeCharStyles() );
  402     generator->setRTFPageColor ( options.includePageColor() );
  403     
  404     generator->setSVGSize ( options.getSVGWidth(),  options.getSVGHeight() );
  405 
  406     generator->setESCCanvasPadding ( options.getCanvasPadding() );
  407 
  408     if (options.useCRDelimiter())
  409         generator->setEOLDelimiter('\r');
  410 
  411     generator->setValidateInput ( options.validateInput() );
  412     generator->setNumberWrappedLines ( options.numberWrappedLines() );
  413 
  414     generator->setStyleInputPath ( options.getStyleInFilename() );
  415     generator->setStyleOutputPath ( options.getStyleOutFilename() );
  416     generator->setIncludeStyle ( options.includeStyleDef() );
  417     generator->setPrintLineNumbers ( options.printLineNumbers(), options.getNumberStart() );
  418     generator->setPrintZeroes ( options.fillLineNrZeroes() );
  419     generator->setFragmentCode ( options.fragmentOutput() );
  420     generator->setOmitVersionComment ( options.omitVersionInfo() );
  421     generator->setIsolateTags ( options.isolateTags() );
  422 
  423     generator->setKeepInjections ( options.keepInjections());
  424     generator->setPreformatting ( options.getWrappingStyle(),
  425                                   ( generator->getPrintLineNumbers() ) ?
  426                                   options.getLineLength() - options.getNumberWidth() : options.getLineLength(),
  427                                   options.getNumberSpaces() );
  428 
  429     //generator->setEncoding ( options.getEncoding() );
  430     generator->setBaseFont ( options.getBaseFont() ) ;
  431     generator->setBaseFontSize ( options.getBaseFontSize() ) ;
  432     generator->setLineNumberWidth ( options.getNumberWidth() );
  433     generator->setStartingNestedLang( options.getStartNestedLang());
  434     generator->disableTrailingNL(options.disableTrailingNL());
  435     generator->setPluginParameter(options.getPluginParameter());
  436     
  437     if (options.getLineRangeStart()>0 && options.getLineRangeEnd()>0){
  438         generator->setStartingInputLine(options.getLineRangeStart());
  439         generator->setMaxInputLineCnt(options.getLineRangeEnd());    
  440     }
  441 
  442     bool styleFileWanted = !options.fragmentOutput() || options.styleOutPathDefined();
  443 
  444     const  vector <string> pluginFileList=collectPluginPaths( options.getPluginPaths());
  445     for (unsigned int i=0; i<pluginFileList.size(); i++) {
  446         if ( !generator->initPluginScript(pluginFileList[i]) ) {
  447             cerr << "highlight: "
  448                  << generator->getPluginScriptError()
  449                  << " in "
  450                  << pluginFileList[i]
  451                  <<"\n";
  452             return EXIT_FAILURE;
  453         }
  454     }
  455 
  456     if ( !generator->initTheme ( themePath ) ) {
  457         cerr << "highlight: "
  458              << generator->getThemeInitError()
  459              << "\n";
  460         return EXIT_FAILURE;
  461     }
  462 
  463     if ( options.printOnlyStyle() ) {
  464         if (!options.formatSupportsExtStyle()) {
  465             cerr << "highlight: output format supports no external styles.\n";
  466             return EXIT_FAILURE;
  467         }
  468         bool useStdout =  options.getStyleOutFilename() =="stdout" || options.forceStdout();
  469         string cssOutFile=options.getOutDirectory()  + options.getStyleOutFilename();
  470         bool success=generator->printExternalStyle ( useStdout?"":cssOutFile );
  471         if ( !success ) {
  472             cerr << "highlight: Could not write " << cssOutFile <<".\n";
  473             return EXIT_FAILURE;
  474         }
  475         return EXIT_SUCCESS;
  476     }
  477 
  478     bool formattingEnabled = generator->initIndentationScheme ( options.getIndentScheme() );
  479 
  480     if ( !formattingEnabled && !options.getIndentScheme().empty() ) {
  481         cerr << "highlight: Undefined indentation scheme "
  482              << options.getIndentScheme()
  483              << ".\n";
  484         return EXIT_FAILURE;
  485     }
  486     
  487     generator->setIndentationOptions(options.getAStyleOptions());
  488 
  489     string outDirectory = options.getOutDirectory();
  490 #ifndef WIN32
  491     ifstream dirTest ( outDirectory.c_str() );
  492     if ( !outDirectory.empty() && !options.quietMode() && !dirTest ) {
  493         cerr << "highlight: Output directory \""
  494              << outDirectory
  495              << "\" does not exist.\n";
  496         return EXIT_FAILURE;
  497     }
  498     dirTest.close();
  499 #endif
  500 
  501     bool initError=false, IOError=false, twoPassMode=false;
  502     unsigned int fileCount=inFileList.size(),
  503                  fileCountWidth=getNumDigits ( fileCount ),
  504                  i=0,
  505                  numBadFormatting=0,
  506                  numBadInput=0,
  507                  numBadOutput=0;
  508 
  509     vector<string> badFormattedFiles, badInputFiles, badOutputFiles;
  510     std::set<string> usedFileNames;
  511     string inFileName, outFilePath;
  512     string suffix, lastSuffix;
  513     string twoPassOutFile=Platform::getTempFilePath();
  514     if ( options.syntaxGiven() ) { // user defined language definition, valid for all files
  515         string syntaxByFile=options.getSyntaxByFilename();
  516         string testSuffix = syntaxByFile.empty() ? options.getSyntax() : dataDir.getFileSuffix(syntaxByFile); 
  517         //FIXME
  518         suffix = dataDir.guessFileType (testSuffix, syntaxByFile, syntaxByFile.empty(), options.getSingleOutFilename().length()==0 );         
  519     }
  520 
  521     generator->setFilesCnt(fileCount);
  522 
  523     while ( i < fileCount && !initError ) {
  524         
  525         if ( Platform::fileSize(inFileList[i]) > options.getMaxFileSize() ) {
  526             
  527             if ( numBadInput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) {
  528                 badInputFiles.push_back ( inFileList[i] + " (size)" );
  529             }
  530             ++i;
  531             continue;
  532         }
  533         
  534         if (i==0 && twoPassMode) {
  535              if ( !generator->initPluginScript(twoPassOutFile) ) {
  536                 cerr << "highlight: "
  537                  << generator->getPluginScriptError()
  538                  << " in "
  539                  << twoPassOutFile
  540                  <<"\n";
  541                 initError = true;
  542                 break;
  543             }
  544         }
  545     
  546         if ( !options.syntaxGiven() ) { // determine file type for each file
  547             suffix = dataDir.guessFileType ( dataDir.getFileSuffix ( inFileList[i] ), inFileList[i] );
  548         }
  549         
  550         if ( suffix.empty()  && options.forceOutput()) suffix=options.getFallbackSyntax(); //avoid segfault
  551         if ( suffix.empty() ) {
  552             if ( !options.enableBatchMode() )
  553                 cerr << "highlight: Undefined language definition. Use --"
  554                      << OPT_SYNTAX << " option.\n";
  555             if ( !options.forceOutput() ) {
  556                 initError = true;
  557                 break;
  558             }
  559         }
  560 
  561         if ( suffix != lastSuffix ) {
  562             
  563             string langDefPath=options.getAbsLangPath().empty() ? dataDir.getLangPath ( suffix+".lang" ) : options.getAbsLangPath();
  564 
  565             highlight::LoadResult loadRes= generator-> loadLanguage( langDefPath );
  566 
  567             if ( loadRes==highlight::LOAD_FAILED_REGEX ) {
  568                 cerr << "highlight: Regex error ( "
  569                      << generator->getSyntaxRegexError()
  570                      << " ) in "<<suffix<<".lang\n";
  571                 initError = true;
  572                 break;
  573             } else if ( loadRes==highlight::LOAD_FAILED_LUA ) {
  574                 cerr << "highlight: Lua error ( "
  575                      << generator->getSyntaxLuaError()
  576                      << " ) in "<<suffix<<".lang\n";
  577                 initError = true;
  578                 break;
  579             } else if ( loadRes==highlight::LOAD_FAILED ) {
  580                 // do also ignore error msg if --syntax parameter should be skipped
  581                 if ( ! (options.forceOutput() || options.quietMode() || options.isSkippedExt ( suffix )) ) {
  582                     cerr << "highlight: Unknown source file extension \""
  583                          << suffix
  584                          << "\". Consider the "
  585                          << (options.enableBatchMode() ? "--skip" : "--force or --syntax")
  586                          << " option.\n";
  587                 }
  588                 if ( !options.forceOutput() ) {
  589                     initError = true;
  590                     break;
  591                 }
  592             }
  593             if ( options.printDebugInfo() && loadRes==highlight::LOAD_OK ) {
  594                 printDebugInfo ( generator->getSyntaxReader(), langDefPath );
  595             }
  596             lastSuffix = suffix;
  597             
  598             string encoding= options.getEncoding();
  599             //user has explicitly defined the encoding:
  600             if (!options.encodingDefined()) {
  601                 
  602                 //syntax definition setting:
  603                 string encodingHint= generator->getSyntaxEncodingHint();
  604                 if (encodingHint.size())
  605                     encoding=encodingHint;
  606                 
  607                 // filetypes.conf setting has higher priority:
  608                 encodingHint= dataDir.getEncodingHint(suffix);
  609                 if (encodingHint.size())
  610                     encoding=encodingHint;
  611             }
  612             generator->setEncoding (encoding);
  613         }
  614 
  615         if (twoPassMode && !generator->syntaxRequiresTwoPassRun()) {
  616             ++i;
  617             continue;
  618         }
  619         
  620         string::size_type pos= ( inFileList[i] ).find_last_of ( Platform::pathSeparator );
  621         inFileName = inFileList[i].substr ( pos+1 );
  622 
  623         if ( options.enableBatchMode() ) {
  624             if (usedFileNames.count(inFileName)) {
  625                 string prefix=inFileList[i].substr (2, pos-1 );
  626                 replace (prefix.begin(), prefix.end(), Platform::pathSeparator, '_');
  627                 inFileName.insert(0, prefix);
  628             } else {
  629                 usedFileNames.insert(inFileName);
  630             }
  631             if (!options.forceStdout()){
  632                 outFilePath = outDirectory;
  633                 outFilePath += inFileName;
  634                 outFilePath += options.getOutFileSuffix();
  635             }
  636             if ( !options.quietMode() &&  !options.forceStdout() ) {
  637                 if ( options.printProgress() ) {
  638                     printProgressBar ( fileCount, i+1 );
  639                 } else {
  640                     printCurrentAction ( outFilePath, fileCount, i+1, fileCountWidth );
  641                 }
  642             }
  643         } else if (!options.forceStdout()) {
  644             outFilePath = options.getSingleOutFilename();
  645             if ( outFilePath.size() && outFilePath==options.getSingleInFilename() ) {
  646                 cerr << "highlight: Output path equals input path: \""
  647                      << outFilePath << "\".\n";
  648                 initError = true;
  649                 break;
  650             }
  651         }
  652 
  653         if ( options.useFNamesAsAnchors() ) {
  654             generator->setHTMLAnchorPrefix ( inFileName );
  655         }
  656 
  657         generator->setTitle ( options.getDocumentTitle().empty() ?
  658                               inFileList[i]:options.getDocumentTitle() );
  659 
  660         generator->setKeyWordCase ( options.getKeywordCase() );
  661         highlight::ParseError error = generator->generateFile ( inFileList[i], outFilePath );
  662 
  663         if ( error==highlight::BAD_INPUT ) {
  664             if ( numBadInput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) {
  665                 badInputFiles.push_back ( inFileList[i] );
  666             }
  667         } else if ( error==highlight::BAD_OUTPUT ) {
  668             if ( numBadOutput++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) {
  669                 badOutputFiles.push_back ( outFilePath );
  670             }
  671         }
  672         if ( formattingEnabled && !generator->formattingIsPossible() ) {
  673             if ( numBadFormatting++ < IO_ERROR_REPORT_LENGTH || options.printDebugInfo() ) {
  674                 badFormattedFiles.push_back ( outFilePath );
  675             }
  676         }
  677         
  678         ++i;
  679         
  680         if (i==fileCount && outFilePath.size() && generator->requiresTwoPassParsing() && twoPassOutFile.size() 
  681             && !numBadInput && !numBadOutput && !twoPassMode) {
  682             
  683             bool success=generator->printPersistentState(twoPassOutFile);
  684             if ( !success ) {
  685                 cerr << "highlight: Could not write "<< twoPassOutFile <<".\n";
  686                 IOError = true;
  687             } else {
  688                 twoPassMode=true;
  689                 if ( !options.quietMode() &&  !options.forceStdout() ) {
  690                     cout << "Enabling two-pass mode using "<<twoPassOutFile<<"\n";
  691                 }
  692                 //start over, add plug-in to list in next iteration
  693                 usedFileNames.clear();
  694                 generator->resetSyntaxReaders();
  695                 i=0;
  696                 lastSuffix.clear();
  697                 numBadFormatting=0;
  698                 badFormattedFiles.clear();    
  699             }
  700         }
  701     }
  702 
  703     if ( i  && !options.includeStyleDef()
  704             && !options.inlineCSS()
  705             && styleFileWanted
  706             && options.formatSupportsExtStyle() ) {
  707         string cssOutFile=outDirectory  + options.getStyleOutFilename();
  708         bool success=generator->printExternalStyle ( cssOutFile );
  709         if ( !success ) {
  710             cerr << "highlight: Could not write " << cssOutFile <<".\n";
  711             IOError = true;
  712         }
  713     }
  714 
  715     if ( i && options.printIndexFile() ) {
  716         bool success=generator -> printIndexFile ( inFileList, outDirectory );
  717         if ( !success ) {
  718             cerr << "highlight: Could not write index file.\n";
  719             IOError = true;
  720         }
  721     }
  722     
  723     if ( numBadInput ) {
  724         printIOErrorReport ( numBadInput, badInputFiles, "read input", "<stdin>" );
  725         IOError = true;
  726     }
  727     if ( numBadOutput ) {
  728         printIOErrorReport ( numBadOutput, badOutputFiles, "write output",  "<stdout>" );
  729         IOError = true;
  730     }
  731     if ( numBadFormatting ) {
  732         printIOErrorReport ( numBadFormatting, badFormattedFiles, "reformat", "<stdout>" );
  733     }
  734     
  735     vector<string> posTestErrors = generator->getPosTestErrors();
  736     if (posTestErrors.size()){
  737         IOError = true;
  738         printIOErrorReport ( posTestErrors.size(), posTestErrors, "validate", "<stdin>" );
  739     }
  740     
  741     if (twoPassMode) {
  742         unlink(twoPassOutFile.c_str());
  743     }
  744         
  745     return ( initError || IOError ) ? EXIT_FAILURE : EXIT_SUCCESS;
  746 }
  747 
  748 int main ( const int argc, const char *argv[] )
  749 {
  750     HLCmdLineApp app;
  751     return app.run ( argc, argv );
  752 }