diff options
-rw-r--r-- | src/cite.cpp | 172 | ||||
-rw-r--r-- | src/cite.h | 5 | ||||
-rw-r--r-- | src/debug.cpp | 3 | ||||
-rw-r--r-- | src/debug.h | 3 | ||||
-rwxr-xr-x | templates/html/bib2xhtml.pl | 11 |
5 files changed, 138 insertions, 56 deletions
diff --git a/src/cite.cpp b/src/cite.cpp index 78df0c3..fd6fe3e 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -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/"; @@ -108,64 +105,141 @@ 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 StringVector &citeDataList = Config_getList(CITE_BIB_FILES); - for (const auto &bibdata : citeDataList) + 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.c_str(); - 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) { - 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),(uint)(k-j)); + } + else + { + 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); @@ -233,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); @@ -327,7 +401,7 @@ void CitationManager::generatePage() } // 9. Remove temporary files - if (RM_TMP_FILES) + if (!citeDebug) { thisDir.remove(citeListFile); thisDir.remove(doxygenBstFile); @@ -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. * @@ -70,6 +70,7 @@ class CitationManager private: /** Create the database, with an expected maximum of \a size entries */ CitationManager(); + void insertCrossReferencesForBibFile(const QCString &bibFile); struct Private; std::unique_ptr<Private> p; }; diff --git a/src/debug.cpp b/src/debug.cpp index 6815b3b..f56ef3a 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -42,7 +42,8 @@ static std::map< std::string, Debug::DebugMask > s_labels = { "filteroutput", Debug::FilterOutput }, { "lex", Debug::Lex }, { "plantuml", Debug::Plantuml }, - { "fortranfixed2free", Debug::FortranFixed2Free } + { "fortranfixed2free", Debug::FortranFixed2Free }, + { "cite", Debug::Cite } }; //------------------------------------------------------------------------ diff --git a/src/debug.h b/src/debug.h index edc95e2..e71595f 100644 --- a/src/debug.h +++ b/src/debug.h @@ -36,7 +36,8 @@ class Debug FilterOutput = 0x00001000, Lex = 0x00002000, Plantuml = 0x00004000, - FortranFixed2Free = 0x00008000 + FortranFixed2Free = 0x00008000, + Cite = 0x00010000 }; static void print(DebugMask mask,int prio,const char *fmt,...); diff --git a/templates/html/bib2xhtml.pl b/templates/html/bib2xhtml.pl index da6dc62..539aaab 100755 --- a/templates/html/bib2xhtml.pl +++ b/templates/html/bib2xhtml.pl @@ -118,11 +118,14 @@ sub html_ent { s/\\lfloor\b/⌊/g; s/\\rfloor\b/⌋/g; } +$bdebug = 0; foreach (@ARGV) { if (/\.bib$/) { $bibfile = $_; $bibfile =~ s/\.bib$//; push(@bibfiles,$bibfile); + } elsif ("$_" eq "-d") { + $bdebug = 1; } else { $htmlfile = $_; } @@ -198,7 +201,7 @@ while (<BBLFILE>) { next loop; } $nentry++; - ($bcite, $blabel) = m+<dt><a name=\"([^\"]*)\">\[([^\]]*)\]</a></dt><dd>+; + ($bcite, $blabel) = m:<dt><a\s+name=\"([^\"]*)\">\[([^\]]*)\]</a></dt><dd>:; $blabel = "$nentry"; $bibcite{$bcite} = $blabel; } @@ -222,7 +225,7 @@ while (<BBLFILE>) { } s/\%\n//g; s/(\.(<\/cite>|<\/a>|\')+)\./$1/g; - s:(<dt><a name=\"[^\"]*\">\[)[^\]]*(\]</a></dt><dd>):$1$nentry$2:; + s:(<dt><a\s+name=\"[^\"]*\">\[)[^\]]*(\]</a></dt><dd>):$1$nentry$2:; while (m/(\\(cite(label)?)(\001\d+)\{([^\001]+)\4\})/) { $old = $1; $cmd = $2; @@ -315,5 +318,7 @@ close (OHTMLFILE); close(HTMLFILE); chmod($mode, "$htmlfile$$"); rename("$htmlfile$$", $htmlfile); -unlink(@tmpfiles); +if ($bdebug == 0) { + unlink(@tmpfiles); +} exit(0); |