summaryrefslogtreecommitdiffstats
path: root/src/cite.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/cite.cpp')
-rw-r--r--src/cite.cpp212
1 files changed, 143 insertions, 69 deletions
diff --git a/src/cite.cpp b/src/cite.cpp
index dac2bcd..fd6fe3e 100644
--- a/src/cite.cpp
+++ b/src/cite.cpp
@@ -4,8 +4,8 @@
* Based on a patch by David Munger
*
* Permission to use, copy, modify, and distribute this software and its
- * documentation under the terms of the GNU General Public License is hereby
- * granted. No representations are made about the suitability of this software
+ * documentation under the terms of the GNU General Public License is hereby
+ * granted. No representations are made about the suitability of this software
* for any purpose. It is provided "as is" without express or implied warranty.
* See the GNU General Public License for more details.
*
@@ -22,6 +22,7 @@
#include "portable.h"
#include "resourcemgr.h"
#include "util.h"
+#include "debug.h"
#include <qfile.h>
#include <qfileinfo.h>
@@ -30,10 +31,6 @@
#include <map>
#include <string>
-// Remove the temporary files
-#define RM_TMP_FILES (true)
-//#define RM_TMP_FILES (false)
-
const char *bibTmpFile = "bibTmpFile_";
const char *bibTmpDir = "bibTmpDir/";
@@ -94,7 +91,7 @@ void CitationManager::clear()
bool CitationManager::isEmpty() const
{
- uint numFiles = Config_getList(CITE_BIB_FILES).count();
+ size_t numFiles = Config_getList(CITE_BIB_FILES).size();
return (numFiles==0 || p->entries.empty());
}
@@ -108,72 +105,147 @@ const char *CitationManager::anchorPrefix() const
return "CITEREF_";
}
-void CitationManager::generatePage()
+void CitationManager::insertCrossReferencesForBibFile(const QCString &bibFile)
{
- //printf("** CitationManager::generatePage() count=%d\n",m_ordering.count());
+ // sanity checks
+ if (bibFile.isEmpty())
+ {
+ return;
+ }
+ QFileInfo fi(bibFile);
+ if (!fi.exists())
+ {
+ err("bib file %s not found!\n",bibFile.data());
+ return;
+ }
+ QFile f(bibFile);
+ if (!f.open(IO_ReadOnly))
+ {
+ err("could not open file %s for reading\n",bibFile.data());
+ return;
+ }
- // do not generate an empty citations page
- if (isEmpty()) return; // nothing to cite
+ // convert file to string
+ QCString doc;
+ QCString input(fi.size()+1);
+ f.readBlock(input.rawData(),fi.size());
+ f.close();
+ input.at(fi.size())='\0';
- // 0. add cross references from the bib files to the cite dictionary
- QFile f;
- const QStrList &citeDataList = Config_getList(CITE_BIB_FILES);
- QStrListIterator li(citeDataList);
- const char *bibdata = 0;
- for (li.toFirst() ; (bibdata = li.current()) ; ++li)
+ int pos=0;
+ int s;
+
+ // helper lambda function to get the next line of input and update pos accordingly
+ auto get_next_line = [&input,&pos,&s]()
{
- QCString bibFile = bibdata;
- if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
- QFileInfo fi(bibFile);
- if (fi.exists())
+ uint prevPos = (uint)pos;
+ pos=s+1;
+ return input.mid(prevPos,(uint)(s-prevPos));
+ };
+
+ // helper lambda function to return if the end of the input has reached
+ auto end_of_input = [&s]()
+ {
+ return s==-1;
+ };
+
+ // helper lambda function to proceed to the next line in the input, and update s
+ // to point to the start of the line. Return true as long as there is a new line.
+ auto has_next_line = [&input,&pos,&s]()
+ {
+ s=input.find('\n',pos);
+ return s!=-1;
+ };
+
+ // search for citation cross references
+ QCString citeName;
+ while (has_next_line())
+ {
+ QCString line = get_next_line();
+
+ int i;
+ if (line.stripWhiteSpace().startsWith("@"))
{
- if (!bibFile.isEmpty())
+ // assumption entry like: "@book { name," or "@book { name" (spaces optional)
+ int j = line.find('{');
+ // when no {, go hunting for it
+ while (j==-1 && has_next_line())
{
- f.setName(bibFile);
- if (!f.open(IO_ReadOnly))
- {
- err("could not open file %s for reading\n",bibFile.data());
- }
- QCString doc;
- QCString input(fi.size()+1);
- f.readBlock(input.rawData(),fi.size());
- f.close();
- input.at(fi.size())='\0';
- int pos=0;
- int s;
- while ((s=input.find('\n',pos))!=-1)
+ line = get_next_line();
+ j = line.find('{');
+ }
+ // search for the name
+ citeName = "";
+ if (!end_of_input() && j!=-1) // to prevent something like "@manual ," and no { found
+ {
+ int k = line.find(',',j);
+ j++;
+ // found a line "@....{.....,...." or "@.....{....."
+ // ^=j ^=k ^=j k=-1
+ while (!end_of_input() && citeName.isEmpty())
{
- QCString line = input.mid((uint)pos,(uint)(s-pos));
- pos=s+1;
-
- int i;
- if ((i = line.find("crossref")) != -1) /* assumption cross reference is on one line and the only item */
+ if (k!=-1)
+ {
+ citeName = line.mid((uint)(j),(uint)(k-j));
+ }
+ else
{
- int j=line.find("{",i);
- int k=line.find("}",i);
- if (j!=-1 && k!=-1)
- {
- QCString label = line.mid((uint)(j+1),(uint)(k-j-1));
- if (p->entries.find(label.data())==p->entries.end()) // not found yet
- {
- insert(label);
- }
- }
+ citeName = line.mid((uint)(j));
+ }
+ citeName = citeName.stripWhiteSpace();
+ j = 0;
+ if (citeName.isEmpty() && has_next_line())
+ {
+ line = get_next_line();
+ k = line.find(',');
}
}
}
+ //printf("citeName = #%s#\n",citeName.data());
}
- else if (!fi.exists())
+ else if ((i=line.find("crossref"))!=-1 && !citeName.isEmpty()) /* assumption cross reference is on one line and the only item */
{
- err("bib file %s not found!\n",bibFile.data());
+ int j = line.find('{',i);
+ int k = line.find('}',i);
+ if (j>i && k>j)
+ {
+ QCString crossrefName = line.mid((uint)(j+1),(uint)(k-j-1));
+ // check if the reference with the cross reference is used
+ // insert cross refererence when cross reference has not yet been added.
+ if ((p->entries.find(citeName.data())!=p->entries.end()) &&
+ (p->entries.find(crossrefName.data())==p->entries.end())) // not found yet
+ {
+ insert(crossrefName);
+ }
+ }
}
}
+}
+
+void CitationManager::generatePage()
+{
+ //printf("** CitationManager::generatePage() count=%d\n",m_ordering.count());
+
+ // do not generate an empty citations page
+ if (isEmpty()) return; // nothing to cite
+
+ bool citeDebug = Debug::isFlagSet(Debug::Cite);
+
+ // 0. add cross references from the bib files to the cite dictionary
+ QFile f;
+ const StringVector &citeDataList = Config_getList(CITE_BIB_FILES);
+ for (const auto &bibdata : citeDataList)
+ {
+ QCString bibFile = bibdata.c_str();
+ if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
+ insertCrossReferencesForBibFile(bibFile);
+ }
// 1. generate file with markers and citations to OUTPUT_DIRECTORY
QCString outputDir = Config_getString(OUTPUT_DIRECTORY);
QCString citeListFile = outputDir+"/citelist.doc";
f.setName(citeListFile);
- if (!f.open(IO_WriteOnly))
+ if (!f.open(IO_WriteOnly))
{
err("could not open file %s for writing\n",citeListFile.data());
}
@@ -205,11 +277,15 @@ void CitationManager::generatePage()
QCString bibOutputDir = outputDir+"/"+bibTmpDir;
QCString bibOutputFiles = "";
QDir thisDir;
- thisDir.mkdir(bibOutputDir);
+ if (!thisDir.exists(bibOutputDir) && !thisDir.mkdir(bibOutputDir))
+ {
+ err("Failed to create temporary output directory '%s', skipping citations\n",bibOutputDir.data());
+ return;
+ }
int i = 0;
- for (li.toFirst() ; (bibdata = li.current()) ; ++li)
+ for (const auto &bibdata : citeDataList)
{
- QCString bibFile = bibdata;
+ QCString bibFile = bibdata.c_str();
if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
QFileInfo fi(bibFile);
if (fi.exists())
@@ -231,7 +307,7 @@ void CitationManager::generatePage()
int exitCode;
Portable::sysTimerStop();
if ((exitCode=Portable::system("perl","\""+bib2xhtmlFile+"\" "+bibOutputFiles+" \""+
- citeListFile+"\"")) != 0)
+ citeListFile+"\"" + (citeDebug ? " -d" : ""))) != 0)
{
err("Problems running bibtex. Verify that the command 'perl --version' works from the command line. Exit code: %d\n",
exitCode);
@@ -242,7 +318,7 @@ void CitationManager::generatePage()
// 6. read back the file
f.setName(citeListFile);
- if (!f.open(IO_ReadOnly))
+ if (!f.open(IO_ReadOnly))
{
err("could not open file %s for reading\n",citeListFile.data());
}
@@ -294,16 +370,16 @@ void CitationManager::generatePage()
// 7. add it as a page
addRelatedPage(fileName(),theTranslator->trCiteReferences(),doc,fileName(),1);
- // 8. for latex we just copy the bib files to the output and let
+ // 8. for latex we just copy the bib files to the output and let
// latex do this work.
if (Config_getBool(GENERATE_LATEX))
{
// copy bib files to the latex output dir
QCString latexOutputDir = Config_getString(LATEX_OUTPUT)+"/";
i = 0;
- for (li.toFirst() ; (bibdata = li.current()) ; ++li)
+ for (const auto &bibdata : citeDataList)
{
- QCString bibFile = bibdata;
+ QCString bibFile = bibdata.c_str();
// Note: file can now have multiple dots
if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
fi.setFile(bibFile);
@@ -325,7 +401,7 @@ void CitationManager::generatePage()
}
// 9. Remove temporary files
- if (RM_TMP_FILES)
+ if (!citeDebug)
{
thisDir.remove(citeListFile);
thisDir.remove(doxygenBstFile);
@@ -333,9 +409,9 @@ void CitationManager::generatePage()
// we might try to remove too many files as empty files didn't get a corresponding new file
// but the remove function does not emit an error for it and we don't catch the error return
// so no problem.
- for (unsigned int j = 1; j <= citeDataList.count(); j++)
+ for (size_t j = 1; j <= citeDataList.size(); j++)
{
- thisDir.remove(bibOutputDir + bibTmpFile + QCString().setNum(j) + ".bib");
+ thisDir.remove(bibOutputDir + bibTmpFile + QCString().setNum(static_cast<ulong>(j)) + ".bib");
}
thisDir.rmdir(bibOutputDir);
}
@@ -370,13 +446,11 @@ void CitationManager::writeLatexBibliography(FTextStream &t) const
}
t << "\\bibliographystyle{" << style << "}\n"
"\\bibliography{";
- QStrList &citeDataList = Config_getList(CITE_BIB_FILES);
+ const StringVector &citeDataList = Config_getList(CITE_BIB_FILES);
int i = 0;
- QStrListIterator li(citeDataList);
- const char *bibdata = 0;
- for (li.toFirst() ; (bibdata = li.current()) ; ++li)
+ for (const auto &bibdata : citeDataList)
{
- QCString bibFile = bibdata;
+ QCString bibFile = bibdata.c_str();
// Note: file can now have multiple dots
if (!bibFile.isEmpty() && bibFile.right(4)!=".bib") bibFile+=".bib";
QFileInfo fi(bibFile);