NCBI C++ ToolKit
xm_index.cpp
Go to the documentation of this file.

Go to the SVN repository for this file.

1 /* $Id: xm_index.cpp 99335 2023-03-13 13:48:10Z stakhovv $
2  * ===========================================================================
3  *
4  * PUBLIC DOMAIN NOTICE
5  * National Center for Biotechnology Information
6  *
7  * This software/database is a "United States Government Work" under the
8  * terms of the United States Copyright Act. It was written as part of
9  * the author's official duties as a United States Government employee and
10  * thus cannot be copyrighted. This software/database is freely available
11  * to the public for use. The National Library of Medicine and the U.S.
12  * Government have not placed any restriction on its use or reproduction.
13  *
14  * Although all reasonable efforts have been taken to ensure the accuracy
15  * and reliability of the software and data, the NLM and the U.S.
16  * Government do not and cannot warrant the performance or results that
17  * may be obtained by using this software or data. The NLM and the U.S.
18  * Government disclaim all warranties, express or implied, including
19  * warranties of performance, merchantability or fitness for any particular
20  * purpose.
21  *
22  * Please cite the author in any work or product based on this material.
23  *
24  * ===========================================================================
25  *
26  * File Name: xm_index.cpp
27  *
28  * Author: Sergey Bazhin
29  *
30  * File Description:
31  * Parsing flat records to memory blocks in XML format.
32  *
33  */
34 
35 #include <ncbi_pch.hpp>
36 
37 #include "ftacpp.hpp"
38 #include "index.h"
39 
40 #include "ftaerr.hpp"
41 #include "indx_blk.h"
42 #include "indx_def.h"
43 #include "utilfun.h"
44 #include "fta_xml.h"
45 
46 #ifdef THIS_FILE
47 # undef THIS_FILE
48 #endif
49 #define THIS_FILE "xm_index.cpp"
50 
51 #define XML_FAKE_ACC_TAG "AC "
52 
54 
55 struct XmlKwordBlk {
56  const char* str;
59 };
60 using XmlKwordBlkPtr = const XmlKwordBlk*;
61 
62 // clang-format off
64  {"<INSDSeq_locus>", 1, INSDSEQ_LOCUS},
65  {"<INSDSeq_length>", 2, INSDSEQ_LENGTH},
66  {"<INSDSeq_strandedness>", 3, INSDSEQ_STRANDEDNESS},
67  {"<INSDSeq_moltype>", 4, INSDSEQ_MOLTYPE},
68  {"<INSDSeq_topology>", 5, INSDSEQ_TOPOLOGY},
69  {"<INSDSeq_division>", 6, INSDSEQ_DIVISION},
70  {"<INSDSeq_update-date>", 7, INSDSEQ_UPDATE_DATE},
71  {"<INSDSeq_create-date>", 8, INSDSEQ_CREATE_DATE},
72  {"<INSDSeq_update-release>", 9, INSDSEQ_UPDATE_RELEASE},
73  {"<INSDSeq_create-release>", 10, INSDSEQ_CREATE_RELEASE},
74  {"<INSDSeq_definition>", 11, INSDSEQ_DEFINITION},
75  {"<INSDSeq_primary-accession>", 12, INSDSEQ_PRIMARY_ACCESSION},
76  {"<INSDSeq_entry-version>", 13, INSDSEQ_ENTRY_VERSION},
77  {"<INSDSeq_accession-version>", 14, INSDSEQ_ACCESSION_VERSION},
78  {"<INSDSeq_other-seqids>", 15, INSDSEQ_OTHER_SEQIDS},
79  {"<INSDSeq_secondary-accessions>", 16, INSDSEQ_SECONDARY_ACCESSIONS},
80  {"<INSDSeq_keywords>", 17, INSDSEQ_KEYWORDS},
81  {"<INSDSeq_segment>", 18, INSDSEQ_SEGMENT},
82  {"<INSDSeq_source>", 19, INSDSEQ_SOURCE},
83  {"<INSDSeq_organism>", 20, INSDSEQ_ORGANISM},
84  {"<INSDSeq_taxonomy>", 21, INSDSEQ_TAXONOMY},
85  {"<INSDSeq_references>", 22, INSDSEQ_REFERENCES},
86  {"<INSDSeq_comment>", 23, INSDSEQ_COMMENT},
87  {"<INSDSeq_primary>", 24, INSDSEQ_PRIMARY},
88  {"<INSDSeq_source-db>", 25, INSDSEQ_SOURCE_DB},
89  {"<INSDSeq_database-reference>", 26, INSDSEQ_DATABASE_REFERENCE},
90  {"<INSDSeq_feature-table>", 27, INSDSEQ_FEATURE_TABLE},
91  {"<INSDSeq_sequence>", 28, INSDSEQ_SEQUENCE},
92  {"<INSDSeq_contig>", 29, INSDSEQ_CONTIG},
93  {nullptr, -1, -1}
94 };
95 
97  {"<INSDFeature_key>", 1, INSDFEATURE_KEY},
98  {"<INSDFeature_location>", 2, INSDFEATURE_LOCATION},
99  {"<INSDFeature_intervals>", 3, INSDFEATURE_INTERVALS},
100  {"<INSDFeature_quals>", 4, INSDFEATURE_QUALS},
101  {nullptr, -1, -1}
102 };
103 
105  {"<INSDInterval_from>", 1, INSDINTERVAL_FROM},
106  {"<INSDInterval_to>", 2, INSDINTERVAL_TO},
107  {"<INSDInterval_point>", 3, INSDINTERVAL_POINT},
108  {"<INSDInterval_accession>", 4, INSDINTERVAL_ACCESSION},
109  {nullptr, -1, -1}
110 };
111 
113  {"<INSDReference_reference>", 1, INSDREFERENCE_REFERENCE},
114  {"<INSDReference_position>", 2, INSDREFERENCE_POSITION},
115  {"<INSDReference_authors>", 3, INSDREFERENCE_AUTHORS},
116  {"<INSDReference_consortium>", 4, INSDREFERENCE_CONSORTIUM},
117  {"<INSDReference_title>", 5, INSDREFERENCE_TITLE},
118  {"<INSDReference_journal>", 6, INSDREFERENCE_JOURNAL},
119  {"<INSDReference_xref>", 7, INSDREFERENCE_XREF},
120  {"<INSDReference_medline>", 8, INSDREFERENCE_MEDLINE},
121  {"<INSDReference_pubmed>", 9, INSDREFERENCE_PUBMED},
122  {"<INSDReference_remark>", 10, INSDREFERENCE_REMARK},
123  {nullptr, -1, -1}
124 };
125 
127  {"<INSDQualifier_name>", 1, INSDQUALIFIER_NAME},
128  {"<INSDQualifier_value>", 2, INSDQUALIFIER_VALUE},
129  {nullptr, -1, -1}
130 };
131 
133  {"<INSDXref_dbname>", 1, INSDXREF_DBNAME},
134  {"<INSDXref_id>", 2, INSDXREF_ID},
135  {nullptr, -1, -1}
136 };
137 
139  {"<INSDSecondary-accn>", 1, INSDSECONDARY_ACCN},
140  {"<INSDKeyword>", 1, INSDKEYWORD},
141  {"<INSDFeature>", 1, INSDFEATURE},
142  {"<INSDInterval>", 1, INSDINTERVAL},
143  {"<INSDQualifier>", 1, INSDQUALIFIER},
144  {"<INSDReference>", 1, INSDREFERENCE},
145  {"<INSDAuthor>", 1, INSDAUTHOR},
146  {"<INSDXref>", 1, INSDXREF},
147  {nullptr, -1, -1}
148 };
149 // clang-format on
150 
151 /**********************************************************/
153 {
154  XmlIndexPtr xip;
155 
156  xip = new XmlIndex;
157  xip->tag = -1;
158  xip->order = -1;
159  xip->start = 0;
160  xip->end = 0;
161  xip->start_line = -1;
162  xip->end_line = -1;
163  xip->subtags = nullptr;
164  xip->next = nullptr;
165  return (xip);
166 }
167 
168 /**********************************************************/
170 {
171  char* p;
172  char* q;
173 
174  for (p = buf, q = buf; *p != '\0';) {
175  if (StringEquN(p, "&lt;", 4)) {
176  *q++ = '<';
177  p += 4;
178  } else if (StringEquN(p, "&gt;", 4)) {
179  *q++ = '>';
180  p += 4;
181  } else if (StringEquN(p, "&amp;", 5)) {
182  *q++ = '&';
183  p += 5;
184  } else if (StringEquN(p, "&apos;", 6)) {
185  *q++ = '\'';
186  p += 6;
187  } else if (StringEquN(p, "&quot;", 6)) {
188  *q++ = '\"';
189  p += 6;
190  } else
191  *q++ = *p++;
192  }
193  *q = '\0';
194 }
195 
196 /**********************************************************/
197 char* XMLGetTagValue(const char* entry, const XmlIndex* xip)
198 {
199  if (! entry || ! xip || xip->start == 0 || xip->end == 0 ||
200  xip->start >= xip->end)
201  return nullptr;
202 
203  size_t i = xip->end - xip->start;
204  char* buf = MemNew(i + 1);
205  StringNCpy(buf, entry + xip->start, i);
206  buf[i] = '\0';
207 
209  return (buf);
210 }
211 
212 /**********************************************************/
213 char* XMLFindTagValue(const char* entry, const XmlIndex* xip, Int4 tag)
214 {
215  for (; xip; xip = xip->next)
216  if (xip->tag == tag)
217  break;
218  if (! xip)
219  return nullptr;
220  return (XMLGetTagValue(entry, xip));
221 }
222 
223 /**********************************************************/
224 static bool XMLDelSegnum(IndexblkPtr ibp, const char* segnum, size_t len2)
225 {
226  if (! segnum)
227  return false;
228  size_t len1 = StringLen(segnum);
229  if (len2 < len1)
230  return false;
231 
232  /* check, is there enough digits to delete
233  */
234  size_t tlen = len1;
235  char* str = ibp->blocusname;
236  size_t i = StringLen(str) - 1;
237  for (; tlen > 0 && str[i] >= '0' && str[i] <= '9'; i--)
238  tlen--;
239 
240  if (tlen != 0)
241  return false;
242 
243  if (len2 > len1 && str[i] == '0') {
244  /* check, is there enough "0" appended
245  */
246  for (tlen = len2 - len1; tlen > 0 && str[i] == '0'; i--)
247  tlen--;
248 
249  if (tlen != 0)
250  return false;
251  }
252 
253  char* p;
254  char* q;
255  for (q = &str[i + 1], p = q; *p == '0';)
256  p++;
257 
258  i = atoi(segnum);
259  if (atoi(p) != (int)i) {
260  ErrPostEx(SEV_REJECT, ERR_SEGMENT_BadLocusName, "Segment suffix in locus name \"%s\" does not match number in <INSDSEQ_segment> line = \"%d\". Entry dropped.", str, i);
261  ibp->drop = true;
262  }
263 
264  *q = '\0'; /* strip off "len" characters */
265  return true;
266 }
267 
268 /**********************************************************/
269 static void XMLGetSegment(const char* entry, IndexblkPtr ibp)
270 {
271  TokenStatBlkPtr stoken;
272  XmlIndexPtr xip;
273  char* buf;
274  const char* segnum;
275  const char* segtotal;
276 
277  if (! entry || ! ibp || ! ibp->xip)
278  return;
279 
280  for (xip = ibp->xip; xip; xip = xip->next)
281  if (xip->tag == INSDSEQ_SEGMENT)
282  break;
283  if (! xip)
284  return;
285 
286  buf = XMLGetTagValue(entry, xip);
287  if (! buf)
288  return;
289 
290  stoken = TokenString(buf, ' ');
291 
292  if (stoken->num > 2) {
293  segnum = stoken->list->str;
294  segtotal = stoken->list->next->next->str;
295  ibp->segnum = (Uint2)atoi(segnum);
296 
297  if (! XMLDelSegnum(ibp, segnum, StringLen(segtotal))) {
298  ErrPostEx(SEV_ERROR, ERR_SEGMENT_BadLocusName, "Bad locus name \"%s\".", ibp->blocusname);
299  }
300 
301  ibp->segtotal = (Uint2)atoi(segtotal);
302  } else {
303  ErrPostEx(SEV_ERROR, ERR_SEGMENT_IncompSeg, "Incomplete Segment information at line %d.", xip->start_line);
304  }
305 
306  FreeTokenstatblk(stoken);
307  MemFree(buf);
308 }
309 
310 
311 static bool s_HasInput(const Parser& config)
312 {
313  return (config.ffbuf.start != nullptr);
314 }
315 
316 
318 {
319  if (*config.ffbuf.current == '\0') {
320  return -1;
321  }
322  return *(config.ffbuf.current++);
323 }
324 
326 {
327  config.ffbuf.set_offs(offset);
328 }
329 
330 /**********************************************************/
331 static void XMLPerformIndex(ParserPtr pp)
332 {
333  XmlKwordBlkPtr xkbp;
334  IndBlkNextPtr ibnp;
335  IndBlkNextPtr tibnp;
336  XmlIndexPtr xip;
337  IndexblkPtr ibp;
338  char* p;
339  Char s[60];
340  Char ch;
341  size_t count;
342  Int4 line;
343  Int4 c;
344  Int4 i;
345 
346 
347  if (! pp || ! s_HasInput(*pp)) {
348  return;
349  }
350 
351  c = 0;
352  s[0] = '\0';
353  bool within = false;
354  tibnp = nullptr;
355  ibnp = nullptr;
356  ibp = nullptr;
357  xip = nullptr;
358  pp->indx = 0;
359  size_t start_len = StringLen(INSDSEQ_START);
360  for (count = 0, line = 1;;) {
361  if (c != '<') {
362  c = s_GetCharAndAdvance(*pp);
363  if (c < 0)
364  break;
365  count++;
366  if ((Char)c == '\n')
367  line++;
368  }
369  if (c != '<')
370  continue;
371 
372  s[0] = '<';
373  for (i = 1; i < 50; i++) {
374  c = s_GetCharAndAdvance(*pp);
375  if (c < 0)
376  break;
377  count++;
378  ch = (Char)c;
379  if (ch == '\n')
380  line++;
381  s[i] = ch;
382  if (ch == '<' || ch == '>')
383  break;
384  }
385  if (c < 0)
386  break;
387  if (ch == '<')
388  continue;
389  s[++i] = '\0';
390  if (StringEqu(s, INSDSEQ_START)) {
391  if (within)
392  continue;
393  within = true;
394 
395  ibp = new Indexblk;
396  ibp->offset = count - start_len;
397  ibp->linenum = line;
398 
399  if (! ibnp) {
400  ibnp = new IndBlkNode(ibp);
401  tibnp = ibnp;
402  } else {
403  tibnp->next = new IndBlkNode(ibp);
404  tibnp = tibnp->next;
405  }
406 
407  pp->indx++;
408  continue;
409  }
410  if (! within) {
411  if (StringEqu(s, INSDSEQ_END))
412  ErrPostEx(SEV_ERROR, ERR_FORMAT_UnexpectedEnd, "Unexpected end tag \"%s\" of XML record found at line %d.", s, line);
413  continue;
414  }
415  if (StringEqu(s, INSDSEQ_END)) {
416  ibp->len = count - ibp->offset;
417  within = false;
418  continue;
419  }
420  p = s + ((s[1] == '/') ? 2 : 1);
421  for (xkbp = xmkwl; xkbp->str; xkbp++)
422  if (StringEqu(p, xkbp->str + 1))
423  break;
424  if (! xkbp->str)
425  continue;
426  if (! ibp->xip || xip->tag != xkbp->tag) {
427  if (! ibp->xip) {
428  ibp->xip = XMLIndexNew();
429  xip = ibp->xip;
430  } else {
431  xip->next = XMLIndexNew();
432  xip = xip->next;
433  }
434  xip->tag = xkbp->tag;
435  xip->order = xkbp->order;
436  if (s[1] == '/') {
437  xip->end = count - i - ibp->offset;
438  xip->end_line = line;
439  } else {
440  xip->start = count - ibp->offset;
441  xip->start_line = line;
442  }
443  continue;
444  }
445  if (s[1] == '/') {
446  if (xip->end != 0) {
447  xip->next = XMLIndexNew();
448  xip = xip->next;
449  xip->tag = xkbp->tag;
450  xip->order = xkbp->order;
451  }
452  xip->end = count - i - ibp->offset;
453  xip->end_line = line;
454  } else {
455  if (xip->start != 0) {
456  xip->next = XMLIndexNew();
457  xip = xip->next;
458  xip->tag = xkbp->tag;
459  xip->order = xkbp->order;
460  }
461  xip->start = count - ibp->offset;
462  xip->start_line = line;
463  }
464  }
465 
466  pp->entrylist.resize(pp->indx, nullptr);
467  for (tibnp = ibnp, i = 0; tibnp; i++, tibnp = ibnp) {
468  pp->entrylist[i] = tibnp->ibp;
469  ibnp = tibnp->next;
470  delete tibnp;
471  }
472 }
473 
474 /**********************************************************/
475 static void XMLParseVersion(IndexblkPtr ibp, char* line)
476 {
477  char* p;
478  char* q;
479 
480  if (! line) {
481  ErrPostEx(SEV_FATAL, ERR_VERSION_BadVersionLine, "Empty <INSDSeq_accession-version> line. Entry dropped.");
482  ibp->drop = true;
483  return;
484  }
485 
486  for (p = line; *p != '\0' && *p != ' ' && *p != '\t';)
487  p++;
488  if (*p != '\0') {
489  ErrPostEx(SEV_FATAL, ERR_VERSION_BadVersionLine, "Incorrect <INSDSeq_accession-version> line: \"%s\". Entry dropped.", line);
490  ibp->drop = true;
491  return;
492  }
493  q = StringRChr(line, '.');
494  if (! q) {
495  ErrPostEx(SEV_FATAL, ERR_VERSION_MissingVerNum, "Missing version number in <INSDSeq_accession-version> line: \"%s\". Entry dropped.", line);
496  ibp->drop = true;
497  return;
498  }
499  for (p = q + 1; *p >= '0' && *p <= '9';)
500  p++;
501  if (*p != '\0') {
502  ErrPostEx(SEV_FATAL, ERR_VERSION_NonDigitVerNum, "Incorrect VERSION number in <INSDSeq_accession-version> line: \"%s\". Entry dropped.", line);
503  ibp->drop = true;
504  return;
505  }
506  *q = '\0';
507  if (! StringEqu(ibp->acnum, line)) {
508  *q = '.';
509  ErrPostEx(SEV_FATAL, ERR_VERSION_AccessionsDontMatch, "Accessions in <INSDSeq_accession-version> and <INSDSeq_primary-accession> lines don't match: \"%s\" vs \"%s\". Entry dropped.", line, ibp->acnum);
510  ibp->drop = true;
511  return;
512  }
513  *q++ = '.';
514  ibp->vernum = atoi(q);
515 
516  if (ibp->vernum > 0)
517  return;
518 
519  ErrPostEx(SEV_FATAL, ERR_VERSION_InvalidVersion, "Version number \"%d\" from Accession.Version value \"%s.%d\" is not a positive integer. Entry dropped.", ibp->vernum, ibp->acnum, ibp->vernum);
520  ibp->drop = true;
521 }
522 
523 /**********************************************************/
524 static void XMLInitialEntry(IndexblkPtr ibp, const char* entry, bool accver, Parser::ESource source)
525 {
526  XmlIndexPtr xip;
527  char* buf;
528 
529  if (! ibp || ! ibp->xip || ! entry)
530  return;
531 
533  ibp->is_pat = true;
534 
535  ibp->locusname[0] = '\0';
536  ibp->acnum[0] = '\0';
537  for (xip = ibp->xip; xip; xip = xip->next) {
538  if (xip->tag == INSDSEQ_LOCUS && ibp->locusname[0] == '\0') {
539  if (xip->start == 0 || xip->end == 0 || xip->start >= xip->end ||
541  StringCpy(ibp->locusname, "???");
542  StringCpy(ibp->blocusname, "???");
543  continue;
544  }
545  size_t imax = xip->end - xip->start;
546  if (imax > (int)sizeof(ibp->locusname) - 1)
547  imax = sizeof(ibp->locusname) - 1;
548  StringNCpy(ibp->locusname, entry + xip->start, imax);
549  ibp->locusname[imax] = '\0';
550  StringCpy(ibp->blocusname, ibp->locusname);
551  } else if (xip->tag == INSDSEQ_PRIMARY_ACCESSION && ibp->acnum[0] == '\0') {
552  if (xip->start == 0 || xip->end == 0 || xip->start >= xip->end) {
553  StringCpy(ibp->acnum, "???");
554  continue;
555  }
556  size_t imax = xip->end - xip->start;
557  if (imax > (int)sizeof(ibp->acnum) - 1)
558  imax = sizeof(ibp->acnum) - 1;
559  StringNCpy(ibp->acnum, entry + xip->start, imax);
560  ibp->acnum[imax] = '\0';
561  }
562  if (ibp->locusname[0] != '\0' && ibp->acnum[0] != '\0')
563  break;
564  }
565 
567  if (ibp->acnum[0] == '\0')
569  else
571 
572  if (accver) {
573  for (xip = ibp->xip; xip; xip = xip->next) {
574  if (xip->tag != INSDSEQ_ACCESSION_VERSION)
575  continue;
576  buf = XMLGetTagValue(entry, xip);
577  XMLParseVersion(ibp, buf);
578  if (buf) {
580  MemFree(buf);
581  }
582  break;
583  }
584  }
585 
586  ibp->bases = 0;
587  ibp->date = nullptr;
588  StringCpy(ibp->division, "???");
589  for (xip = ibp->xip; xip; xip = xip->next) {
590  if (xip->tag == INSDSEQ_LENGTH && ibp->bases == 0) {
591  buf = XMLGetTagValue(entry, xip);
592  if (! buf)
593  continue;
594  ibp->bases = (size_t)atoi(buf);
595  MemFree(buf);
596  } else if (xip->tag == INSDSEQ_UPDATE_DATE && ! ibp->date) {
597  buf = XMLGetTagValue(entry, xip);
598  if (! buf)
599  continue;
600  ibp->date = GetUpdateDate(buf, source);
601  MemFree(buf);
602  } else if (xip->tag == INSDSEQ_DIVISION && ibp->division[0] == '?') {
603  if (xip->start == 0 || xip->end == 0 || xip->start >= xip->end ||
604  xip->end - xip->start < 3)
605  continue;
606  StringNCpy(ibp->division, entry + xip->start, 3);
607  ibp->division[3] = '\0';
608  if (NStr::CompareNocase(ibp->division, "EST") == 0)
609  ibp->EST = true;
610  else if (StringEqu(ibp->division, "STS"))
611  ibp->STS = true;
612  else if (StringEqu(ibp->division, "GSS"))
613  ibp->GSS = true;
614  else if (StringEqu(ibp->division, "HTC"))
615  ibp->HTC = true;
616  } else if (xip->tag == INSDSEQ_MOLTYPE && ibp->is_prot == false) {
617  buf = XMLGetTagValue(entry, xip);
618  if (NStr::CompareNocase(buf, "AA") == 0)
619  ibp->is_prot = true;
620  MemFree(buf);
621  }
622  if (ibp->bases > 0 && ibp->date && ibp->division[0] != '?')
623  break;
624  }
625 }
626 
627 /**********************************************************/
628 static const char* XMLStringByTag(XmlKwordBlkPtr xkbp, Int4 tag)
629 {
630  for (; xkbp->str; xkbp++)
631  if (xkbp->tag == tag)
632  break;
633  if (! xkbp->str)
634  return ("???");
635  return (xkbp->str);
636 }
637 
638 /**********************************************************/
639 static bool XMLTagCheck(XmlIndexPtr xip, XmlKwordBlkPtr xkbp)
640 {
641  XmlIndexPtr txip;
642  bool ret = true;
643  for (txip = xip; txip; txip = txip->next) {
644  if (txip->start == 0) {
645  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLMissingStartTag, "XML record's missing start tag for \"%s\" at line %d.", XMLStringByTag(xkbp, txip->tag), txip->end_line);
646  ret = false;
647  }
648  if (txip->end == 0) {
649  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLMissingEndTag, "XML record's missing end tag for \"%s\" at line %d.", XMLStringByTag(xkbp, txip->tag), txip->start_line);
650  ret = false;
651  }
652  if (txip->next && txip->order >= txip->next->order) {
653  ErrPostEx(SEV_ERROR, ERR_FORMAT_LineTypeOrder, "XML tag \"%s\" at line %d is out of order.", XMLStringByTag(xkbp, txip->next->tag), (txip->next->start > 0) ? txip->next->start_line : txip->next->end_line);
654  ret = false;
655  }
656  }
657  return (ret);
658 }
659 
660 /**********************************************************/
661 static bool XMLSameTagsCheck(XmlIndexPtr xip, const char* name)
662 {
663  bool ret = true;
664 
665  for (XmlIndexPtr txip = xip; txip; txip = txip->next) {
666  if (txip->start == 0) {
667  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLMissingStartTag, "XML record's missing start tag for \"%s\" at line %d.", name, txip->end_line);
668  ret = false;
669  }
670  if (txip->end == 0) {
671  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLMissingEndTag, "XML record's missing end tag for \"%s\" at line %d.", name, txip->start_line);
672  ret = false;
673  }
674  }
675  return (ret);
676 }
677 
678 /**********************************************************/
679 static XmlIndexPtr XMLIndexSameSubTags(const char* entry, XmlIndexPtr xip, Int4 tag)
680 {
681  XmlIndexPtr xipsub;
682  XmlIndexPtr txipsub;
683  const char* name;
684  const char* c;
685  char* p;
686  size_t count;
687  Char s[60];
688  Int4 line;
689  Int4 i;
690 
691  if (! entry || ! xip)
692  return nullptr;
693 
694  name = XMLStringByTag(xmsubkwl, tag);
695  if (! name)
696  return nullptr;
697 
698  s[0] = '\0';
699  xipsub = nullptr;
700  txipsub = nullptr;
701  line = xip->start_line;
702  c = entry + xip->start;
703  for (count = xip->start + 1;;) {
704  if (*c != '<') {
705  c++;
706  count++;
707  if (*c == '\0' || count > xip->end)
708  break;
709  if (*c == '\n')
710  line++;
711  }
712  if (*c != '<')
713  continue;
714 
715  for (s[0] = '<', i = 1; i < 50; i++) {
716  c++;
717  count++;
718  if (*c == '\0' || count > xip->end)
719  break;
720  if (*c == '\n')
721  line++;
722  s[i] = *c;
723  if (*c == '<' || *c == '>')
724  break;
725  }
726  if (*c == '\0' || count > xip->end)
727  break;
728  if (*c == '<')
729  continue;
730  s[++i] = '\0';
731  p = s + ((s[1] == '/') ? 2 : 1);
732  if (! StringEqu(p, name + 1))
733  continue;
734 
735  if (! xipsub) {
736  xipsub = XMLIndexNew();
737  txipsub = xipsub;
738  } else if ((s[1] != '/' && txipsub->start != 0) ||
739  (s[1] == '/' && txipsub->end != 0)) {
740  txipsub->next = XMLIndexNew();
741  txipsub = txipsub->next;
742  }
743  if (s[1] == '/') {
744  txipsub->end = count - i;
745  txipsub->end_line = line;
746  } else {
747  txipsub->start = count;
748  txipsub->start_line = line;
749  }
750  txipsub->tag = tag;
751  }
752 
753  if (XMLSameTagsCheck(xipsub, name))
754  return (xipsub);
755 
756  XMLIndexFree(xipsub);
757  return nullptr;
758 }
759 
760 /**********************************************************/
761 static bool XMLAccessionsCheck(ParserPtr pp, IndexblkPtr ibp, const char* entry)
762 {
763  XmlIndexPtr xip;
764  XmlIndexPtr xipsec;
765  string buf;
766  char* p;
767 
768  bool ret = true;
769  size_t len = StringLen(ibp->acnum) + StringLen(XML_FAKE_ACC_TAG);
770 
771  for (xip = ibp->xip; xip; xip = xip->next)
772  if (xip->tag == INSDSEQ_SECONDARY_ACCESSIONS)
773  break;
774 
775  if (! xip) {
776  buf.reserve(len);
777  buf.append(XML_FAKE_ACC_TAG);
778  buf.append(ibp->acnum);
779  ret = GetAccession(pp, buf.c_str(), ibp, 2);
780  return ret;
781  }
782 
783  xip->subtags = XMLIndexSameSubTags(entry, xip, INSDSECONDARY_ACCN);
784  if (! xip->subtags) {
786  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLFormatError, "Incorrectly formatted \"%s\" XML block. Entry dropped.", p);
787  ibp->drop = true;
788  return false;
789  }
790 
791  for (xipsec = xip->subtags; xipsec; xipsec = xipsec->next)
792  len += (xipsec->end - xipsec->start + 1);
793 
794  buf.reserve(len);
795  buf.append(XML_FAKE_ACC_TAG);
796  buf.append(ibp->acnum);
797  for (xipsec = xip->subtags; xipsec; xipsec = xipsec->next) {
798  p = XMLGetTagValue(entry, xipsec);
799  if (p) {
800  buf.append(" ");
801  buf.append(p);
802  MemFree(p);
803  }
804  }
805  ret = GetAccession(pp, buf.c_str(), ibp, 2);
806  return ret;
807 }
808 
809 /**********************************************************/
810 static bool XMLKeywordsCheck(const char* entry, IndexblkPtr ibp, Parser::ESource source)
811 {
812  XmlIndexPtr xip;
813  XmlIndexPtr xipkwd;
814  ValNodePtr vnp;
815  char* p;
816 
817  bool tpa_check = (source == Parser::ESource::EMBL);
818 
819  if (! entry || ! ibp || ! ibp->xip)
820  return true;
821 
822  for (xip = ibp->xip; xip; xip = xip->next)
823  if (xip->tag == INSDSEQ_KEYWORDS)
824  break;
825  if (! xip)
826  return true;
827 
828  xip->subtags = XMLIndexSameSubTags(entry, xip, INSDKEYWORD);
829  if (! xip->subtags) {
831  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLFormatError, "Incorrectly formatted \"%s\" XML block. Entry dropped.", p);
832  ibp->drop = true;
833  return false;
834  }
835 
836  size_t len = 0;
837  for (xipkwd = xip->subtags; xipkwd; xipkwd = xipkwd->next)
838  len += (xipkwd->end - xipkwd->start + 2);
839 
840  string buf;
841  buf.reserve(len);
842  for (xipkwd = xip->subtags; xipkwd; xipkwd = xipkwd->next) {
843  p = XMLGetTagValue(entry, xipkwd);
844  if (p) {
845  if (! buf.empty())
846  buf += "; ";
847  buf += p;
848  MemFree(p);
849  }
850  }
851 
853  check_est_sts_gss_tpa_kwds(vnp, len, ibp, tpa_check, ibp->specialist_db, ibp->inferential, ibp->experimental, ibp->assembly);
854  delete vnp;
855  return true;
856 }
857 
858 /**********************************************************/
859 static bool XMLErrField(Int4 tag)
860 {
861  ErrPostEx(SEV_ERROR, ERR_FORMAT_MissingField, "No %s data in XML format file. Entry dropped.", XMLStringByTag(xmkwl, tag));
862  return false;
863 }
864 
865 /**********************************************************/
867 {
868  XmlIndexPtr xip;
869  bool got_locus = false;
870  bool got_length = false;
871  bool got_moltype = false;
872  bool got_division = false;
873  bool got_update_date = false;
874  bool got_definition = false;
875  bool got_accession = false;
876  bool got_version = false;
877  bool got_source = false;
878  bool got_organism = false;
879  bool got_reference = false;
880  bool got_primary = false;
881  bool got_features = false;
882  bool ret = true;
883 
884  ibp->origin = false;
885  ibp->is_contig = false;
886  for (xip = ibp->xip; xip; xip = xip->next) {
887  if (xip->tag == INSDSEQ_LOCUS && pp->source != Parser::ESource::USPTO)
888  got_locus = true;
889  else if (xip->tag == INSDSEQ_LENGTH)
890  got_length = true;
891  else if (xip->tag == INSDSEQ_MOLTYPE)
892  got_moltype = true;
893  else if (xip->tag == INSDSEQ_DIVISION)
894  got_division = true;
895  else if (xip->tag == INSDSEQ_UPDATE_DATE)
896  got_update_date = true;
897  else if (xip->tag == INSDSEQ_DEFINITION)
898  got_definition = true;
899  else if (xip->tag == INSDSEQ_PRIMARY_ACCESSION)
900  got_accession = true;
901  else if (xip->tag == INSDSEQ_ACCESSION_VERSION)
902  got_version = true;
903  else if (xip->tag == INSDSEQ_SOURCE)
904  got_source = true;
905  else if (xip->tag == INSDSEQ_ORGANISM)
906  got_organism = true;
907  else if (xip->tag == INSDSEQ_REFERENCES)
908  got_reference = true;
909  else if (xip->tag == INSDSEQ_PRIMARY)
910  got_primary = true;
911  else if (xip->tag == INSDSEQ_FEATURE_TABLE)
912  got_features = true;
913  else if (xip->tag == INSDSEQ_CONTIG)
914  ibp->is_contig = true;
915  else if (xip->tag == INSDSEQ_SEQUENCE)
916  ibp->origin = true;
917  }
918 
919  if (got_locus == false && pp->source != Parser::ESource::USPTO)
920  ret = XMLErrField(INSDSEQ_LOCUS);
921  if (got_length == false)
923  if (got_moltype == false)
925  if (got_division == false)
927  if (got_update_date == false && pp->source != Parser::ESource::USPTO)
929  if (got_definition == false)
931  if (got_accession == false) {
932  ErrPostEx(SEV_ERROR, ERR_ACCESSION_NoAccessNum, "No accession number for this record. Entry dropped.");
933  ret = false;
934  }
935  if (got_version == false) {
936  if (pp->accver != false)
938  } else if (pp->source == Parser::ESource::USPTO) {
939  ErrPostEx(SEV_REJECT, ERR_ENTRY_InvalidLineType, "Line type %s is not allowed for USPTO records. Entry dropped.", XMLStringByTag(xmkwl, INSDSEQ_PRIMARY));
940  ret = false;
941  }
942  if (got_source == false)
944  if (got_organism == false)
946  if (got_reference == false && pp->source != Parser::ESource::Flybase &&
947  ibp->is_wgs == false &&
949  ! StringEquN(ibp->acnum, "NW_", 3)))
951  if (got_primary && ibp->is_tpa == false && ibp->tsa_allowed == false) {
952  ErrPostEx(SEV_ERROR, ERR_ENTRY_InvalidLineType, "Line type %s is allowed for TPA or TSA records only. Continue anyway.", XMLStringByTag(xmkwl, INSDSEQ_PRIMARY));
953  }
954  if (got_features == false)
956  if (ibp->is_contig && ibp->segnum != 0) {
957  ErrPostEx(SEV_ERROR, ERR_FORMAT_ContigInSegset, "%s data are not allowed for members of segmented sets. Entry dropped.", XMLStringByTag(xmkwl, INSDSEQ_CONTIG));
958  ret = false;
959  }
960 
961  ibp->is_tpa_wgs_con = (ibp->is_contig && ibp->is_wgs && ibp->is_tpa);
962 
963  return (ret);
964 }
965 
966 /**********************************************************/
967 char* XMLLoadEntry(ParserPtr pp, bool err)
968 {
969  IndexblkPtr ibp;
970  char* entry;
971  char* p;
972  size_t i;
973  Int4 c;
974 
975  if (! pp || ! s_HasInput(*pp)) {
976  return nullptr;
977  }
978 
979  ibp = pp->entrylist[pp->curindx];
980  if (! ibp || ibp->len == 0)
981  return nullptr;
982 
983  entry = MemNew(ibp->len + 1);
984  s_SetPointer(*pp, ibp->offset);
985 
986 
987  for (p = entry, i = 0; i < ibp->len; i++) {
988  c = s_GetCharAndAdvance(*pp);
989  if (c < 0)
990  break;
991  if (c == 13) {
992  c = 10;
993  }
994  if (c > 126 || (c < 32 && c != 10)) {
995  if (err)
996  ErrPostEx(SEV_WARNING, ERR_FORMAT_NonAsciiChar, "None-ASCII character within the record which begins at line %d, decimal value %d, replaced by #.", ibp->linenum, c);
997  *p++ = '#';
998  } else
999  *p++ = (Char)c;
1000  }
1001  if (i != ibp->len) {
1002  MemFree(entry);
1003  return nullptr;
1004  }
1005  *p = '\0';
1006 
1007  return (entry);
1008 }
1009 
1010 
1011 /**********************************************************/
1012 static bool XMLIndexSubTags(const char* entry, XmlIndexPtr xip, XmlKwordBlkPtr xkbp)
1013 {
1014  XmlKwordBlkPtr txkbp;
1015  XmlIndexPtr xipsub;
1016  const char* c;
1017  char* p;
1018  Char s[60];
1019  size_t count;
1020  Int4 line;
1021  Int4 i;
1022 
1023  if (! entry || ! xip)
1024  return false;
1025 
1026  s[0] = '\0';
1027  xipsub = nullptr;
1028  line = xip->start_line;
1029  c = entry + xip->start;
1030  for (count = xip->start + 1;;) {
1031  if (*c != '<') {
1032  c++;
1033  count++;
1034  if (*c == '\0' || count > xip->end)
1035  break;
1036  if (*c == '\n')
1037  line++;
1038  }
1039  if (*c != '<')
1040  continue;
1041 
1042  for (s[0] = '<', i = 1; i < 50; i++) {
1043  c++;
1044  count++;
1045  if (*c == '\0' || count > xip->end)
1046  break;
1047  if (*c == '\n')
1048  line++;
1049  s[i] = *c;
1050  if (*c == '<' || *c == '>')
1051  break;
1052  }
1053  if (*c == '\0' || count > xip->end)
1054  break;
1055  if (*c == '<')
1056  continue;
1057  s[++i] = '\0';
1058  p = s + ((s[1] == '/') ? 2 : 1);
1059  for (txkbp = xkbp; txkbp->str; txkbp++)
1060  if (StringEqu(p, txkbp->str + 1))
1061  break;
1062  if (! txkbp->str)
1063  continue;
1064  if (! xipsub || xipsub->tag != txkbp->tag) {
1065  if (! xipsub) {
1066  xipsub = XMLIndexNew();
1067  xip->subtags = xipsub;
1068  } else {
1069  xipsub->next = XMLIndexNew();
1070  xipsub = xipsub->next;
1071  }
1072  xipsub->tag = txkbp->tag;
1073  xipsub->order = txkbp->order;
1074  if (s[1] == '/') {
1075  xipsub->end = count - i;
1076  xipsub->end_line = line;
1077  } else {
1078  xipsub->start = count;
1079  xipsub->start_line = line;
1080  }
1081  continue;
1082  }
1083  if (s[1] == '/') {
1084  if (xipsub->end != 0) {
1085  xipsub->next = XMLIndexNew();
1086  xipsub = xipsub->next;
1087  xipsub->tag = txkbp->tag;
1088  xipsub->order = txkbp->order;
1089  }
1090  xipsub->end = count - i;
1091  xipsub->end_line = line;
1092  } else {
1093  if (xipsub->start != 0) {
1094  xipsub->next = XMLIndexNew();
1095  xipsub = xipsub->next;
1096  xipsub->tag = txkbp->tag;
1097  xipsub->order = txkbp->order;
1098  }
1099  xipsub->start = count;
1100  xipsub->start_line = line;
1101  }
1102  }
1103 
1104  if (! XMLTagCheck(xip->subtags, xkbp))
1105  return false;
1106 
1107  return true;
1108 }
1109 
1110 /**********************************************************/
1112 {
1113  bool got_key = false;
1114  bool got_location = false;
1115  bool ret = true;
1116 
1117  for (; xip; xip = xip->next) {
1118  if (xip->tag == INSDFEATURE_KEY)
1119  got_key = true;
1120  else if (xip->tag == INSDFEATURE_LOCATION)
1121  got_location = true;
1122  }
1123 
1124  if (! got_key) {
1125  ErrPostEx(SEV_ERROR, ERR_FORMAT_MissingField, "Feature table is missing %s data in XML format file.", XMLStringByTag(xmfeatkwl, INSDFEATURE_KEY));
1126  ret = false;
1127  }
1128 
1129  if (! got_location) {
1130  ErrPostEx(SEV_ERROR, ERR_FORMAT_MissingField, "Feature table is missing %s data in XML format file.", XMLStringByTag(xmfeatkwl, INSDFEATURE_LOCATION));
1131  ret = false;
1132  }
1133  return (ret);
1134 }
1135 
1136 /**********************************************************/
1138 {
1139  bool got_from = false;
1140  bool got_to = false;
1141  bool got_point = false;
1142  bool got_accession = false;
1143  bool ret = true;
1144 
1145  for (; xip; xip = xip->next) {
1146  if (xip->tag == INSDINTERVAL_FROM)
1147  got_from = true;
1148  else if (xip->tag == INSDINTERVAL_TO)
1149  got_to = true;
1150  else if (xip->tag == INSDINTERVAL_POINT)
1151  got_point = true;
1152  else if (xip->tag == INSDINTERVAL_ACCESSION)
1153  got_accession = true;
1154  }
1155 
1156  if (! got_accession) {
1157  ErrPostEx(SEV_ERROR, ERR_FORMAT_MissingField, "Feature's interval block is missing %s data in XML format file.", XMLStringByTag(xmintkwl, INSDINTERVAL_ACCESSION));
1158  ret = false;
1159  }
1160 
1161  if (got_point) {
1162  if (got_from || got_to) {
1164  ret = false;
1165  }
1166  } else if (got_from == false || got_to == false) {
1168  ret = false;
1169  }
1170 
1171  return (ret);
1172 }
1173 
1174 /**********************************************************/
1176 {
1177  for (; xip; xip = xip->next) {
1178  if (xip->tag == INSDQUALIFIER_NAME)
1179  break;
1180  }
1181 
1182  if (xip)
1183  return true;
1184 
1185  ErrPostEx(SEV_ERROR, ERR_FORMAT_MissingField, "Qualifier block is missing %s data in XML format file.", XMLStringByTag(xmqualkwl, INSDQUALIFIER_NAME));
1186  return false;
1187 }
1188 
1189 /**********************************************************/
1190 static bool XMLIndexFeatures(const char* entry, XmlIndexPtr xip)
1191 {
1192  XmlIndexPtr xipfeat;
1193  XmlIndexPtr xipsub;
1194  XmlIndexPtr txip;
1195 
1196  if (! xip || ! entry)
1197  return true;
1198 
1199  for (; xip; xip = xip->next) {
1200  if (xip->tag == INSDSEQ_FEATURE_TABLE)
1201  break;
1202  }
1203 
1204  if (! xip)
1205  return true;
1206 
1207  xip->subtags = XMLIndexSameSubTags(entry, xip, INSDFEATURE);
1208  if (! xip->subtags) {
1209  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLFormatError, "Incorrectly formatted \"%s\" XML block. Entry dropped.", XMLStringByTag(xmkwl, INSDSEQ_FEATURE_TABLE));
1210  return false;
1211  }
1212 
1213  for (xipfeat = xip->subtags; xipfeat; xipfeat = xipfeat->next) {
1214  if (XMLIndexSubTags(entry, xipfeat, xmfeatkwl) == false ||
1215  XMLCheckRequiredFeatTags(xipfeat->subtags) == false)
1216  break;
1217  for (txip = xipfeat->subtags; txip; txip = txip->next) {
1218  if (txip->tag == INSDFEATURE_INTERVALS) {
1219  txip->subtags = XMLIndexSameSubTags(entry, txip, INSDINTERVAL);
1220  if (! txip->subtags)
1221  break;
1222  xipsub = txip->subtags;
1223  for (; xipsub; xipsub = xipsub->next)
1224  if (XMLIndexSubTags(entry, xipsub, xmintkwl) == false ||
1225  XMLCheckRequiredIntTags(xipsub->subtags) == false)
1226  break;
1227  } else if (txip->tag == INSDFEATURE_QUALS) {
1228  txip->subtags = XMLIndexSameSubTags(entry, txip, INSDQUALIFIER);
1229  if (! txip->subtags)
1230  break;
1231  xipsub = txip->subtags;
1232  for (; xipsub; xipsub = xipsub->next)
1233  if (XMLIndexSubTags(entry, xipsub, xmqualkwl) == false ||
1234  XMLCheckRequiredQualTags(xipsub->subtags) == false)
1235  break;
1236  }
1237  }
1238  if (txip)
1239  break;
1240  }
1241 
1242  if (! xipfeat)
1243  return true;
1244 
1245  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLFormatError, "Incorrectly formatted \"%s\" XML block. Entry dropped.", XMLStringByTag(xmkwl, INSDSEQ_FEATURE_TABLE));
1246  return false;
1247 }
1248 
1249 /**********************************************************/
1251 {
1252  bool got_reference = false;
1253  bool got_journal = false;
1254  bool ret = true;
1255 
1256  for (; xip; xip = xip->next) {
1257  if (xip->tag == INSDREFERENCE_REFERENCE)
1258  got_reference = true;
1259  else if (xip->tag == INSDREFERENCE_JOURNAL)
1260  got_journal = true;
1261  }
1262 
1263  if (! got_reference) {
1265  ret = false;
1266  }
1267 
1268  if (! got_journal) {
1270  ret = false;
1271  }
1272  return (ret);
1273 }
1274 
1275 /**********************************************************/
1276 static Int2 XMLGetRefTypePos(char* reftag, size_t bases)
1277 {
1278  if (! reftag || *reftag == '\0')
1279  return (ParFlat_REF_NO_TARGET);
1280 
1281  const string str = "1.." + to_string(bases);
1282  if (StringEqu(reftag, str.c_str()))
1283  return (ParFlat_REF_END);
1284  if (StringEqu(reftag, "sites"))
1285  return (ParFlat_REF_SITES);
1286  return (ParFlat_REF_BTW);
1287 }
1288 
1289 /**********************************************************/
1290 static Int2 XMLGetRefType(char* reftag, size_t bases)
1291 {
1292  char* p;
1293 
1294  if (! reftag)
1295  return (ParFlat_REF_NO_TARGET);
1296 
1297  for (p = reftag; *p != '\0' && *p != '(';)
1298  p++;
1299  if (*p == '\0')
1300  return (ParFlat_REF_NO_TARGET);
1301 
1302  const string str = "(bases 1 to " + to_string(bases) + ")";
1303  const string str1 = "(bases 1 to " + to_string(bases) + ";";
1304 
1305  if (StringStr(p, str.c_str()) || StringStr(p, str1.c_str()))
1306  return (ParFlat_REF_END);
1307  if (StringStr(p, "(sites)"))
1308  return (ParFlat_REF_SITES);
1309  return (ParFlat_REF_BTW);
1310 }
1311 
1312 /**********************************************************/
1314 {
1315  bool got_dbname = false;
1316  bool got_id = false;
1317  bool ret = true;
1318 
1319  for (; xip; xip = xip->next) {
1320  if (xip->tag == INSDXREF_DBNAME)
1321  got_dbname = true;
1322  else if (xip->tag == INSDXREF_ID)
1323  got_id = true;
1324  }
1325 
1326  if (! got_dbname) {
1327  ErrPostEx(SEV_ERROR, ERR_FORMAT_MissingField, "%s block is missing %s data in XML format file.", XMLStringByTag(xmsubkwl, INSDXREF), XMLStringByTag(xmrefkwl, INSDXREF_DBNAME));
1328  ret = false;
1329  }
1330 
1331  if (! got_id) {
1332  ErrPostEx(SEV_ERROR, ERR_FORMAT_MissingField, "%s block is missing %s data in XML format file.", XMLStringByTag(xmsubkwl, INSDXREF), XMLStringByTag(xmrefkwl, INSDXREF_ID));
1333  ret = false;
1334  }
1335  return (ret);
1336 }
1337 
1338 /**********************************************************/
1339 static bool XMLIndexReferences(const char* entry, XmlIndexPtr xip, size_t bases)
1340 {
1341  XmlIndexPtr xipref;
1342  XmlIndexPtr txip;
1343  XmlIndexPtr xipsub;
1344  char* reftagref;
1345  char* reftagpos;
1346 
1347  if (! xip || ! entry)
1348  return true;
1349 
1350  for (; xip; xip = xip->next) {
1351  if (xip->tag == INSDSEQ_REFERENCES)
1352  break;
1353  }
1354  if (! xip)
1355  return true;
1356 
1357  xip->subtags = XMLIndexSameSubTags(entry, xip, INSDREFERENCE);
1358  if (! xip->subtags) {
1359  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLFormatError, "Incorrectly formatted \"%s\" XML block. Entry dropped.", XMLStringByTag(xmkwl, INSDSEQ_REFERENCES));
1360  return false;
1361  }
1362 
1363  for (xipref = xip->subtags; xipref; xipref = xipref->next) {
1364  if (XMLIndexSubTags(entry, xipref, xmrefkwl) == false ||
1365  XMLCheckRequiredRefTags(xipref->subtags) == false)
1366  break;
1367 
1368  reftagref = nullptr;
1369  reftagpos = nullptr;
1370  for (txip = xipref->subtags; txip; txip = txip->next) {
1371  if (txip->tag == INSDREFERENCE_REFERENCE) {
1372  if (reftagref)
1373  MemFree(reftagref);
1374  reftagref = XMLGetTagValue(entry, txip);
1375  continue;
1376  }
1377  if (txip->tag == INSDREFERENCE_POSITION) {
1378  if (reftagpos)
1379  MemFree(reftagpos);
1380  reftagpos = XMLGetTagValue(entry, txip);
1381  continue;
1382  }
1383  if (txip->tag == INSDREFERENCE_AUTHORS) {
1384  txip->subtags = XMLIndexSameSubTags(entry, txip, INSDAUTHOR);
1385  if (! txip->subtags)
1386  break;
1387  } else if (txip->tag == INSDREFERENCE_XREF) {
1388  txip->subtags = XMLIndexSameSubTags(entry, txip, INSDXREF);
1389  if (! txip->subtags)
1390  break;
1391  xipsub = txip->subtags;
1392  for (; xipsub; xipsub = xipsub->next)
1393  if (XMLIndexSubTags(entry, xipsub, xmxrefkwl) == false ||
1394  XMLCheckRequiredXrefTags(xipsub->subtags) == false)
1395  break;
1396  }
1397  }
1398 
1399  if (reftagpos) {
1400  xipref->type = XMLGetRefTypePos(reftagpos, bases);
1401  MemFree(reftagpos);
1402  } else
1403  xipref->type = XMLGetRefType(reftagref, bases);
1404  if (reftagref)
1405  MemFree(reftagref);
1406 
1407  if (txip)
1408  break;
1409  }
1410 
1411  if (! xipref)
1412  return true;
1413 
1414  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLFormatError, "Incorrectly formatted \"%s\" XML block. Entry dropped.", XMLStringByTag(xmkwl, INSDSEQ_REFERENCES));
1415  return false;
1416 }
1417 
1418 /**********************************************************/
1420 {
1421  IndexblkPtr ibp;
1422  char* entry;
1423 
1424  XMLPerformIndex(pp);
1425 
1426  if (pp->indx == 0)
1427  return false;
1428 
1429  pp->curindx = 0;
1430  for (auto ibpp = pp->entrylist.begin(); ibpp != pp->entrylist.end(); ++ibpp, pp->curindx++) {
1431  ibp = *ibpp;
1432  if (ibp->len == 0) {
1433  ErrPostEx(SEV_ERROR, ERR_FORMAT_MissingEnd, "Missing end tag of XML record, which starts at line %d. Entry dropped.", ibp->linenum);
1434  ibp->drop = true;
1435  continue;
1436  }
1437  entry = XMLLoadEntry(pp, true);
1438  if (! entry) {
1439  ErrPostEx(SEV_FATAL, ERR_INPUT_CannotReadEntry, "Failed ro read entry from file, which starts at line %d. Entry dropped.", ibp->linenum);
1440  ibp->drop = true;
1441  continue;
1442  }
1443 
1444  XMLInitialEntry(ibp, entry, pp->accver, pp->source);
1445  if (ibp->drop) {
1446  MemFree(entry);
1447  continue;
1448  }
1449  if (XMLTagCheck(ibp->xip, xmkwl) == false) {
1450  ErrPostEx(SEV_ERROR, ERR_FORMAT_XMLFormatError, "Incorrectly formatted XML record. Entry dropped.");
1451  ibp->drop = true;
1452  MemFree(entry);
1453  continue;
1454  }
1455  if (XMLAccessionsCheck(pp, ibp, entry) == false) {
1456  MemFree(entry);
1457  continue;
1458  }
1459  XMLGetSegment(entry, ibp);
1460  if (XMLCheckRequiredTags(pp, ibp) == false) {
1461  ibp->drop = true;
1462  MemFree(entry);
1463  continue;
1464  }
1465  if (XMLKeywordsCheck(entry, ibp, pp->source) == false) {
1466  MemFree(entry);
1467  continue;
1468  }
1469  if (XMLIndexFeatures(entry, ibp->xip) == false ||
1470  XMLIndexReferences(entry, ibp->xip, ibp->bases) == false) {
1471  ibp->drop = true;
1472  MemFree(entry);
1473  continue;
1474  }
1475  MemFree(entry);
1476  }
1477 
1478  pp->num_drop = 0;
1479  for (auto ibpp = pp->entrylist.begin(); ibpp != pp->entrylist.end(); ++ibpp)
1480  if ((*ibpp)->drop)
1481  pp->num_drop++;
1482 
1483  if (pp->indx > 0)
1484  return true;
1485  return false;
1486 }
1487 
1488 /**********************************************************/
1489 DataBlkPtr XMLBuildRefDataBlk(char* entry, const XmlIndex* xip, int type)
1490 {
1491  XmlIndexPtr txip;
1492  DataBlkPtr dbp;
1493  DataBlkPtr tdbp;
1494 
1495  if (! entry || ! xip)
1496  return nullptr;
1497 
1498  while (xip && xip->tag != INSDSEQ_REFERENCES)
1499  xip = xip->next;
1500  if (! xip || ! xip->subtags)
1501  return nullptr;
1502 
1503  for (dbp = nullptr, txip = xip->subtags; txip; txip = txip->next) {
1504  if (txip->type != type || ! txip->subtags)
1505  continue;
1506  if (! dbp) {
1507  dbp = new DataBlk;
1508  tdbp = dbp;
1509  } else {
1510  tdbp->mpNext = new DataBlk;
1511  tdbp = tdbp->mpNext;
1512  }
1513  tdbp->mType = txip->type;
1514  tdbp->mOffset = entry;
1515  tdbp->mpData = txip->subtags;
1516  tdbp->mpNext = nullptr;
1517  }
1518  return (dbp);
1519 }
1520 
1521 /**********************************************************/
1522 void XMLGetKeywords(const char* entry, const XmlIndex* xip, TKeywordList& keywords)
1523 {
1524  XmlIndexPtr xipkwd;
1525  char* p;
1526 
1527  keywords.clear();
1528  if (! entry || ! xip)
1529  return;
1530 
1531  for (; xip; xip = xip->next)
1532  if (xip->tag == INSDSEQ_KEYWORDS && xip->subtags)
1533  break;
1534  if (! xip)
1535  return;
1536 
1537  for (xipkwd = xip->subtags; xipkwd; xipkwd = xipkwd->next) {
1538  p = XMLGetTagValue(entry, xipkwd);
1539  if (! p)
1540  continue;
1541 
1542  keywords.push_back(p);
1543  MemFree(p);
1544  }
1545 }
1546 
1547 /**********************************************************/
1548 char* XMLConcatSubTags(const char* entry, const XmlIndex* xip, Int4 tag, Char sep)
1549 {
1550  XmlIndexPtr txip;
1551  char* buf;
1552  const char* p;
1553  char* q;
1554  size_t i;
1555 
1556  if (! entry || ! xip)
1557  return nullptr;
1558 
1559  while (xip && xip->tag != tag)
1560  xip = xip->next;
1561 
1562  if (! xip || ! xip->subtags)
1563  return nullptr;
1564 
1565  for (i = 0, txip = xip->subtags; txip; txip = txip->next)
1566  i += (txip->end - txip->start + 2);
1567 
1568  buf = MemNew(i);
1569  buf[0] = '\0';
1570  for (q = buf, txip = xip->subtags; txip; txip = txip->next) {
1571  if (txip->end <= txip->start)
1572  continue;
1573  if (buf[0] != '\0') {
1574  *q++ = sep;
1575  *q++ = ' ';
1576  }
1577  for (i = txip->start, p = entry + txip->start; i < txip->end; i++)
1578  *q++ = *p++;
1579  *q = '\0';
1580  }
1582  return (buf);
1583 }
1584 
void XMLIndexFree(XmlIndexPtr xip)
Definition: block.cpp:130
char * mOffset
Definition: ftablock.h:332
CFlatFileData * mpData
Definition: ftablock.h:331
DataBlk * mpNext
Definition: ftablock.h:336
int mType
Definition: ftablock.h:330
#define ERR_FORMAT_LineTypeOrder
Definition: flat2err.h:40
#define ERR_FORMAT_MissingEnd
Definition: flat2err.h:39
#define INSDXREF_DBNAME
Definition: fta_xml.h:101
#define INSDAUTHOR
Definition: fta_xml.h:103
#define INSDSEQ_ACCESSION_VERSION
Definition: fta_xml.h:55
#define INSDSEQ_OTHER_SEQIDS
Definition: fta_xml.h:56
#define INSDSEQ_TOPOLOGY
Definition: fta_xml.h:46
#define INSDSEQ_START
Definition: fta_xml.h:39
#define INSDREFERENCE_REMARK
Definition: fta_xml.h:98
#define INSDINTERVAL
Definition: fta_xml.h:81
#define INSDSEQ_PRIMARY_ACCESSION
Definition: fta_xml.h:53
#define INSDSEQ_UPDATE_RELEASE
Definition: fta_xml.h:50
#define INSDINTERVAL_POINT
Definition: fta_xml.h:84
#define INSDSEQ_MOLTYPE
Definition: fta_xml.h:45
#define INSDSEQ_DEFINITION
Definition: fta_xml.h:52
#define INSDINTERVAL_TO
Definition: fta_xml.h:83
#define INSDINTERVAL_FROM
Definition: fta_xml.h:82
#define INSDQUALIFIER_NAME
Definition: fta_xml.h:87
#define INSDSEQ_CREATE_RELEASE
Definition: fta_xml.h:51
#define INSDSEQ_STRANDEDNESS
Definition: fta_xml.h:44
#define INSDREFERENCE_PUBMED
Definition: fta_xml.h:97
#define INSDSEQ_FEATURE_TABLE
Definition: fta_xml.h:68
#define INSDSEQ_COMMENT
Definition: fta_xml.h:64
#define INSDSEQ_ORGANISM
Definition: fta_xml.h:61
#define INSDREFERENCE
Definition: fta_xml.h:89
#define INSDFEATURE_LOCATION
Definition: fta_xml.h:78
#define INSDREFERENCE_AUTHORS
Definition: fta_xml.h:92
#define INSDREFERENCE_XREF
Definition: fta_xml.h:99
#define INSDQUALIFIER_VALUE
Definition: fta_xml.h:88
#define INSDSEQ_SEGMENT
Definition: fta_xml.h:59
#define INSDSEQ_REFERENCES
Definition: fta_xml.h:63
#define INSDSEQ_SECONDARY_ACCESSIONS
Definition: fta_xml.h:57
#define INSDFEATURE_KEY
Definition: fta_xml.h:77
#define INSDKEYWORD
Definition: fta_xml.h:75
#define INSDREFERENCE_POSITION
Definition: fta_xml.h:91
#define INSDSEQ_SOURCE_DB
Definition: fta_xml.h:66
#define INSDXREF_ID
Definition: fta_xml.h:102
#define INSDSEQ_LOCUS
Definition: fta_xml.h:42
#define INSDREFERENCE_TITLE
Definition: fta_xml.h:94
#define INSDSEQ_END
Definition: fta_xml.h:40
#define INSDSECONDARY_ACCN
Definition: fta_xml.h:74
#define INSDSEQ_KEYWORDS
Definition: fta_xml.h:58
#define INSDFEATURE_QUALS
Definition: fta_xml.h:80
#define INSDINTERVAL_ACCESSION
Definition: fta_xml.h:85
#define INSDSEQ_DATABASE_REFERENCE
Definition: fta_xml.h:67
#define INSDXREF
Definition: fta_xml.h:100
#define INSDSEQ_TAXONOMY
Definition: fta_xml.h:62
#define INSDSEQ_SEQUENCE
Definition: fta_xml.h:69
#define INSDSEQ_ENTRY_VERSION
Definition: fta_xml.h:54
#define INSDSEQ_CREATE_DATE
Definition: fta_xml.h:49
#define INSDFEATURE_INTERVALS
Definition: fta_xml.h:79
#define INSDSEQ_LENGTH
Definition: fta_xml.h:43
#define INSDSEQ_DIVISION
Definition: fta_xml.h:47
#define INSDREFERENCE_JOURNAL
Definition: fta_xml.h:95
#define INSDSEQ_UPDATE_DATE
Definition: fta_xml.h:48
#define INSDSEQ_SOURCE
Definition: fta_xml.h:60
#define INSDREFERENCE_MEDLINE
Definition: fta_xml.h:96
#define INSDREFERENCE_CONSORTIUM
Definition: fta_xml.h:93
#define INSDSEQ_CONTIG
Definition: fta_xml.h:70
#define INSDQUALIFIER
Definition: fta_xml.h:86
#define INSDREFERENCE_REFERENCE
Definition: fta_xml.h:90
#define INSDSEQ_PRIMARY
Definition: fta_xml.h:65
#define INSDFEATURE
Definition: fta_xml.h:76
std::list< std::string > TKeywordList
Definition: ftablock.h:166
bool StringEquN(const char *s1, const char *s2, size_t n)
Definition: ftacpp.hpp:106
bool StringEqu(const char *s1, const char *s2)
Definition: ftacpp.hpp:96
void StringCpy(char *d, const char *s)
Definition: ftacpp.hpp:74
void StringNCpy(char *d, const char *s, size_t n)
Definition: ftacpp.hpp:75
void MemFree(char *p)
Definition: ftacpp.hpp:55
size_t StringLen(const char *s)
Definition: ftacpp.hpp:60
char * MemNew(size_t sz)
Definition: ftacpp.hpp:43
char * StringRChr(char *s, const char c)
Definition: ftacpp.hpp:78
void FtaInstallPrefix(int prefix, const char *name, const char *location)
Definition: ftaerr.cpp:319
#define PREFIX_LOCUS
Definition: ftaerr.hpp:15
#define PREFIX_ACCESSION
Definition: ftaerr.hpp:14
#define SEV_WARNING
Definition: gicache.c:90
#define SEV_ERROR
Definition: gicache.c:91
#define SEV_FATAL
Definition: gicache.c:93
#define SEV_REJECT
Definition: gicache.c:92
#define StringStr
Definition: ncbistr.hpp:322
#define Char
Definition: ncbistd.hpp:124
#define ErrPostEx(sev, err_code,...)
Definition: ncbierr.hpp:78
int16_t Int2
2-byte (16-bit) signed integer
Definition: ncbitype.h:100
int32_t Int4
4-byte (32-bit) signed integer
Definition: ncbitype.h:102
char Char
Alias for char.
Definition: ncbitype.h:93
uint16_t Uint2
2-byte (16-bit) unsigned integer
Definition: ncbitype.h:101
#define END_NCBI_SCOPE
End previously defined NCBI scope.
Definition: ncbistl.hpp:103
#define BEGIN_NCBI_SCOPE
Define ncbi namespace.
Definition: ncbistl.hpp:100
static int CompareNocase(const CTempString s1, SIZE_TYPE pos, SIZE_TYPE n, const char *s2)
Case-insensitive compare of a substring with another string.
Definition: ncbistr.cpp:219
@ ParFlat_REF_BTW
Definition: index.h:61
@ ParFlat_REF_NO_TARGET
Definition: index.h:63
@ ParFlat_REF_SITES
Definition: index.h:62
@ ParFlat_REF_END
Definition: index.h:60
CRef< CDate_std > GetUpdateDate(const char *ptr, Parser::ESource source)
Definition: indx_blk.cpp:611
#define ERR_FORMAT_XMLMissingStartTag
Definition: indx_err.h:52
#define ERR_VERSION_NonDigitVerNum
Definition: indx_err.h:83
#define ERR_FORMAT_XMLInvalidINSDInterval
Definition: indx_err.h:55
#define ERR_VERSION_MissingVerNum
Definition: indx_err.h:82
#define ERR_ACCESSION_NoAccessNum
Definition: indx_err.h:68
#define ERR_SEGMENT_BadLocusName
Definition: indx_err.h:78
#define ERR_FORMAT_ContigInSegset
Definition: indx_err.h:47
#define ERR_FORMAT_XMLFormatError
Definition: indx_err.h:54
#define ERR_FORMAT_UnexpectedEnd
Definition: indx_err.h:51
#define ERR_INPUT_CannotReadEntry
Definition: indx_err.h:100
#define ERR_SEGMENT_IncompSeg
Definition: indx_err.h:79
#define ERR_FORMAT_XMLMissingEndTag
Definition: indx_err.h:53
#define ERR_VERSION_BadVersionLine
Definition: indx_err.h:85
#define ERR_VERSION_InvalidVersion
Definition: indx_err.h:88
#define ERR_FORMAT_MissingField
Definition: indx_err.h:42
#define ERR_FORMAT_NonAsciiChar
Definition: indx_err.h:40
#define ERR_ENTRY_InvalidLineType
Definition: indx_err.h:64
#define ERR_VERSION_AccessionsDontMatch
Definition: indx_err.h:84
@ e_not_set
char * buf
int i
int len
const CharType(& source)[N]
Definition: pointer.h:1149
const char * tag
const CConstRef< CSeq_id > GetAccession(const CSeq_id_Handle &id_handle)
int offset
Definition: replacements.h:160
static const char * str(char *buf, int n)
Definition: stats.c:84
Indexblk * ibp
Definition: indx_blk.h:56
IndBlkNode * next
Definition: indx_blk.h:57
Char acnum[200]
Definition: ftablock.h:169
Char division[4]
Definition: ftablock.h:174
bool assembly
Definition: ftablock.h:244
bool tsa_allowed
Definition: ftablock.h:214
Char blocusname[200]
Definition: ftablock.h:181
CRef< objects::CDate_std > date
Definition: ftablock.h:190
bool is_tpa_wgs_con
Definition: ftablock.h:212
Int2 vernum
Definition: ftablock.h:170
bool is_tpa
Definition: ftablock.h:209
bool is_prot
Definition: ftablock.h:225
bool is_wgs
Definition: ftablock.h:208
bool origin
Definition: ftablock.h:204
bool is_contig
Definition: ftablock.h:200
bool STS
Definition: ftablock.h:196
bool is_pat
Definition: ftablock.h:205
bool HTC
Definition: ftablock.h:198
bool drop
Definition: ftablock.h:185
bool experimental
Definition: ftablock.h:250
size_t bases
Definition: ftablock.h:175
bool inferential
Definition: ftablock.h:248
Uint2 segtotal
Definition: ftablock.h:178
bool EST
Definition: ftablock.h:195
size_t linenum
Definition: ftablock.h:183
size_t len
Definition: ftablock.h:187
size_t offset
Definition: ftablock.h:171
bool specialist_db
Definition: ftablock.h:246
Uint2 segnum
Definition: ftablock.h:176
Char locusname[200]
Definition: ftablock.h:173
XmlIndexPtr xip
Definition: ftablock.h:220
bool GSS
Definition: ftablock.h:197
vector< IndexblkPtr > entrylist
TokenBlk * next
Definition: ftablock.h:135
char * str
Definition: ftablock.h:134
TokenBlk * list
Definition: ftablock.h:140
Int2 type
Definition: ftablock.h:159
size_t start
Definition: ftablock.h:155
XmlIndex * next
Definition: ftablock.h:161
Int4 end_line
Definition: ftablock.h:158
Int4 start_line
Definition: ftablock.h:157
XmlIndex * subtags
Definition: ftablock.h:160
size_t end
Definition: ftablock.h:156
Int4 tag
Definition: ftablock.h:153
Int4 order
Definition: ftablock.h:154
const char * str
Definition: xm_index.cpp:56
Int4 order
Definition: xm_index.cpp:57
Definition: type.c:6
void check_est_sts_gss_tpa_kwds(ValNodePtr kwds, size_t len, IndexblkPtr entry, bool tpa_check, bool &specialist_db, bool &inferential, bool &experimental, bool &assembly)
Definition: utilfun.cpp:1516
TokenStatBlkPtr TokenString(char *str, Char delimiter)
Definition: utilfun.cpp:489
void FreeTokenstatblk(TokenStatBlkPtr tsbp)
Definition: utilfun.cpp:542
ValNodePtr ConstructValNode(CSeq_id::E_Choice choice, const char *data)
Definition: utilfun.cpp:1582
static bool XMLKeywordsCheck(const char *entry, IndexblkPtr ibp, Parser::ESource source)
Definition: xm_index.cpp:810
static bool XMLTagCheck(XmlIndexPtr xip, XmlKwordBlkPtr xkbp)
Definition: xm_index.cpp:639
static bool XMLIndexReferences(const char *entry, XmlIndexPtr xip, size_t bases)
Definition: xm_index.cpp:1339
static void XMLRestoreSpecialCharacters(char *buf)
Definition: xm_index.cpp:169
DataBlkPtr XMLBuildRefDataBlk(char *entry, const XmlIndex *xip, int type)
Definition: xm_index.cpp:1489
char * XMLFindTagValue(const char *entry, const XmlIndex *xip, Int4 tag)
Definition: xm_index.cpp:213
static Int2 XMLGetRefTypePos(char *reftag, size_t bases)
Definition: xm_index.cpp:1276
char * XMLGetTagValue(const char *entry, const XmlIndex *xip)
Definition: xm_index.cpp:197
static bool XMLCheckRequiredFeatTags(XmlIndexPtr xip)
Definition: xm_index.cpp:1111
XmlKwordBlk xmrefkwl[]
Definition: xm_index.cpp:112
static bool XMLCheckRequiredRefTags(XmlIndexPtr xip)
Definition: xm_index.cpp:1250
XmlKwordBlk xmkwl[]
Definition: xm_index.cpp:63
XmlKwordBlk xmfeatkwl[]
Definition: xm_index.cpp:96
static bool XMLCheckRequiredIntTags(XmlIndexPtr xip)
Definition: xm_index.cpp:1137
XmlKwordBlk xmqualkwl[]
Definition: xm_index.cpp:126
void XMLGetKeywords(const char *entry, const XmlIndex *xip, TKeywordList &keywords)
Definition: xm_index.cpp:1522
static void XMLGetSegment(const char *entry, IndexblkPtr ibp)
Definition: xm_index.cpp:269
static const char * XMLStringByTag(XmlKwordBlkPtr xkbp, Int4 tag)
Definition: xm_index.cpp:628
bool XMLIndex(ParserPtr pp)
Definition: xm_index.cpp:1419
static void XMLParseVersion(IndexblkPtr ibp, char *line)
Definition: xm_index.cpp:475
static XmlIndexPtr XMLIndexSameSubTags(const char *entry, XmlIndexPtr xip, Int4 tag)
Definition: xm_index.cpp:679
XmlKwordBlk xmintkwl[]
Definition: xm_index.cpp:104
static int s_GetCharAndAdvance(Parser &config)
Definition: xm_index.cpp:317
static Int2 XMLGetRefType(char *reftag, size_t bases)
Definition: xm_index.cpp:1290
static bool XMLCheckRequiredQualTags(XmlIndexPtr xip)
Definition: xm_index.cpp:1175
static bool XMLCheckRequiredTags(ParserPtr pp, IndexblkPtr ibp)
Definition: xm_index.cpp:866
static bool XMLAccessionsCheck(ParserPtr pp, IndexblkPtr ibp, const char *entry)
Definition: xm_index.cpp:761
static void XMLPerformIndex(ParserPtr pp)
Definition: xm_index.cpp:331
#define XML_FAKE_ACC_TAG
Definition: xm_index.cpp:51
char * XMLLoadEntry(ParserPtr pp, bool err)
Definition: xm_index.cpp:967
XmlKwordBlk xmsubkwl[]
Definition: xm_index.cpp:138
static bool XMLSameTagsCheck(XmlIndexPtr xip, const char *name)
Definition: xm_index.cpp:661
static XmlIndexPtr XMLIndexNew(void)
Definition: xm_index.cpp:152
static bool XMLDelSegnum(IndexblkPtr ibp, const char *segnum, size_t len2)
Definition: xm_index.cpp:224
static bool XMLIndexSubTags(const char *entry, XmlIndexPtr xip, XmlKwordBlkPtr xkbp)
Definition: xm_index.cpp:1012
static bool XMLCheckRequiredXrefTags(XmlIndexPtr xip)
Definition: xm_index.cpp:1313
static bool XMLIndexFeatures(const char *entry, XmlIndexPtr xip)
Definition: xm_index.cpp:1190
void s_SetPointer(Parser &config, size_t offset)
Definition: xm_index.cpp:325
XmlKwordBlk xmxrefkwl[]
Definition: xm_index.cpp:132
static void XMLInitialEntry(IndexblkPtr ibp, const char *entry, bool accver, Parser::ESource source)
Definition: xm_index.cpp:524
char * XMLConcatSubTags(const char *entry, const XmlIndex *xip, Int4 tag, Char sep)
Definition: xm_index.cpp:1548
static bool s_HasInput(const Parser &config)
Definition: xm_index.cpp:311
static bool XMLErrField(Int4 tag)
Definition: xm_index.cpp:859
Modified on Sat Dec 09 04:46:36 2023 by modify_doxy.py rev. 669887