Orb/Doxygen/src/pre.l
changeset 1 82f11024044a
parent 0 42188c7ea2d9
equal deleted inserted replaced
0:42188c7ea2d9 1:82f11024044a
    33 #include <qstrlist.h>
    33 #include <qstrlist.h>
    34 #include <qdict.h>
    34 #include <qdict.h>
    35 #include <qregexp.h>
    35 #include <qregexp.h>
    36 #include <qfileinfo.h>
    36 #include <qfileinfo.h>
    37 #include <qdir.h>
    37 #include <qdir.h>
       
    38 #include <qmap.h>
    38   
    39   
    39 #include "pre.h"
    40 #include "pre.h"
    40 #include "constexp.h"
    41 #include "constexp.h"
    41 #include "define.h"
    42 #include "define.h"
    42 #include "doxygen.h"
    43 #include "doxygen.h"
    47 #include "bufstr.h"
    48 #include "bufstr.h"
    48 #include "portable.h"
    49 #include "portable.h"
    49 #include "bufstr.h"
    50 #include "bufstr.h"
    50 
    51 
    51 #define YY_NEVER_INTERACTIVE 1
    52 #define YY_NEVER_INTERACTIVE 1
    52   
       
    53 
    53 
    54 struct FileState
    54 struct FileState
    55 {
    55 {
    56   FileState(int size) : fileBuf(size), oldFileBuf(0), oldFileBufPos(0) {}
    56   FileState(int size) : fileBuf(size), oldFileBuf(0), oldFileBufPos(0) {}
    57   int lineNr;
    57   int lineNr;
   124 {
   124 {
   125   bool ambig;
   125   bool ambig;
   126   QFileInfo fi(name);
   126   QFileInfo fi(name);
   127   g_yyFileName=convertToQCString(fi.absFilePath());
   127   g_yyFileName=convertToQCString(fi.absFilePath());
   128   g_yyFileDef=findFileDef(Doxygen::inputNameDict,g_yyFileName,ambig);
   128   g_yyFileDef=findFileDef(Doxygen::inputNameDict,g_yyFileName,ambig);
       
   129   if (g_yyFileDef == 0 && Config_getBool("PREPROCESS_INCLUDES")) {
       
   130 		// Search again using Doxygen::includeNameDict
       
   131 	    // First insert the include file in the Doxygen::includeNameDict if
       
   132 	    // it is not there already. This can happen if the Doxygen::includeNameDict
       
   133 	    // has scanned .../inc but the #include "usr/usr.h"
       
   134 	    // The Doxygen::includeNameDict will not have usr.h in it so we poke it in.
       
   135 		if (!Doxygen::includeNameDict->find(g_yyFileName.data())) {
       
   136 			//Debug::print(Debug::IncludeGraph, 0, "pre.l setFileName() inserting in Doxygen::includeNameDict: %s\n", name);
       
   137 			FileDef  *fd=new FileDef(fi.dirPath()+"/", fi.fileName());
       
   138             FileName *fn=0;
       
   139             if (!fi.absFilePath().isEmpty() && (fn=(*Doxygen::includeNameDict)[name])) {
       
   140 				fn->append(fd);
       
   141             } else {
       
   142 				fn = new FileName(fi.absFilePath(), name);
       
   143 				fn->append(fd);
       
   144 				Doxygen::includeNameDict->insert(name, fn);
       
   145             }
       
   146 			g_yyFileDef = fd;
       
   147 		} else {
       
   148 			// Search the dictionary
       
   149 			FileName *fn = Doxygen::includeNameDict->find(g_yyFileName.data());
       
   150 			FileNameIterator fni(*fn);
       
   151 			FileDef *fd = 0;
       
   152 			for (fni.toFirst(); (fd=fni.current()); ++fni) {
       
   153 				if (fd && fd->absFilePath() == g_yyFileName) {
       
   154 					break;
       
   155 				}
       
   156 				fd = 0;
       
   157 			}
       
   158 			g_yyFileDef = fd;
       
   159 		}
       
   160 		//printf("pre.l setFileName() searching Doxygen::includeNameDict for %s, result=%p\n", name, g_yyFileDef);
       
   161 		//Debug::print(Debug::IncludeGraph, 0, "pre.l setFileName() searching Doxygen::includeNameDict for %s, result=%p\n", name, g_yyFileDef);
       
   162   }
   129   if (g_yyFileDef && g_yyFileDef->isReference()) g_yyFileDef=0;
   163   if (g_yyFileDef && g_yyFileDef->isReference()) g_yyFileDef=0;
   130   g_insideCS = g_yyFileName.right(3)==".cs";
   164   g_insideCS = g_yyFileName.right(3)==".cs";
   131 }
   165 }
   132 
   166 
   133 static void incrLevel()
   167 static void incrLevel()
   188 
   222 
   189 static FileState *checkAndOpenFile(const QCString &fileName,bool &alreadyIncluded)
   223 static FileState *checkAndOpenFile(const QCString &fileName,bool &alreadyIncluded)
   190 {
   224 {
   191   alreadyIncluded = FALSE;
   225   alreadyIncluded = FALSE;
   192   FileState *fs = 0;
   226   FileState *fs = 0;
   193   //printf("checkAndOpenFile(%s)\n",fileName.data());
   227   //msg("checkAndOpenFile(%s)\n", fileName.data());
   194   QFileInfo fi(fileName);
   228   QFileInfo fi(fileName);
   195   if (fi.exists() && fi.isFile())
   229   if (fi.exists() && fi.isFile())
   196   {
   230   {
   197     QCString absName = convertToQCString(fi.absFilePath());
   231     QCString absName = convertToQCString(fi.absFilePath());
   198 
   232 	//msg("checkAndOpenFile() found: %s\n", absName.data());
   199     // global guard
   233     // global guard
   200     if (g_curlyCount==0) // not #include inside { ... }
   234     if (g_curlyCount==0) // not #include inside { ... }
   201     {
   235     {
   202       if (g_allIncludes.find(absName)!=0)
   236       if (g_allIncludes.find(absName)!=0)
   203       {
   237       {
   204         alreadyIncluded = TRUE;
   238         alreadyIncluded = TRUE;
   205         //printf("  already included 1\n");
   239         //printf("  already included 1\n");
   206         return 0; // already done
   240         if (!Config_getBool("PREPROCCESS_FULL_TU")) {
   207       }
   241 			return 0; // already done
   208       g_allIncludes.insert(absName,(void *)0x8);
   242 		}
       
   243       } else {
       
   244 		g_allIncludes.insert(absName,(void *)0x8);
       
   245 	  }
   209     }
   246     }
   210     // check include stack for absName
   247     // check include stack for absName
   211 	// This is equivelent to walking the stack and setting alreadyIncluded to
   248 	// This is equivelent to walking the stack and setting alreadyIncluded to
   212 	// TRUE if absName matches any filename
   249 	// TRUE if absName matches any filename
   213     QStack<FileState> tmpStack;
   250     QStack<FileState> tmpStack;
   282   return fs;
   319   return fs;
   283 }
   320 }
   284 
   321 
   285 static FileState *findFile(const char *fileName,bool localInclude,bool &alreadyIncluded)
   322 static FileState *findFile(const char *fileName,bool localInclude,bool &alreadyIncluded)
   286 {
   323 {
   287   //printf("** findFile(%s,%d) g_yyFileName=%s\n",fileName,localInclude,g_yyFileName.data());
   324   //msg("** findFile(%s,%d) g_yyFileName=%s\n",fileName,localInclude,g_yyFileName.data());
   288   if (localInclude && !g_yyFileName.isEmpty())
   325   if (localInclude && !g_yyFileName.isEmpty())
   289   {
   326   {
   290     QFileInfo fi(g_yyFileName);
   327     QFileInfo fi(g_yyFileName);
   291     if (fi.exists())
   328     if (fi.exists())
   292     {
   329     {
  1226         msg("#include %s: parsing...\n",incFileName.data());
  1263         msg("#include %s: parsing...\n",incFileName.data());
  1227       }
  1264       }
  1228       if (oldFileDef)
  1265       if (oldFileDef)
  1229       {
  1266       {
  1230         // add include dependency to the file in which the #include was found
  1267         // add include dependency to the file in which the #include was found
       
  1268 	    //Debug::print(Debug::IncludeGraph, 0, "pre.l readIncludeFile() adding dependency \"%s\" to \"%s\"\n", incFileName, oldFileDef->absFilePath().data());
  1231         oldFileDef->addIncludeDependency(g_yyFileDef,incFileName,localInclude,g_isImported);
  1269         oldFileDef->addIncludeDependency(g_yyFileDef,incFileName,localInclude,g_isImported);
  1232         // add included by dependency
  1270         // add included by dependency
  1233         if (g_yyFileDef)
  1271         if (g_yyFileDef)
  1234         {
  1272         {
  1235           //printf("Adding include dependency %s->%s\n",oldFileDef->name().data(),incFileName.data());
  1273           //printf("Adding include dependency %s->%s\n",oldFileDef->name().data(),incFileName.data());
  1502 					  outputChar(*yytext);
  1540 					  outputChar(*yytext);
  1503 					  BEGIN( CopyLine );
  1541 					  BEGIN( CopyLine );
  1504 					}
  1542 					}
  1505 <CopyLine>{ID}/{BN}{0,80}"("			{
  1543 <CopyLine>{ID}/{BN}{0,80}"("			{
  1506   					  Define *def=0;
  1544   					  Define *def=0;
  1507 					  //def=g_fileDefineDict->find(yytext);
  1545 					  def=g_fileDefineDict->find(yytext);
  1508 					  //printf("Search for define %s found=%d g_includeStack.isEmpty()=%d "
  1546 					  //printf("Search for define %s found=%d g_includeStack.count()=%d "
  1509 					  //       "g_curlyCount=%d g_macroExpansion=%d g_expandOnlyPredef=%d "
  1547 					  //       "g_curlyCount=%d g_macroExpansion=%d g_expandOnlyPredef=%d "
  1510 					  //	 "isPreDefined=%d\n",yytext,def ? 1 : 0,
  1548 					  //	 "isPreDefined=%d tu=%d\n",yytext,def ? 1 : 0,
  1511 					  //	 g_includeStack.isEmpty(),g_curlyCount,g_macroExpansion,g_expandOnlyPredef,
  1549 					  //	 g_includeStack.count(),g_curlyCount,g_macroExpansion,g_expandOnlyPredef,
  1512 					  //	 def ? def->isPredefined : -1
  1550 					  //	 def ? def->isPredefined : -1,
       
  1551 					  //	 Config_getBool("PREPROCCESS_FULL_TU")
  1513 					  //	);
  1552 					  //	);
  1514 					  if ((g_includeStack.isEmpty() || g_curlyCount>0) &&
  1553 					  if ((g_includeStack.isEmpty() || g_curlyCount>0 || Config_getBool("PREPROCCESS_FULL_TU")) &&
  1515 					      g_macroExpansion &&
  1554 					      g_macroExpansion &&
  1516 					      (def=g_fileDefineDict->find(yytext)) &&
  1555 					      (def=g_fileDefineDict->find(yytext)) &&
  1517 					      (!g_expandOnlyPredef || def->isPredefined)
  1556 					      (!g_expandOnlyPredef || def->isPredefined || Config_getBool("PREPROCCESS_FULL_TU"))
  1518 					     )
  1557 					     )
  1519 					  {
  1558 					  {
  1520 					    //printf("Found it!\n");
  1559 					    //printf("Found it!\n");
  1521 					    g_roundCount=0;
  1560 					    g_roundCount=0;
  1522 					    g_defArgsStr=yytext;
  1561 					    g_defArgsStr=yytext;
  1919 					  g_defName = yytext;
  1958 					  g_defName = yytext;
  1920                                           g_defArgsStr.resize(0);
  1959                                           g_defArgsStr.resize(0);
  1921 					  g_defText.resize(0);
  1960 					  g_defText.resize(0);
  1922 					  g_defLitText.resize(0);
  1961 					  g_defLitText.resize(0);
  1923 					  g_defVarArgs = FALSE;
  1962 					  g_defVarArgs = FALSE;
  1924 					  if ( g_defName!=g_lastGuardName )
  1963 					  if ( g_defName!=g_lastGuardName || Config_getBool("PREPROCCESS_FULL_TU"))
  1925 					  { // define may appear in the output
  1964 					  { // define may appear in the output
  1926 					    QCString tmp=(QCString)"#define "+g_defName;
  1965 					    QCString tmp=(QCString)"#define "+g_defName;
  1927 					    outputArray(tmp.data(),tmp.length());
  1966 					    outputArray(tmp.data(),tmp.length());
  1928 					    g_quoteArg=FALSE;
  1967 					    g_quoteArg=FALSE;
  1929 					    g_insideComment=FALSE;
  1968 					    g_insideComment=FALSE;
  2435   //delete g_fileDefineDict; g_fileDefineDict=0;
  2474   //delete g_fileDefineDict; g_fileDefineDict=0;
  2436   delete g_expandedDict; g_expandedDict=0;
  2475   delete g_expandedDict; g_expandedDict=0;
  2437   delete g_pathList; g_pathList=0;
  2476   delete g_pathList; g_pathList=0;
  2438 }
  2477 }
  2439 
  2478 
  2440 void loadGolbalInput(BufStr &input)
  2479 void dumpDefineDict(const DefineDict *theDefDict)
  2441 {
  2480 {
  2442 	QStrList& preIncList = Config_getList("PRE_INCLUDES");
  2481 	if (Debug::isFlagSet(Debug::Preprocessor)) {
  2443 	int countPreInc = 0;
  2482 		// Make a map to sort the macros in alphbetical order
  2444 	if (!preIncList.isEmpty()) {
  2483 		typedef QMap<QString, Define*> DefineMapType;
  2445 		QStrListIterator sli(preIncList);
  2484 		DefineMapType DefineMap;
  2446 		char *filterStr;
  2485 		Define *def = 0;
  2447 		for (sli.toFirst(); (filterStr = sli.current()); ++sli) {
  2486 		QDictIterator<Define> it(*theDefDict);
  2448 			printf("Adding %s\n", filterStr);
  2487 		while (it.current()) {
  2449 			QString incStmt = "#include \"";
  2488 			def = it.current();
  2450 			incStmt += filterStr;
  2489 			DefineMap.insert(def->name, def);
  2451 			incStmt += "\"\n";
  2490 			++it;
  2452 			printf("Adding string %s, length %d\n", incStmt.data(), incStmt.length());
       
  2453 			g_inputBuf->addArray(incStmt.data(), incStmt.length());
       
  2454 			printf("Added  string %s, length %d\n", incStmt.data(), incStmt.length());
       
  2455 			countPreInc++;
       
  2456 		}
  2491 		}
  2457 	}
  2492 		// Now write them out
  2458 	msg("Added pre-includes[%d]\n", countPreInc);
  2493 		DefineMapType::Iterator mapIt;
  2459 	g_inputBuf->addArray(input.data(), input.size());
  2494 		for (mapIt = DefineMap.begin(); mapIt != DefineMap.end(); ++mapIt) {
  2460 	// Is this really needed?
  2495 			def = mapIt.data();
  2461 	g_inputBuf->addChar('\0');
  2496 			QString myDecl = def->name;
  2462 	msg("Added input\n");
  2497 			if (def->nargs > 0) {
  2463 }
  2498 				myDecl.append("(");
  2464 
  2499 				myDecl.append(def->args);
  2465 class GlobalInBufProtect
  2500 				myDecl.append(")");
  2466 {
  2501 			}
  2467 public:
  2502 			printf("#define %s %s /* %s %d */\n",
  2468 	GlobalInBufProtect(int size) {
  2503 				myDecl.data(),
  2469 		g_inputBuf = new BufStr(size);
  2504 				def->definition.data(),
  2470 	}
  2505 				def->fileName.data(),
  2471 	~GlobalInBufProtect() {
  2506 				def->lineNr
  2472 		delete g_inputBuf;
  2507 				);
  2473 		g_inputBuf = 0;
  2508 		}
  2474 	}
  2509 	}
  2475 };
  2510 }
       
  2511 
       
  2512 void dumpDefineDicts()
       
  2513 {
       
  2514 	if (Debug::isFlagSet(Debug::Preprocessor)) {
       
  2515 		printf("g_expandedDict:\n");
       
  2516 		dumpDefineDict(g_expandedDict);
       
  2517 		printf("g_fileDefineDict:\n");
       
  2518 		dumpDefineDict(g_fileDefineDict);
       
  2519 	}
       
  2520 }
  2476 
  2521 
  2477 void preprocessFile(const char *fileName,BufStr &input,BufStr &output)
  2522 void preprocessFile(const char *fileName,BufStr &input,BufStr &output)
  2478 {
  2523 {
  2479   uint orgOffset=output.curPos();
  2524   uint orgOffset=output.curPos();
  2480   //printf("##########################\n%s\n####################\n",
  2525   //printf("##########################\n%s\n####################\n",
  2482 
  2527 
  2483   g_macroExpansion = Config_getBool("MACRO_EXPANSION");
  2528   g_macroExpansion = Config_getBool("MACRO_EXPANSION");
  2484   g_expandOnlyPredef = Config_getBool("EXPAND_ONLY_PREDEF");
  2529   g_expandOnlyPredef = Config_getBool("EXPAND_ONLY_PREDEF");
  2485   g_curlyCount=0;
  2530   g_curlyCount=0;
  2486   g_nospaces=FALSE;
  2531   g_nospaces=FALSE;
  2487   // Initialise the global buffer and when I go out of scope free it
  2532   g_inputBuf=&input;
  2488   GlobalInBufProtect g_input_protect(input.size());
       
  2489   //g_inputBuf=&input;
       
  2490   loadGolbalInput(input);
       
  2491   
       
  2492   g_inputBufPos=0;
  2533   g_inputBufPos=0;
  2493   g_outputBuf=&output;
  2534   g_outputBuf=&output;
  2494   g_includeStack.setAutoDelete(TRUE);
  2535   g_includeStack.setAutoDelete(TRUE);
  2495   g_includeStack.clear();
  2536   g_includeStack.clear();
  2496   //g_fileDefineDict->setAutoDelete(TRUE);
  2537   //g_fileDefineDict->setAutoDelete(TRUE);
  2497   //g_fileDefineDict->clear();
  2538   //g_fileDefineDict->clear();
  2498   g_expandedDict->setAutoDelete(FALSE);
  2539   g_expandedDict->setAutoDelete(FALSE);
  2499   g_expandedDict->clear();
  2540   g_expandedDict->clear();
  2500   g_condStack.clear();
  2541   g_condStack.clear();
  2501   g_condStack.setAutoDelete(TRUE);
  2542   g_condStack.setAutoDelete(TRUE);
  2502   
       
  2503   static bool firstTime=TRUE;
  2543   static bool firstTime=TRUE;
  2504   if (firstTime)
  2544   if (firstTime)
  2505   {
  2545   {
  2506     // add predefined macros
  2546     // add predefined macros
  2507     char *defStr;
  2547     char *defStr;
  2625     Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data());
  2665     Debug::print(Debug::ExtCmd,0,"Executing popen(`%s`)\n",cmd.data());
  2626     preYYin = portable_popen(cmd,"r");
  2666     preYYin = portable_popen(cmd,"r");
  2627     if (!preYYin)
  2667     if (!preYYin)
  2628     {
  2668     {
  2629       err("Error: could not execute filter %s\n",cmd.data());
  2669       err("Error: could not execute filter %s\n",cmd.data());
  2630 	  delete g_inputBuf;
       
  2631       return;
  2670       return;
  2632     }
  2671     }
  2633   }
  2672   }
  2634 #endif
  2673 #endif
  2635   g_yyLineNr = 1;
  2674   g_yyLineNr = 1;
  2652     portable_pclose(preYYin);
  2691     portable_pclose(preYYin);
  2653 #endif
  2692 #endif
  2654   
  2693   
  2655   if (Debug::isFlagSet(Debug::Preprocessor))
  2694   if (Debug::isFlagSet(Debug::Preprocessor))
  2656   {
  2695   {
       
  2696 	printf("preprocessFile() dump from %d to %d\n", orgOffset, output.curPos());
  2657     char *orgPos=output.data()+orgOffset;
  2697     char *orgPos=output.data()+orgOffset;
  2658     char *newPos=output.data()+output.curPos();
  2698     char *newPos=output.data()+output.curPos();
  2659     msg("Preprocessor output (size: %d bytes):\n",newPos-orgPos);
  2699     printf("Preprocessor output (size: %d bytes):\n",newPos-orgPos);
  2660     int line=1;
  2700     int line=1;
  2661     msg("---------\n00001 ");
  2701     printf("---------\n00001 ");
  2662     while (orgPos<newPos) 
  2702     while (orgPos<newPos) 
  2663     {
  2703     {
  2664       putchar(*orgPos);
  2704       putchar(*orgPos);
  2665       if (*orgPos=='\n') printf("%05d ",++line);
  2705       if (*orgPos=='\n') printf("%05d ",++line);
  2666       orgPos++;
  2706       orgPos++;
  2667     }
  2707     }
  2668     msg("\n---------\n");
  2708     printf("\n---------\n");
       
  2709 	dumpDefineDicts();
  2669   }
  2710   }
  2670 }
  2711 }
  2671 
  2712 
  2672 void preFreeScanner()
  2713 void preFreeScanner()
  2673 {
  2714 {