From 89f9d113d0d788552a32b699a89f273f6ce58c0f Mon Sep 17 00:00:00 2001 From: albert-github Date: Wed, 29 Jul 2020 18:00:57 +0200 Subject: crossref citations are shown unconditionally The crossref items in a bib file are unconditionally added to the list of used citations although the the citation to which the crossref belongs to is not used. This has been fixed. The problem was seen in the CGAL output. Note: a crossref in LaTeX is a bit different from the normal understanding of cross-reference, from https://tex.stackexchange.com/questions/401138/what-is-the-bibtex-crossref-field-used-for: "crossref can be used if you have multiple entries referring to the same proceeding, book or similar." --- src/cite.cpp | 39 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 38 insertions(+), 1 deletion(-) diff --git a/src/cite.cpp b/src/cite.cpp index 78df0c3..d02cb75 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -139,6 +139,7 @@ void CitationManager::generatePage() input.at(fi.size())='\0'; int pos=0; int s; + QCString label1; while ((s=input.find('\n',pos))!=-1) { QCString line = input.mid((uint)pos,(uint)(s-pos)); @@ -152,12 +153,48 @@ void CitationManager::generatePage() 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 + // 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(label1.data())!=p->entries.end()) && + (p->entries.find(label.data())==p->entries.end())) // not found yet { insert(label); } } } + else if (line.stripWhiteSpace().startsWith("@")) + { + // assumption entry like: "@book { name," or "@book { name" (spaces optional) + int j=line.find("{",0); + // when no {, go hunting for it + while (j==-1 && (s=input.find('\n',pos))!=-1) + { + line = input.mid((uint)pos,(uint)(s-pos)); + j=line.find("{",0); + pos=s+1; + } + // search for the name + label1 = ""; + while (label1.isEmpty()) + { + int k=line.find(",",j); + if (k != -1) + { + label1 = line.mid((uint)(j+1),(uint)(k-j-1)); + } + else + { + label1 = line.mid((uint)(j+1)); + } + label1 = label1.stripWhiteSpace(); + j = -1; + if (label1.isEmpty() && (s=input.find('\n',pos))!=-1) + { + line = input.mid((uint)pos,(uint)(s-pos)); + pos=s+1; + } + } + } } } } -- cgit v0.12 From 7894dd7d82d9fcfe524cb7ff2e5dea1824816bb8 Mon Sep 17 00:00:00 2001 From: albert-github Date: Thu, 30 Jul 2020 11:38:57 +0200 Subject: crossref citations are shown unconditionally Based on the review - implemented tip `find("{");` instead of `find("{",0);` - made `label..` names more expressing their content - got a few regressions regarding endless loops (it is incorrect bib file syntax), the constructs have to be at the end of the bib file, like (also with extra newlines) - `@book ,` - `@book { ,` --- src/cite.cpp | 49 ++++++++++++++++++++++++++----------------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/src/cite.cpp b/src/cite.cpp index d02cb75..271e262 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -139,7 +139,7 @@ void CitationManager::generatePage() input.at(fi.size())='\0'; int pos=0; int s; - QCString label1; + QCString citeName; while ((s=input.find('\n',pos))!=-1) { QCString line = input.mid((uint)pos,(uint)(s-pos)); @@ -152,46 +152,49 @@ void CitationManager::generatePage() int k=line.find("}",i); if (j!=-1 && k!=-1) { - QCString label = line.mid((uint)(j+1),(uint)(k-j-1)); + 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(label1.data())!=p->entries.end()) && - (p->entries.find(label.data())==p->entries.end())) // not found yet + if ((p->entries.find(citeName.data())!=p->entries.end()) && + (p->entries.find(crossrefName.data())==p->entries.end())) // not found yet { - insert(label); + insert(crossrefName); } } } else if (line.stripWhiteSpace().startsWith("@")) { // assumption entry like: "@book { name," or "@book { name" (spaces optional) - int j=line.find("{",0); + int j=line.find("{"); // when no {, go hunting for it while (j==-1 && (s=input.find('\n',pos))!=-1) { line = input.mid((uint)pos,(uint)(s-pos)); - j=line.find("{",0); + j=line.find("{"); pos=s+1; } // search for the name - label1 = ""; - while (label1.isEmpty()) + citeName = ""; + if (j != -1) // to prevent something like "@manual ," and no { found { - int k=line.find(",",j); - if (k != -1) + while (s != -1 && citeName.isEmpty()) { - label1 = line.mid((uint)(j+1),(uint)(k-j-1)); - } - else - { - label1 = line.mid((uint)(j+1)); - } - label1 = label1.stripWhiteSpace(); - j = -1; - if (label1.isEmpty() && (s=input.find('\n',pos))!=-1) - { - line = input.mid((uint)pos,(uint)(s-pos)); - pos=s+1; + int k=line.find(",",j); + if (k != -1) + { + citeName = line.mid((uint)(j+1),(uint)(k-j-1)); + } + else + { + citeName = line.mid((uint)(j+1)); + } + citeName = citeName.stripWhiteSpace(); + j = -1; + if (citeName.isEmpty() && (s=input.find('\n',pos))!=-1) + { + line = input.mid((uint)pos,(uint)(s-pos)); + pos=s+1; + } } } } -- cgit v0.12 From e9853388b4c682ecf0e19d1222d75ad452039340 Mon Sep 17 00:00:00 2001 From: albert-github Date: Fri, 31 Jul 2020 14:40:07 +0200 Subject: crossref citations are shown unconditionally unfortunately some more regressions... --- src/cite.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/cite.cpp b/src/cite.cpp index 271e262..f9af2b4 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -175,28 +175,31 @@ void CitationManager::generatePage() } // search for the name citeName = ""; - if (j != -1) // to prevent something like "@manual ," and no { found + if (s != -1 && j!= -1) // to prevent something like "@manual ," and no { found { + int k=line.find(",",j); + j++; while (s != -1 && citeName.isEmpty()) { - int k=line.find(",",j); if (k != -1) { - citeName = line.mid((uint)(j+1),(uint)(k-j-1)); + citeName = line.mid((uint)(j),(uint)(k-j)); } else { - citeName = line.mid((uint)(j+1)); + citeName = line.mid((uint)(j)); } citeName = citeName.stripWhiteSpace(); - j = -1; + j = 0; if (citeName.isEmpty() && (s=input.find('\n',pos))!=-1) { line = input.mid((uint)pos,(uint)(s-pos)); pos=s+1; + k=line.find(","); } } } + //printf("citeName = #%s#\n",citeName.data()); } } } -- cgit v0.12 From f8c1c09b5f25489223530bb73b9d7b173562b3ff Mon Sep 17 00:00:00 2001 From: Dimitri van Heesch Date: Fri, 31 Jul 2020 20:23:27 +0200 Subject: Moved citation cross reference searching to a separate function --- src/cite.cpp | 200 ++++++++++++++++++++++++++++++++++------------------------- src/cite.h | 5 +- 2 files changed, 119 insertions(+), 86 deletions(-) diff --git a/src/cite.cpp b/src/cite.cpp index f9af2b4..044651b 100644 --- a/src/cite.cpp +++ b/src/cite.cpp @@ -108,107 +108,139 @@ 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; - QCString citeName; - 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 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); - } - } + citeName = line.mid((uint)(j)); } - else if (line.stripWhiteSpace().startsWith("@")) + citeName = citeName.stripWhiteSpace(); + j = 0; + if (citeName.isEmpty() && has_next_line()) { - // assumption entry like: "@book { name," or "@book { name" (spaces optional) - int j=line.find("{"); - // when no {, go hunting for it - while (j==-1 && (s=input.find('\n',pos))!=-1) - { - line = input.mid((uint)pos,(uint)(s-pos)); - j=line.find("{"); - pos=s+1; - } - // search for the name - citeName = ""; - if (s != -1 && j!= -1) // to prevent something like "@manual ," and no { found - { - int k=line.find(",",j); - j++; - while (s != -1 && citeName.isEmpty()) - { - if (k != -1) - { - citeName = line.mid((uint)(j),(uint)(k-j)); - } - else - { - citeName = line.mid((uint)(j)); - } - citeName = citeName.stripWhiteSpace(); - j = 0; - if (citeName.isEmpty() && (s=input.find('\n',pos))!=-1) - { - line = input.mid((uint)pos,(uint)(s-pos)); - pos=s+1; - k=line.find(","); - } - } - } - //printf("citeName = #%s#\n",citeName.data()); + 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 + + // 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); diff --git a/src/cite.h b/src/cite.h index 4666d5a..9fea954 100644 --- a/src/cite.h +++ b/src/cite.h @@ -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 p; }; -- cgit v0.12