1 /* @source ajnam **************************************************************
2 **
3 ** AJAX nam functions
4 **
5 ** Creates a hash table of initial values and allow access to this
6 ** via the routines ajNamDatabase and ajNamGetValueS.
7 **
8 ** @author Copyright (C) 1998 Ian Longden
9 ** @version $Revision: 1.190 $
10 ** @modified 2000-2011 Peter Rice
11 ** @modified $Date: 2013/01/24 15:31:46 $ by $Author: rice $
12 ** @@
13 **
14 ** This library is free software; you can redistribute it and/or
15 ** modify it under the terms of the GNU Lesser General Public
16 ** License as published by the Free Software Foundation; either
17 ** version 2.1 of the License, or (at your option) any later version.
18 **
19 ** This library is distributed in the hope that it will be useful,
20 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
21 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
22 ** Lesser General Public License for more details.
23 **
24 ** You should have received a copy of the GNU Lesser General Public
25 ** License along with this library; if not, write to the Free Software
26 ** Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
27 ** MA  02110-1301,  USA.
28 **
29 ******************************************************************************/
30 
31 #include "ajlib.h"
32 
33 #include "ajnam.h"
34 #include "ajsys.h"
35 #include "ajfileio.h"
36 #include "ajquery.h"
37 #include "ajreg.h"
38 #include "ajtagval.h"
39 #include "ajassemread.h"
40 #include "ajfeatread.h"
41 #include "ajoboread.h"
42 #include "ajrefseqread.h"
43 #include "ajresourceread.h"
44 #include "ajseqread.h"
45 #include "ajtaxread.h"
46 #include "ajtextread.h"
47 #include "ajurlread.h"
48 #include "ajvarread.h"
49 #include "ajxmlread.h"
50 
51 #ifndef WIN32
52 #include <dirent.h>
53 #include <unistd.h>
54 #else /* !WIN32 */
55 #include "win32.h"
56 #include <winsock2.h>
57 #include <stdlib.h>
58 #endif /* WIN32 */
59 
60 #ifdef HAVE_MCHECK
61 #include <mcheck.h>
62 #endif /* ! HAVE_MCHECK */
63 
64 
65 enum NamEType
66 {
67     TYPE_UNKNOWN,			/* no type set */
68     TYPE_ENV,				/* env or set variable */
69     TYPE_SVR,				/* server definition */
70     TYPE_DB,				/* database definition */
71     TYPE_RESOURCE,			/* resource definition */
72     TYPE_IFILE,				/* include filename */
73     TYPE_ALIAS,				/* database alias */
74     TYPE_SVRDB,				/* server:database table */
75     TYPE_SVRALI,                        /* server:alias table */
76     TYPE_IF,
77     TYPE_IFDEF,
78     TYPE_ELSE,
79     TYPE_ENDIF,
80     TYPE_MAX
81 };
82 
83 enum NamEAttrtype
84 {
85     ATTR_UNKNOWN,			/* no type set */
86     ATTR_STR,				/* string */
87     ATTR_BOOL,				/* boolean */
88     ATTR_LIST,				/* list of strings */
89 };
90 
91 const char* namTypes[] = { "unknown", "SET",
92                            "SERVER", "DBNAME", "RESOURCE",
93                            "INCLUDE", "ALIAS",
94                            "SERVER:DB", "SERVER:ALIAS",
95                            "IF", "ELSE", "ENDIF",
96                            "MAX"
97 };
98 
99 #define NAM_INCLUDE_ESTIMATE 5	/* estimate of maximum number of include */
100                                 /* statements in emboss.default          */
101 
102 /* Scope values for entry methods returned from name*Method2Scope */
103 #define SLOW_ENTRY 8
104 #define SLOW_QUERY 16
105 
106 static AjBool namDoDebug  = AJFALSE;
107 static AjBool namDoValid  = AJFALSE;
108 static AjBool namDoHomeRc = AJTRUE;
109 static AjPStr namRootStr  = NULL;
110 static AjPStr namStandardFilename = NULL;
111 static AjPStr namStandardDir = NULL;
112 static AjPStr namUserDir = NULL;
113 static AjPStr namUserFilename = NULL;
114 static AjPStr namValNameTmp  = NULL;
115 
116 static AjBool namListParseOK = AJFALSE;
117 
118 static ajuint namIfBlock = 0;
119 static AjBool namIfNow = AJTRUE;
120 
121 static AjPList namIfList = NULL;
122 static AjBool *namIfValue;
123 static AjBool namTrue = AJTRUE;
124 static AjBool namFalse = AJFALSE;
125 
126 /* source directory where control and data files can be found */
127 
128 #ifdef AJAX_FIXED_ROOT
129 static char namFixedRoot[] = AJAX_FIXED_ROOT;
130 #else
131 static char namFixedRoot[] = "/nfs/WWW/data/EMBOSS";
132 #endif
133 
134 /* install target directory where installed control and data files can
135    be found  - this is the --prefix= from ./configure */
136 
137 #ifdef PREFIX
138 static char namInstallRoot[] = PREFIX;
139 #else
140 #ifndef WIN32
141 static char namInstallRoot[] = "/usr/local";
142 #else
143 static char namInstallRoot[MAX_PATH];
144 #endif
145 #endif
146 
147 /* package name from the makefile */
148 
149 #ifdef PACKAGE
150 static char namPackage[] = PACKAGE;
151 #else
152 static char namPackage[] = "EMBOSS";
153 #endif
154 
155 #ifdef VERSION
156 static char namVersion[] = VERSION;
157 #else
158 static char namVersion[] = "6.x.x";
159 #endif
160 
161 #ifdef AJAX_SYSTEM
162 static char namSystem[] = AJAX_SYSTEM;
163 #else
164 #ifdef WIN32
165 static char namSystem[] = "windows";
166 #else
167 static char namSystem[] = "unknown";
168 #endif
169 #endif
170 
171 /* string versions of char* constants set in ajNamInit */
172 static AjPStr namFixedBaseStr     = NULL;
173 static AjPStr namFixedRootStr     = NULL;
174 static AjPStr namFixedInstallStr  = NULL;
175 static AjPStr namFixedPackageStr  = NULL;
176 static AjPStr namFixedSystemStr  = NULL;
177 static AjPStr namFixedVersionStr  = NULL;
178 static AjPStr namPrefixStr        = NULL;
179 static AjPStr namFileOrig         = NULL;
180 
181 static AjPTable namDbTypeTable = NULL;
182 static AjPTable namAliasMasterTable = NULL;
183 static AjPTable namVarMasterTable = NULL;
184 static AjPTable namSvrMasterTable = NULL;
185 static AjPTable namDbMasterTable = NULL;
186 static AjPTable namResMasterTable = NULL;
187 static AjPTable namSvrAttrTable = NULL;
188 static AjPTable namDbAttrTable = NULL;
189 static AjPTable namResAttrTable = NULL;
190 static AjPTable namSvrDatabaseTable = NULL;
191 static AjPTable namSvrAliasTable = NULL;
192 static ajint namParseType      = 0;
193 static AjPStr namFileName      = NULL;
194 static ajint namLine           = 0;
195 static ajint namErrorCount     = 0;
196 
197 static AjPRegexp namNameExp = NULL;
198 static AjPRegexp namVarExp  = NULL;
199 
200 
201 static AjPStr namCmpStr = NULL;
202 
203 /* @datastatic NamPAttr *******************************************************
204 **
205 ** Resource attribute definition structure
206 **
207 ** @alias NamSAttr
208 ** @alias NamOAttr
209 **
210 ** @attr Name [const char*] Attribute name
211 ** @attr Type [enum NamEAttrtype] Type of value
212 ** @attr Defval [const char*] Default value, usually an empty string
213 ** @attr Comment [const char*] Comment for documentation purposes
214 ** @@
215 ******************************************************************************/
216 
217 typedef struct NamSAttr
218 {
219     const char* Name;
220     enum NamEAttrtype Type;
221     const char* Defval;
222     const char* Comment;
223 } NamOAttr;
224 
225 #define NamPAttr NamOAttr*
226 
227 
228 
229 
230 /* @datastatic NamPValid ******************************************************
231 **
232 ** Resource attribute validation structure
233 **
234 ** @alias NamSValid
235 ** @alias NamOValid
236 **
237 ** @attr Name [const char*] Attribute name
238 ** @attr Comment [const char*] Comment for documentation purposes
239 ** @@
240 ******************************************************************************/
241 
242 typedef struct NamSValid
243 {
244     const char* Name;
245     const char* Comment;
246 } NamOValid;
247 
248 #define NamPValid NamOValid*
249 
250 
251 
252 
253 /* @datastatic NamPType ******************************************************
254 **
255 ** Resource attribute validation structure
256 **
257 ** @alias NamSType
258 ** @alias NamOType
259 **
260 ** @attr Name [const char*] Type name
261 ** @attr Scope [const char*] Type scope
262 ** @attr Comment [const char*] Comment for documentation purposes
263 ** @attr DataType [ajuint] Enumerated datatype matching scope
264 ** @@
265 ******************************************************************************/
266 
267 typedef struct NamSType
268 {
269     const char* Name;
270     const char* Scope;
271     const char* Comment;
272     ajuint DataType;
273 } NamOType;
274 
275 #define NamPType NamOType*
276 
277 
278 
279 
280 NamOAttr namSvrAttrs[] =
281 {
282     {"method", ATTR_STR, "",
283      "access method (required, at some level)"},
284     {"type", ATTR_STR, "",
285      "database type(s) 'Nucleotide', 'Protein', etc (required)"},
286     {"cachedirectory", ATTR_STR, "",
287      "cache directory name"},
288     {"cachefile", ATTR_STR, "", "cache file name"},
289 
290     {"accession", ATTR_STR, "",
291      "secondary identifier field"},
292     {"app", ATTR_STR, "",
293      "external application commandline (APP, EXTERNAL)"},
294     {"appall", ATTR_STR, "",
295      "external commandline for 'methodall' (APP, EXTERNAL)"},
296     {"appentry", ATTR_STR, "",
297      "external commandline for 'methodentry' (APP, EXTERNAL)"},
298     {"appquery", ATTR_STR, "",
299      "external commandline for 'methodquery' (APP, EXTERNAL)"},
300 
301     {"caseidmatch", ATTR_BOOL, "N",
302      "match exact case of entry identifier"},
303     {"comment", ATTR_STR, "",
304      "text comment for the server definition"},
305     {"directory", ATTR_STR, "",
306      "data directory"},
307 /*    {"exclude", ATTR_STR, "",
308       "wildcard filenames to exclude from 'filename'"},*/
309     {"field", ATTR_LIST, "",
310      "database query field, with altnames and description"},
311     {"filters", ATTR_STR, "",
312      "database query filters to apply to all retrievals"},
313 /*    {"filename", "",
314       "(wildcard) database filename"},*/
315 
316     {"format", ATTR_STR, "",
317      "database entry format(s)"},
318     {"formatall", ATTR_STR, "",
319      "database entry format(s) for 'methodall' access"},
320     {"formatentry", ATTR_STR, "",
321      "database entry format(s) for 'methodentry' access"},
322     {"formatquery", ATTR_STR, "",
323      "database query format(s) for 'methodquery' access"},
324 
325     {"hasaccession", ATTR_BOOL, "Y",
326      "database has an acc field as an alternate id"},
327     {"httpversion", ATTR_STR, "",
328      "HTTP version for GET requests"},
329     {"identifier", ATTR_STR, "",
330      "standard identifier field"},
331     {"indexdirectory", ATTR_STR, "",
332      "Index directory, defaults to data 'directory'"},
333 
334     {"methodall", ATTR_STR, "",
335      "access method for all entries"},
336     {"methodentry", ATTR_STR, "",
337      "access method for single entry"},
338     {"methodquery", ATTR_STR, "",
339      "access method for query (several entries)"},
340 
341     {"proxy", ATTR_STR, "",
342      "http proxy server, or ':' to cancel a global proxy "},
343     {"query", ATTR_STR, "",
344      "database query (SQL, SPARQL, etc.)"},
345 /*    {"release", ATTR_STR, "",
346       "release of the database, comment only"},*/
347     {"return", ATTR_STR, "",
348      "names fields to be returned"},
349     {"sequence", ATTR_STR, "",
350      "sequence field to be returned"},
351     {"serverversion", ATTR_STR, "",
352      "Version of database server"},
353     {"special", ATTR_LIST, "",
354      "name:value attributes for access method"},
355     {"url", ATTR_STR, "",
356      "Basic URL for data access"},
357     {"view", ATTR_STR, "",
358      "Access method view"},
359 
360     {"edamdat", ATTR_LIST, "",
361      "EDAM datatype term references"},
362     {"edamfmt", ATTR_LIST, "",
363      "EDAM format term references"},
364     {"edamid", ATTR_LIST, "",
365      "EDAM identifier term references"},
366     {"edamtpc", ATTR_LIST, "",
367      "EDAM topic term references"},
368     {"taxon", ATTR_LIST, "",
369      "taxon id and name"},
370 
371     {NULL, ATTR_UNKNOWN, NULL,
372      NULL}
373 };
374 
375 NamOAttr namDbAttrs[] =
376 {
377     {"format", ATTR_STR, "",
378      "database entry format(s) (required, at some level)"},
379     {"method", ATTR_STR, "",
380      "access method (required, at some level)"},
381     {"type", ATTR_STR, "",
382      "database type(s) 'Nucleotide', 'Protein', etc (required)"},
383 
384     {"accession", ATTR_STR, "",
385      "secondary identifier field"},
386     {"app", ATTR_STR, "",
387      "external application commandline (APP, EXTERNAL)"},
388     {"appall", ATTR_STR, "",
389      "external commandline for 'methodall' (APP, EXTERNAL)"},
390     {"appentry", ATTR_STR, "",
391      "external commandline for 'methodentry' (APP, EXTERNAL)"},
392     {"appquery", ATTR_STR, "",
393      "external commandline for 'methodquery' (APP, EXTERNAL)"},
394 
395     {"caseidmatch", ATTR_BOOL, "N",
396      "match exact case of entry identifier"},
397     {"comment", ATTR_STR, "",
398      "text comment for the DB definition"},
399     {"dbalias", ATTR_STR, "",
400      "database name(s) to be used by access method if different"},
401     {"directory", ATTR_STR, "",
402      "data directory"},
403     {"example", ATTR_LIST, "",
404      "example identifier"},
405     {"exclude", ATTR_STR, "",
406      "wildcard filenames to exclude from 'filename'"},
407     {"field", ATTR_LIST, "",
408      "database query field, with altnames and description"},
409     {"fields", ATTR_STR, "",
410      "extra database query fields, ID and ACC are standard"},
411     {"filters", ATTR_STR, "",
412      "database query filters to apply to all retrievals"},
413     {"filename", ATTR_STR, "",
414      "(wildcard) database filename"},
415 
416     {"formatall", ATTR_STR, "",
417      "database entry format(s) for 'methodall' access"},
418     {"formatentry", ATTR_STR, "",
419      "database entry format(s) for 'methodentry' access"},
420     {"formatquery", ATTR_STR, "",
421      "database query format(s) for 'methodquery' access"},
422 
423     {"hasaccession", ATTR_BOOL, "Y",
424      "database has an acc field as an alternate id"},
425     {"httpversion", ATTR_STR, "", "HTTP version for GET requests"},
426     {"identifier", ATTR_STR, "", "standard identifier field"},
427     {"indexdirectory", ATTR_STR, "",
428      "Index directory, defaults to data 'directory'"},
429 
430     {"methodall", ATTR_STR, "",
431      "access method for all entries"},
432     {"methodentry", ATTR_STR, "",
433      "access method for single entry"},
434     {"methodquery", ATTR_STR, "",
435      "access method for query (several entries)"},
436 
437     {"namespace", ATTR_STR, "",
438      "namespace query to restrict ontology searches"},
439     {"organisms", ATTR_STR, "",
440      "organism/taxonomy query to restrict biological searches"},
441     {"proxy", ATTR_STR, "",
442      "http proxy server, or ':' to cancel a global proxy"},
443     {"query", ATTR_STR, "",
444      "database query (SQL, SPARQL, etc.)"},
445     {"release", ATTR_STR, "",
446      "release of the database, comment only"},
447     {"return", ATTR_STR, "",
448      "names of fields to be returned"},
449     {"sequence", ATTR_STR, "",
450      "sequence field to be returned"},
451     {"serverversion", ATTR_STR, "",
452      "version of database server"},
453     {"special", ATTR_LIST, "",
454      "name:value attributes for access method"},
455     {"url", ATTR_STR, "",
456      "Basic URL for data access"},
457     {"view", ATTR_STR, "",
458      "Access method view"},
459 
460     {"edamdat", ATTR_LIST, "",
461      "EDAM datatype term references"},
462     {"edamfmt", ATTR_LIST, "",
463      "EDAM format term references"},
464     {"edamid", ATTR_LIST, "",
465      "EDAM identifier term references"},
466     {"edamtpc", ATTR_LIST, "",
467      "EDAM topic term references"},
468     {"taxon", ATTR_LIST, "",
469      "taxon id and name"},
470 
471     {NULL, ATTR_UNKNOWN, NULL,
472      NULL}
473 };
474 
475 NamOAttr namRsAttrs[] =
476 {
477     {"type", ATTR_STR, "",
478      "resource type (required)"},
479 
480 /*    {"identifier",ATTR_STR,  "",
481       "standard identifier (defaults to name)"},*/
482     {"release", ATTR_STR, "",
483      "release of the resource"},
484     {"pagesize", ATTR_STR, "",
485      "default index pagesize"},
486     {"secpagesize", ATTR_STR, "",
487      "default index secondary pagesize"},
488     {"cachesize", ATTR_STR, "",
489      "default index cache size"},
490     {"seccachesize", ATTR_STR, "",
491      "default index secondary cache size"},
492 
493     {"fields", ATTR_STR,
494      "id,acc,sv,key,des,org,nam,isa,xref",
495                     "known database query fields"},
496 
497     {"value", ATTR_STR, "",
498      "value appropriate to the resource type"},
499     {NULL, ATTR_UNKNOWN, NULL,
500      NULL}
501 };
502 
503 NamOType namDbTypes[] =
504 {
505     {"N",            "sequence",
506      "Nucleotide (obsolete short name)",
507      AJDATATYPE_SEQUENCE},
508     {"P",            "sequence",
509      "Protein (obsolete short name)",
510      AJDATATYPE_SEQUENCE},
511     {"Nucleotide",   "sequence",
512      "Nucleotide sequence data",
513      AJDATATYPE_SEQUENCE},
514     {"Protein",      "sequence",
515      "Protein sequence data",
516      AJDATATYPE_SEQUENCE},
517     {"Sequence",     "sequence",
518      "Both nucleotide and protein sequence data",
519      AJDATATYPE_SEQUENCE},
520     {"Nucfeatures",  "features",
521      "Nucleotide features data",
522      AJDATATYPE_FEATURES},
523     {"Protfeatures", "features",
524      "Protein features data",
525      AJDATATYPE_FEATURES},
526     {"Features",     "features",
527      "Both nucleotide and protein features data",
528      AJDATATYPE_FEATURES},
529 /*    {"Pattern",      "pattern",
530       "Pattern data"},*/
531     {"Assembly",     "assembly",
532      "Assembly of sequence reads",
533      AJDATATYPE_ASSEMBLY},
534     {"Obo",          "obo",
535      "OBO ontology",
536      AJDATATYPE_OBO},
537     {"Refseq",       "refseq",
538      "Reference sequence",
539      AJDATATYPE_REFSEQ},
540     {"Resource" ,    "resource",
541      "Data resource data",
542      AJDATATYPE_RESOURCE},
543     {"Taxonomy",     "taxon",
544      "NCBI taxonomy",
545      AJDATATYPE_TAXON},
546     {"Html",         "text",
547      "HTML data",
548      AJDATATYPE_TEXT},
549     {"Text",         "text",
550      "Text data",
551      AJDATATYPE_TEXT},
552     {"Url",          "url",
553      "Url",
554      AJDATATYPE_URL},
555     {"Variation",    "variation",
556      "Variation",
557      AJDATATYPE_VARIATION},
558     {"Xml",          "xml",
559      "XML data",
560      AJDATATYPE_XML},
561     {"Unknown",      "text",
562      "Unknown type",
563      AJDATATYPE_UNKNOWN},
564     {NULL, NULL,
565      NULL,
566      AJDATATYPE_UNKNOWN}
567 };
568 
569 NamOValid namRsTypes[] =
570 {
571     {"Blast", "Blast database file"},
572     {"Index", "EMBOSS database B+tree index"},
573     {"List", "List of possible values"},
574     {NULL, NULL}
575 };
576 
577 
578 
579 
580 /* @datastatic NamPEntry ******************************************************
581 **
582 ** Internal database standard structure
583 **
584 ** @alias NamSEntry
585 ** @alias NamOEntry
586 **
587 ** @attr name [AjPStr] token name
588 ** @attr value [AjPStr] token value for variables
589 ** @attr file [AjPStr] Short name for definitions file
590 ** @attr data [void*] Attribute names and values for databases
591 ** @@
592 ******************************************************************************/
593 
594 typedef struct NamSEntry
595 {
596     AjPStr name;
597     AjPStr value;
598     AjPStr file;
599     void* data;
600 } NamOEntry;
601 
602 #define NamPEntry NamOEntry*
603 
604 
605 
606 
607 static const AjPTable namQueryDbdata(const AjPQuery qry);
608 static const AjPTable namQuerySvrdata(const AjPQuery qry);
609 static AjBool namSvrCacheParseList(AjPList listwords,
610                                    AjPList listcount,  AjPFile file,
611                                    AjPTable dbtable, AjPTable alitable);
612 static AjBool namSvrCacheParse(AjPFile cachefile, AjPTable dbtable,
613                                AjPTable alitable);
614 static AjPFile namSvrCacheOpen(const AjPStr cachename);
615 static AjBool namSvrCacheRead(const AjPStr server, const AjPStr cachename);
616 static ajint  namSvrAttrC(const char* str);
617 static ajint  namSvrAttrS(const AjPStr thys);
618 static AjBool namSvrSetAttrBoolC(const AjPTable dbtable, const char* attrib,
619                                 AjBool* qrybool);
620 static AjBool namSvrSetAttrStrC(const AjPTable dbtable, const char* attrib,
621                                AjPStr* qrystr);
622 
623 static const char* namDatatype2Fields(ajint datatype);
624 static const char* namDatatype2Qlinks(ajint datatype);
625 static ajint  namDbAttrC(const char* str);
626 static ajint  namDbAttrS(const AjPStr thys);
627 static AjBool namDbSetAttrBoolC(const AjPTable dbtable, const char* attrib,
628                                 AjBool* qrybool);
629 static AjBool namDbSetAttrStrC(const AjPTable dbtable, const char* attrib,
630                                AjPStr* qrystr);
631 
632 static void   namDebugServer(const AjPTable dbtable);
633 static void   namDebugDatabase(const AjPTable dbtable);
634 static void   namDebugResource(const AjPTable dbtable);
635 static void   namDebugVariables(void);
636 static void   namDebugAliases(void);
637 static void   namDebugMaster(const AjPTable table, ajint which);
638 
639 static void   namEntryDelete(NamPEntry* pentry, ajint which);
640 static void   namError(const char* fmt, ...);
641 static void   namListParse(AjPList listwords, AjPList listcount,
642 			   AjPFile file, const AjPStr shortname);
643 static void   namListMasterDelete(AjPTable table, ajint which);
644 static AjBool namAccessTest(const AjPStr method, const AjPStr dbtype);
645 static AjBool namInformatTest(const AjPStr format, const AjPStr dbtype);
646 static const char* namMethod2Qlinks(const AjPStr method, ajint datatype);
647 static ajuint namMethod2Scope(const AjPStr method, const AjPStr dbtype);
648 static void   namNoColon(AjPStr *thys);
649 static AjBool namProcessFile(AjPFile file, const AjPStr shortname);
650 static ajint  namRsAttrC(const char* str);
651 static ajint  namRsAttrS(const AjPStr thys);
652 static ajint  namRsAttrFieldC(const AjPTable rstable, const char* str);
653 static ajint  namRsAttrFieldS(const AjPTable rstable, const AjPStr str);
654 static void   namUser(const char *fmt, ...);
655 static AjBool namValid(const NamPEntry entry, ajint entrytype);
656 static AjBool namValidAlias(const NamPEntry entry);
657 static AjBool namValidDatabase(const NamPEntry entry);
658 static AjBool namValidResource(const NamPEntry entry);
659 static AjBool namValidServer(const NamPEntry entry);
660 static AjBool namValidVariable(const NamPEntry entry);
661 static AjBool namVarResolve(AjPStr* var);
662 static AjBool namDbtablePutAttrS(AjPTable dbtable, AjPStr *Pattribute,
663                                  AjPStr *Pvalue);
664 static AjBool namRstablePutAttrS(AjPTable rstable, AjPStr *Pattribute,
665                                  AjPStr *Pvalue);
666 static AjBool namSvrtablePutAttrS(AjPTable svrtable, AjPStr *Pattribute,
667                                   AjPStr *Pvalue);
668 static void namDbAttrtableFree(AjPTable* Ptable);
669 static void namRsAttrtableFree(AjPTable* Ptable);
670 static void namSvrAttrtableFree(AjPTable* Ptable);
671 
672 
673 
674 
675 /* @funcstatic namEntryDelete *************************************************
676 **
677 ** Deletes a variable, database, or resource entry from the internal table.
678 **
679 ** @param [d] Pentry [NamPEntry*] The entry to be deleted.
680 ** @param [r] which [ajint] Internal table entry type
681 ** @return [void]
682 **
683 ** @release 1.0.0
684 ** @@
685 ******************************************************************************/
686 
namEntryDelete(NamPEntry * Pentry,ajint which)687 static void namEntryDelete(NamPEntry* Pentry, ajint which)
688 {
689 
690     AjPTable attrtable;
691     NamPEntry entry;
692 
693     entry = *Pentry;
694 
695     ajStrDel(&entry->name);
696     ajStrDel(&entry->value);
697     ajStrDel(&entry->file);
698 
699     if(which == TYPE_DB)
700     {
701 	attrtable = (AjPTable) entry->data;
702         namDbAttrtableFree(&attrtable);
703     }
704 
705     else if(which == TYPE_SVR)
706     {
707 	attrtable = (AjPTable) entry->data;
708         namSvrAttrtableFree(&attrtable);
709     }
710 
711     else if(which == TYPE_RESOURCE)
712     {
713 	attrtable = (AjPTable) entry->data;
714         namRsAttrtableFree(&attrtable);
715     }
716 
717     else if(which == TYPE_SVRDB)
718     {
719 	attrtable = (AjPTable) entry->data;
720         namListMasterDelete(attrtable, TYPE_DB);
721         ajTableFree(&attrtable);
722     }
723 
724     else if(which == TYPE_SVRALI)
725     {
726 	attrtable = (AjPTable) entry->data;
727         namListMasterDelete(attrtable, TYPE_ENV);
728         ajTableFree(&attrtable);
729     }
730 
731     else if(which == TYPE_ENV)
732     {
733     }
734 
735     else if(which == TYPE_ALIAS)
736     {
737     }
738 
739     AJFREE(entry);
740 
741     return;
742 }
743 
744 
745 
746 
747 /* @funcstatic namDbAttrtableFree *********************************************
748 **
749 ** Free a database attribute table
750 **
751 ** @param [d] Ptable [AjPTable*] Attribute table
752 **
753 **
754 ** @release 6.4.0
755 ******************************************************************************/
756 
namDbAttrtableFree(AjPTable * Ptable)757 static void namDbAttrtableFree(AjPTable* Ptable)
758 {
759     AjPStr *keys = NULL;
760     void** values = NULL;
761     ajulong n;
762     ajulong i;
763     const NamPAttr attr = NULL;
764 
765     n = ajTableToarrayKeysValues(*Ptable, (void***)&keys, &values);
766 
767     for(i=0UL; i < n; i++)
768     {
769         attr = ajTableFetchS(namDbAttrTable, keys[i]);
770 
771         if(!attr)
772             ajStrDel((AjPStr*) &values[i]);
773         else
774         {
775             switch(attr->Type)
776             {
777                 case ATTR_LIST:
778                     ajListstrFreeData((AjPList*) &values[i]);
779                     break;
780                 default:
781                     ajStrDel((AjPStr*) &values[i]);
782                     break;
783             }
784         }
785 
786         ajStrDel(&keys[i]);
787     }
788 
789     ajTableFree(Ptable);
790 
791     AJFREE(keys);
792     AJFREE(values);
793 
794     return;
795 }
796 
797 
798 
799 
800 /* @funcstatic namRsAttrtableFree *********************************************
801 **
802 ** Free a resource attribute table
803 **
804 ** @param [d] Ptable [AjPTable*] Attribute table
805 **
806 **
807 ** @release 6.4.0
808 ******************************************************************************/
809 
namRsAttrtableFree(AjPTable * Ptable)810 static void namRsAttrtableFree(AjPTable* Ptable)
811 {
812     AjPStr *keys = NULL;
813     void** values = NULL;
814     ajulong n;
815     ajulong i;
816     const NamPAttr attr = NULL;
817 
818     n = ajTableToarrayKeysValues(*Ptable, (void***) &keys, &values);
819 
820     for(i=0UL; i < n; i++)
821     {
822         attr = ajTableFetchS(namResAttrTable, keys[i]);
823 
824         if(!attr)
825             ajStrDel((AjPStr*) &values[i]);
826         else
827         {
828             switch(attr->Type)
829             {
830                 case ATTR_LIST:
831                     ajListstrFreeData((AjPList*) &values[i]);
832                     break;
833                 default:
834                     ajStrDel((AjPStr*) &values[i]);
835                     break;
836             }
837         }
838 
839         ajStrDel(&keys[i]);
840     }
841 
842     ajTableFree(Ptable);
843 
844     AJFREE(keys);
845     AJFREE(values);
846 
847     return;
848 }
849 
850 
851 
852 
853 /* @funcstatic namSvrAttrtableFree ********************************************
854 **
855 ** Free a server attribute table
856 **
857 ** @param [d] Ptable [AjPTable*] Attribute table
858 **
859 **
860 ** @release 6.4.0
861 ******************************************************************************/
862 
namSvrAttrtableFree(AjPTable * Ptable)863 static void namSvrAttrtableFree(AjPTable* Ptable)
864 {
865     AjPStr *keys = NULL;
866     void** values = NULL;
867     ajulong n;
868     ajulong i;
869     const NamPAttr attr = NULL;
870 
871     n = ajTableToarrayKeysValues(*Ptable, (void***) &keys, &values);
872 
873     for(i=0UL; i < n; i++)
874     {
875         attr = ajTableFetchS(namSvrAttrTable, keys[i]);
876 
877         if(!attr)
878             ajStrDel((AjPStr*) &values[i]);
879         else
880         {
881             switch(attr->Type)
882             {
883                 case ATTR_LIST:
884                     ajListstrFreeData((AjPList*) &values[i]);
885                     break;
886                 default:
887                     ajStrDel((AjPStr*) &values[i]);
888                     break;
889             }
890         }
891 
892         ajStrDel(&keys[i]);
893     }
894 
895     ajTableFree(Ptable);
896 
897     AJFREE(keys);
898     AJFREE(values);
899 
900     return;
901 }
902 
903 
904 
905 
906 /* @funcstatic namListMasterDelete ********************************************
907 **
908 ** Deletes all databases in the internal table. The table is converted to
909 ** an array, and each entry in turn is passed to namEntryDelete.
910 **
911 ** @param [u] table [AjPTable] Table object
912 ** @param [r] which [ajint] Internal table entry type
913 ** @return [void]
914 **
915 ** @release 2.7.0
916 ** @@
917 ******************************************************************************/
918 
namListMasterDelete(AjPTable table,ajint which)919 static void namListMasterDelete(AjPTable table, ajint which)
920 {
921     ajint i;
922     NamPEntry fnew = NULL;
923     void **keyarray = NULL;
924     void **valarray = NULL;
925 
926     if(!table)
927         return;
928 
929     ajTableToarrayKeysValues(table, &keyarray, &valarray);
930 
931     for(i = 0; keyarray[i]; i++)
932     {
933 	AJFREE(keyarray[i]);		/* the key */
934 	fnew = (NamPEntry) valarray[i];
935 	namEntryDelete(&fnew, which);
936     }
937 
938     AJFREE(keyarray);
939     AJFREE(valarray);
940 
941     return;
942 }
943 
944 
945 
946 
947 /* @func ajNamPrintSvrAttr ****************************************************
948 **
949 ** Prints a report of the server attributes available (for entrails)
950 **
951 ** @param [u] outf [AjPFile] Output file
952 ** @param [r] full [AjBool] Full output if AjTrue
953 ** @return [void]
954 **
955 ** @release 6.4.0
956 ******************************************************************************/
957 
ajNamPrintSvrAttr(AjPFile outf,AjBool full)958 void ajNamPrintSvrAttr(AjPFile outf, AjBool full)
959 {
960     ajint i;
961     AjPStr tmpstr = NULL;
962     ajuint maxtmp = 0;
963 
964     (void) full;			/* no extra detail to report */
965 
966     ajFmtPrintF(outf, "# Server attributes\n");
967     ajFmtPrintF(outf, "# %-15s %-12s %s\n", "Attribute", "Default", "Comment");
968     ajFmtPrintF(outf, "namSvrAttrs {\n");
969 
970     for(i=0; namSvrAttrs[i].Name; i++)
971     {
972 	ajFmtPrintF(outf, "  %-15s", namSvrAttrs[i].Name);
973 	ajFmtPrintS(&tmpstr, "\"%s\"", namSvrAttrs[i].Defval);
974 
975 	if(ajStrGetLen(tmpstr) > maxtmp)
976 	    maxtmp = ajStrGetLen(tmpstr);
977 
978 	ajFmtPrintF(outf, " %-12S", tmpstr);
979 	ajFmtPrintF(outf, " \"%s\"\n", namSvrAttrs[i].Comment);
980     }
981 
982     if(maxtmp > 12)
983         ajWarn("ajNamPrintSvrAttr max tmpstr len %u",
984                maxtmp);
985 
986     ajFmtPrintF(outf, "}\n\n");
987     ajStrDel(&tmpstr);
988 
989     return;
990 }
991 
992 
993 
994 
995 /* @func ajNamPrintDbAttr *****************************************************
996 **
997 ** Prints a report of the database attributes available (for entrails)
998 **
999 ** @param [u] outf [AjPFile] Output file
1000 ** @param [r] full [AjBool] Full output if AjTrue
1001 ** @return [void]
1002 **
1003 ** @release 2.5.0
1004 ******************************************************************************/
1005 
ajNamPrintDbAttr(AjPFile outf,AjBool full)1006 void ajNamPrintDbAttr(AjPFile outf, AjBool full)
1007 {
1008     ajint i;
1009     AjPStr tmpstr = NULL;
1010     ajuint maxtmp = 0;
1011 
1012     (void) full;			/* no extra detail to report */
1013 
1014     ajFmtPrintF(outf, "# Database attributes\n");
1015     ajFmtPrintF(outf, "# %-15s %-12s %s\n", "Attribute", "Default", "Comment");
1016     ajFmtPrintF(outf, "namDbAttrs {\n");
1017 
1018     for(i=0; namDbAttrs[i].Name; i++)
1019     {
1020 	ajFmtPrintF(outf, "  %-15s", namDbAttrs[i].Name);
1021 	ajFmtPrintS(&tmpstr, "\"%s\"", namDbAttrs[i].Defval);
1022 
1023 	if(ajStrGetLen(tmpstr) > maxtmp)
1024 	    maxtmp = ajStrGetLen(tmpstr);
1025 
1026 	ajFmtPrintF(outf, " %-12S", tmpstr);
1027 	ajFmtPrintF(outf, " \"%s\"\n", namDbAttrs[i].Comment);
1028     }
1029 
1030     if(maxtmp > 12)
1031         ajWarn("ajNamPrintDbAttr max tmpstr len %u",
1032                maxtmp);
1033 
1034     ajFmtPrintF(outf, "}\n\n");
1035     ajStrDel(&tmpstr);
1036 
1037     return;
1038 }
1039 
1040 
1041 
1042 
1043 /* @func ajNamPrintRsAttr *****************************************************
1044 **
1045 ** Prints a report of the resource attributes available (for entrails)
1046 **
1047 ** @param [u] outf [AjPFile] Output file
1048 ** @param [r] full [AjBool] Full output if AjTrue
1049 ** @return [void]
1050 **
1051 ** @release 2.7.0
1052 ******************************************************************************/
1053 
ajNamPrintRsAttr(AjPFile outf,AjBool full)1054 void ajNamPrintRsAttr(AjPFile outf, AjBool full)
1055 {
1056     ajint i;
1057     AjPStr tmpstr = NULL;
1058     ajuint maxtmp = 0;
1059 
1060     (void) full;			/* no extra detail to report */
1061 
1062     ajFmtPrintF(outf, "# Resource attributes\n");
1063     ajFmtPrintF(outf, "# %-15s %-26s %s\n", "Attribute", "Default", "Comment");
1064     ajFmtPrintF(outf, "namRsAttrs {\n");
1065 
1066     for(i=0; namRsAttrs[i].Name; i++)
1067     {
1068 	ajFmtPrintF(outf, "  %-15s", namRsAttrs[i].Name);
1069 	ajFmtPrintS(&tmpstr, "\"%s\"", namRsAttrs[i].Defval);
1070 
1071 	if(ajStrGetLen(tmpstr) > maxtmp)
1072 	    maxtmp = ajStrGetLen(tmpstr);
1073 
1074 	ajFmtPrintF(outf, " %-36S", tmpstr);
1075 	ajFmtPrintF(outf, " \"%s\"\n", namRsAttrs[i].Comment);
1076     }
1077 
1078     ajFmtPrintF(outf, "}\n\n");
1079 
1080     if(maxtmp > 36)
1081         ajWarn("ajNamPrintRsAttr max tmpstr len %u",
1082                maxtmp);
1083 
1084     ajStrDel(&tmpstr);
1085 
1086     return;
1087 }
1088 
1089 
1090 
1091 
1092 /* @funcstatic namDebugDatabase ***********************************************
1093 **
1094 ** Prints a report of defined attributes for a database definition.
1095 **
1096 ** @param [r] dbtable [const AjPTable] Attribute table from a database entry.
1097 ** @return [void]
1098 **
1099 ** @release 1.13.0
1100 ** @@
1101 ******************************************************************************/
1102 
namDebugDatabase(const AjPTable dbtable)1103 static void namDebugDatabase(const AjPTable dbtable)
1104 {
1105     ajulong i;
1106     ajulong nkeys;
1107     AjPStr *names = NULL;
1108     AjPStr *values = NULL;
1109 
1110     nkeys = ajTableToarrayKeysValues(dbtable,
1111                                      (void***) &names, (void***) &values);
1112 
1113    for(i=0UL; i < nkeys; i++)
1114 	if(ajStrGetLen(values[i]))
1115 	    namUser("\t%S: %S\n", names[i], values[i]);
1116 
1117     AJFREE(names);
1118     AJFREE(values);
1119 
1120     return;
1121 }
1122 
1123 
1124 
1125 
1126 /* @funcstatic namDebugServer *************************************************
1127 **
1128 ** Prints a report of defined attributes for a server definition.
1129 **
1130 ** @param [r] svrtable [const AjPTable] Attribute table from a server entry.
1131 ** @return [void]
1132 **
1133 ** @release 6.4.0
1134 ** @@
1135 ******************************************************************************/
1136 
namDebugServer(const AjPTable svrtable)1137 static void namDebugServer(const AjPTable svrtable)
1138 {
1139     ajulong i;
1140     ajulong nkeys;
1141     AjPStr *names = NULL;
1142     AjPStr *values = NULL;
1143 
1144     nkeys = ajTableToarrayKeysValues(svrtable,
1145                                      (void***) &names, (void***) &values);
1146 
1147    for(i=0UL; i < nkeys; i++)
1148 	if(ajStrGetLen(values[i]))
1149 	    namUser("\t%S: %S\n", names[i], values[i]);
1150 
1151     AJFREE(names);
1152     AJFREE(values);
1153 
1154     return;
1155 }
1156 
1157 
1158 
1159 
1160 /* @funcstatic namDebugResource ***********************************************
1161 **
1162 ** Prints a report of defined attributes for a resource definition.
1163 **
1164 ** @param [r] rstable [const AjPTable] Attribute table from a database entry.
1165 ** @return [void]
1166 **
1167 ** @release 2.7.0
1168 ** @@
1169 ******************************************************************************/
1170 
namDebugResource(const AjPTable rstable)1171 static void namDebugResource(const AjPTable rstable)
1172 {
1173     ajulong i;
1174     ajulong nkeys;
1175     AjPStr *names = NULL;
1176     AjPStr *values = NULL;
1177 
1178     nkeys = ajTableToarrayKeysValues(rstable,
1179                                      (void***) &names, (void***) &values);
1180 
1181    for(i=0UL; i < nkeys; i++)
1182 	if(ajStrGetLen(values[i]))
1183 	    namUser("\t%S: %S\n", names[i], values[i]);
1184 
1185     AJFREE(names);
1186     AJFREE(values);
1187 
1188     return;
1189 }
1190 
1191 
1192 
1193 
1194 /* @funcstatic namDebugMaster *************************************************
1195 **
1196 ** Lists databases or variables defined in the internal table.
1197 **
1198 ** @param [r] table [const AjPTable] Table object
1199 ** @param [r] which [ajint] Variable type, either TYPE_ENV for environment
1200 **                        variables or TYPE_DB for databases or
1201 **                        TYPE_RESOURCE for resources.
1202 ** @return [void]
1203 **
1204 ** @release 2.7.0
1205 ** @@
1206 ******************************************************************************/
1207 
namDebugMaster(const AjPTable table,ajint which)1208 static void namDebugMaster(const AjPTable table, ajint which)
1209 {
1210     ajint i;
1211     NamPEntry fnew;
1212     void **keyarray = NULL;
1213     void **valarray = NULL;
1214     char *key;
1215 
1216     ajTableToarrayKeysValues(table, &keyarray, &valarray);
1217 
1218     for(i = 0; keyarray[i]; i++)
1219     {
1220 	key  = (char*) keyarray[i];
1221 	fnew = (NamPEntry) valarray[i];
1222 
1223 	if(TYPE_SVR == which)
1224 	{
1225 	    namUser("SVR %S\t *%s*\n", fnew->name, key);
1226 	    namDebugServer(fnew->data);
1227 	    namUser("\n");
1228 	}
1229 
1230 	else if(TYPE_DB == which)
1231 	{
1232 	    namUser("DB %S\t *%s*\n", fnew->name, key);
1233 	    namDebugDatabase(fnew->data);
1234 	    namUser("\n");
1235 	}
1236 
1237 	else if(TYPE_RESOURCE == which)
1238 	{
1239 	    namUser("RES %S\t *%s*\n", fnew->name, key);
1240 	    namDebugResource(fnew->data);
1241 	    namUser("\n");
1242 	}
1243 
1244 	else if(TYPE_ENV == which)
1245 	    namUser("ENV %S\t%S\t *%s*\n",fnew->name,fnew->value,key);
1246 
1247 	else if(TYPE_ALIAS == which)
1248 	    namUser("ALIAS %S\t%S\t *%s*\n",fnew->name,fnew->value,key);
1249     }
1250 
1251     AJFREE(keyarray);
1252     AJFREE(valarray);
1253 
1254     return;
1255 }
1256 
1257 
1258 
1259 
1260 /* @func ajNamSvrGetAttrC *****************************************************
1261 **
1262 ** Return the value for a server attribute
1263 **
1264 ** @param [r] name [const AjPStr] server name
1265 ** @param [r] attribute [const char *] server attribute name
1266 ** @param [w] value [AjPStr *] attribute value
1267 **
1268 ** @return [AjBool] true if found
1269 **
1270 ** @release 6.4.0
1271 ** @@
1272 ******************************************************************************/
1273 
ajNamSvrGetAttrC(const AjPStr name,const char * attribute,AjPStr * value)1274 AjBool ajNamSvrGetAttrC(const AjPStr name, const char *attribute,
1275                         AjPStr *value)
1276 {
1277     ajint j;
1278     NamPEntry fnew = NULL;
1279     AjPTable svrtable;
1280     const AjPStr svrvalue;
1281 
1282     ajDebug("ajNamSvrGetAttrC '%S' '%s'\n", name, attribute);
1283 
1284     fnew = ajTableFetchmodS(namSvrMasterTable, name);
1285 
1286     if(!fnew)
1287     {
1288         ajWarn("unknown server '%S'",
1289                name);
1290 	return ajFalse;
1291     }
1292 
1293     svrtable = (AjPTable) fnew->data;
1294     j = namSvrAttrC(attribute);
1295 
1296     if(j < 0)
1297     {
1298 	ajWarn("unknown attribute '%s' requested for server '%S'",
1299                attribute, name);
1300         return ajFalse;
1301     }
1302 
1303     svrvalue = ajTableFetchmodC(svrtable, attribute);
1304 
1305     if(ajStrGetLen(svrvalue))
1306     {
1307 	ajStrAssignS(value,svrvalue);
1308 
1309 	return ajTrue;
1310     }
1311 
1312     return ajFalse;
1313 }
1314 
1315 
1316 
1317 
1318 /* @func ajNamSvrGetAttrS *****************************************************
1319 **
1320 ** Return the value for a server attribute
1321 **
1322 ** @param [r] name [const AjPStr] server name
1323 ** @param [r] attribute [const AjPStr] server attribute name
1324 ** @param [w] value [AjPStr *] attribute value
1325 **
1326 ** @return [AjBool] true if found
1327 **
1328 ** @release 6.4.0
1329 ** @@
1330 ******************************************************************************/
1331 
ajNamSvrGetAttrS(const AjPStr name,const AjPStr attribute,AjPStr * value)1332 AjBool ajNamSvrGetAttrS(const AjPStr name, const AjPStr attribute,
1333                        AjPStr *value)
1334 {
1335     return ajNamSvrGetAttrC(name, MAJSTRGETPTR(attribute), value);
1336 }
1337 
1338 
1339 
1340 
1341 /* @func ajNamSvrGetAttrSpecialC **********************************************
1342 **
1343 ** Return the value for the first occurrence of a named special attribute
1344 **
1345 ** @param [r] name [const AjPStr] server name
1346 ** @param [r] attribute [const char*] special attribute name
1347 ** @param [w] value [AjPStr*] value
1348 **
1349 ** @return [ajuint] Number of matching special values
1350 **
1351 ** @release 6.5.0
1352 ** @@
1353 ******************************************************************************/
1354 
ajNamSvrGetAttrSpecialC(const AjPStr name,const char * attribute,AjPStr * value)1355 ajuint ajNamSvrGetAttrSpecialC(const AjPStr name, const char *attribute,
1356                                AjPStr* value)
1357 {
1358     ajuint ret = 0;
1359     ajint j;
1360     NamPEntry fnew = NULL;
1361     AjPTable svrtable;
1362     AjPList svrvalue;
1363     AjIList iter;
1364     const AjPStr tmpstr = NULL;
1365     ajuint attrlen = 0;
1366 
1367     ajDebug("ajNamSvrGetAttrSpecial '%S' '%s'\n", name, attribute);
1368 
1369     attrlen = strlen(attribute);
1370 
1371     fnew = ajTableFetchmodS(namSvrMasterTable, name);
1372 
1373     if(!fnew)
1374     {
1375         ajWarn("unknown database '%S'",
1376                name);
1377 	return ajFalse;
1378     }
1379 
1380     svrtable = (AjPTable) fnew->data;
1381     j = namSvrAttrC("special");
1382 
1383     if(j < 0)
1384     {
1385 	ajWarn("unknown attribute '%s' requested for server '%S'",
1386                "special", name);
1387         return ajFalse;
1388     }
1389 
1390     svrvalue = ajTableFetchmodC(svrtable, "special");
1391 
1392     if(ajListGetLength(svrvalue))
1393     {
1394         iter = ajListIterNewread(svrvalue);
1395 
1396         while(!ajListIterDone(iter))
1397         {
1398             tmpstr = ajListIterGet(iter);
1399             if(ajStrPrefixC(tmpstr, attribute) &&
1400                ajStrGetCharPos(tmpstr, attrlen) == '=')
1401             {
1402                 if(!ret++)
1403                 {
1404                     ajStrAssignS(value, tmpstr);
1405                     ajStrCutStart(value, attrlen+1);
1406                 }
1407             }
1408         }
1409 
1410         ajListIterDel(&iter);
1411     }
1412 
1413     return ret;
1414 }
1415 
1416 
1417 
1418 
1419 /* @func ajNamSvrGetAttrSpecialS **********************************************
1420 **
1421 ** Return the value for the first occurrence of a named special attribute
1422 **
1423 ** @param [r] name [const AjPStr] server name
1424 ** @param [r] attribute [const AjPStr] special attribute name
1425 ** @param [w] value [AjPStr*] value
1426 **
1427 ** @return [ajuint] Number of matching special values
1428 **
1429 ** @release 6.5.0
1430 ** @@
1431 ******************************************************************************/
1432 
ajNamSvrGetAttrSpecialS(const AjPStr name,const AjPStr attribute,AjPStr * value)1433 ajuint ajNamSvrGetAttrSpecialS(const AjPStr name, const AjPStr attribute,
1434                                AjPStr* value)
1435 {
1436     return ajNamSvrGetAttrSpecialC(name, MAJSTRGETPTR(attribute), value);
1437 }
1438 
1439 
1440 
1441 
1442 /* @func ajNamSvrGetAttrlist **************************************************
1443 **
1444 ** Return a list of names and values for all of a server defined attributes
1445 **
1446 ** @param [r] name [const AjPStr] server name
1447 **
1448 ** @return [AjPList] Tag-value list
1449 **
1450 ** @release 6.4.0
1451 ** @@
1452 ******************************************************************************/
1453 
ajNamSvrGetAttrlist(const AjPStr name)1454 AjPList ajNamSvrGetAttrlist(const AjPStr name)
1455 {
1456     AjPList ret = NULL;
1457     AjPTagval tagval = NULL;
1458     NamPEntry fnew = NULL;
1459     AjPTable svrtable = NULL;
1460     const char* svrattr = NULL;
1461     NamOAttr attr;
1462     void* svrvalue;
1463     const AjPStr tmpstr;
1464     ajuint i;
1465     AjIList iter;
1466 
1467     fnew = ajTableFetchmodS(namSvrMasterTable, name);
1468 
1469     if(!fnew)
1470 	return NULL;
1471 
1472     ret = ajListNew();
1473     svrtable = (AjPTable) fnew->data;
1474 
1475     for(i=0; namSvrAttrs[i].Name; i++)
1476     {
1477         attr = namSvrAttrs[i];
1478         svrattr = attr.Name;
1479 
1480         svrvalue = ajTableFetchmodC(svrtable, svrattr);
1481         if(svrvalue)
1482         {
1483             switch(attr.Type)
1484             {
1485                 case ATTR_LIST:
1486                     iter = ajListIterNewread(svrvalue);
1487 
1488                     while(!ajListIterDone(iter))
1489                     {
1490                         tmpstr = ajListIterGet(iter);
1491                         tagval = ajTagvalNewC(svrattr,MAJSTRGETPTR(tmpstr));
1492                         ajListPushAppend(ret, tagval);
1493                     }
1494 
1495                     ajListIterDel(&iter);
1496                     break;
1497                 default:
1498                     tagval = ajTagvalNewC(svrattr,ajStrGetPtr(svrvalue));
1499                     ajListPushAppend(ret, tagval);
1500                    break;
1501             }
1502         }
1503     }
1504 
1505     return ret;
1506 
1507 }
1508 
1509 
1510 
1511 
1512 /* @func ajNamSvrGetdbAttrC ***************************************************
1513 **
1514 ** Return the value for a server database attribute
1515 **
1516 ** @param [r] name [const AjPStr] server name
1517 ** @param [r] dbname [const AjPStr] database name
1518 ** @param [r] attribute [const char *] database attribute name
1519 ** @param [w] value [AjPStr *] attribute value
1520 **
1521 ** @return [AjBool] true if found
1522 **
1523 ** @release 6.4.0
1524 ** @@
1525 ******************************************************************************/
1526 
ajNamSvrGetdbAttrC(const AjPStr name,const AjPStr dbname,const char * attribute,AjPStr * value)1527 AjBool ajNamSvrGetdbAttrC(const AjPStr name, const AjPStr dbname,
1528                           const char *attribute,
1529                           AjPStr *value)
1530 {
1531     ajint j;
1532     NamPEntry dbdata = NULL;
1533     NamPEntry fnew = NULL;
1534     AjPTable sdbtable;
1535     AjPTable dbtable;
1536     const AjPStr dbvalue;
1537 
1538     ajDebug("ajNamSvrGetdbAttrC '%S' '%S' '%s'\n",
1539             name, dbname, attribute);
1540 
1541     if(!ajNamDatabaseServer(dbname, name))
1542         return ajFalse;
1543 
1544     dbdata = ajTableFetchmodS(namSvrDatabaseTable, name);
1545     sdbtable = (AjPTable) dbdata->data;
1546 
1547     fnew = ajTableFetchmodS(sdbtable, dbname);
1548 
1549     dbtable = (AjPTable) fnew->data;
1550     j = namDbAttrC(attribute);
1551 
1552     if(j < 0)
1553     {
1554 	ajWarn("unknown attribute '%s' requested for database '%S'",
1555                attribute, name);
1556         return ajFalse;
1557     }
1558 
1559     dbvalue = ajTableFetchmodC(dbtable, attribute);
1560 
1561     if(ajStrGetLen(dbvalue))
1562     {
1563 	ajStrAssignS(value,dbvalue);
1564 
1565 	return ajTrue;
1566     }
1567 
1568     return ajFalse;
1569 }
1570 
1571 
1572 
1573 
1574 /* @func ajNamSvrGetdbAttrS ***************************************************
1575 **
1576 ** Return the value for a database attribute
1577 **
1578 ** @param [r] name [const AjPStr] server name
1579 ** @param [r] dbname [const AjPStr] database name
1580 ** @param [r] attribute [const AjPStr] database attribute name
1581 ** @param [w] value [AjPStr *] attribute value
1582 **
1583 ** @return [AjBool] true if found
1584 **
1585 ** @release 6.4.0
1586 ** @@
1587 ******************************************************************************/
1588 
ajNamSvrGetdbAttrS(const AjPStr name,const AjPStr dbname,const AjPStr attribute,AjPStr * value)1589 AjBool ajNamSvrGetdbAttrS(const AjPStr name, const AjPStr dbname,
1590                           const AjPStr attribute,
1591                           AjPStr *value)
1592 {
1593     return ajNamSvrGetdbAttrC(name, dbname, MAJSTRGETPTR(attribute), value);
1594 }
1595 
1596 
1597 
1598 
1599 /* @func ajNamSvrGetdbAttrSpecialC ********************************************
1600 **
1601 ** Return the value for a server database special attribute
1602 **
1603 ** @param [r] name [const AjPStr] server name
1604 ** @param [r] dbname [const AjPStr] database name
1605 ** @param [r] attribute [const char *] database special attribute name
1606 ** @param [w] value [AjPStr *] attribute value
1607 **
1608 ** @return [ajuint] Number of matching special values
1609 **
1610 ** @release 6.5.0
1611 ** @@
1612 ******************************************************************************/
1613 
ajNamSvrGetdbAttrSpecialC(const AjPStr name,const AjPStr dbname,const char * attribute,AjPStr * value)1614 ajuint ajNamSvrGetdbAttrSpecialC(const AjPStr name, const AjPStr dbname,
1615                                  const char *attribute,
1616                                  AjPStr *value)
1617 {
1618     ajuint ret = 0;
1619     ajint j;
1620     NamPEntry fnew = NULL;
1621     NamPEntry dbdata = NULL;
1622     AjPTable sdbtable;
1623     AjPTable dbtable;
1624     AjPList dbvalue;
1625     AjIList iter;
1626     const AjPStr tmpstr = NULL;
1627     ajuint attrlen = 0;
1628 
1629     ajDebug("ajNamSvrGetdbAttrSpecialC '%S' '%S' '%s'\n",
1630             name, dbname, attribute);
1631 
1632     if(!ajNamDatabaseServer(dbname, name))
1633         return ajFalse;
1634 
1635     attrlen = strlen(attribute);
1636 
1637     dbdata = ajTableFetchmodS(namSvrDatabaseTable, name);
1638     sdbtable = (AjPTable) dbdata->data;
1639 
1640     fnew = ajTableFetchmodS(sdbtable, dbname);
1641 
1642     dbtable = (AjPTable) fnew->data;
1643     j = namDbAttrC("special");
1644 
1645     if(j < 0)
1646     {
1647 	ajWarn("unknown attribute '%s' requested for database '%S'",
1648                "special", name);
1649         return ajFalse;
1650     }
1651 
1652     dbvalue = ajTableFetchmodC(dbtable, "special");
1653 
1654     if(ajListGetLength(dbvalue))
1655     {
1656         iter = ajListIterNewread(dbvalue);
1657 
1658         while(!ajListIterDone(iter))
1659         {
1660             tmpstr = ajListIterGet(iter);
1661             if(ajStrPrefixC(tmpstr, attribute) &&
1662                ajStrGetCharPos(tmpstr, attrlen) == '=')
1663             {
1664                 if(!ret++)
1665                 {
1666                     ajStrAssignS(value, tmpstr);
1667                     ajStrCutStart(value, attrlen+1);
1668                 }
1669             }
1670         }
1671 
1672         ajListIterDel(&iter);
1673     }
1674 
1675     return ret;
1676 }
1677 
1678 
1679 
1680 
1681 /* @func ajNamSvrGetdbAttrSpecialS ********************************************
1682 **
1683 ** Return the value for a database special attribute
1684 **
1685 ** @param [r] name [const AjPStr] server name
1686 ** @param [r] dbname [const AjPStr] database name
1687 ** @param [r] attribute [const AjPStr] database special attribute name
1688 ** @param [w] value [AjPStr *] attribute value
1689 **
1690 ** @return [ajuint] Number of matching special values
1691 **
1692 ** @release 6.5.0
1693 ** @@
1694 ******************************************************************************/
1695 
ajNamSvrGetdbAttrSpecialS(const AjPStr name,const AjPStr dbname,const AjPStr attribute,AjPStr * value)1696 ajuint ajNamSvrGetdbAttrSpecialS(const AjPStr name, const AjPStr dbname,
1697                                  const AjPStr attribute,
1698                                  AjPStr *value)
1699 {
1700     return ajNamSvrGetdbAttrSpecialC(name, dbname, MAJSTRGETPTR(attribute),
1701                                      value);
1702 }
1703 
1704 
1705 
1706 
1707 /* @func ajNamSvrDetails ******************************************************
1708 **
1709 ** Returns server access method information
1710 **
1711 ** @param [r] name [const AjPStr] Server name
1712 ** @param [w] type [AjPStr*] datatype - 'Protein', 'Nucleic' etc.
1713 ** @param [w] scope [AjPStr*] datatype scope Sequence Features etc.
1714 ** @param [w] id [AjBool*] ajTrue = can access single entries
1715 ** @param [w] qry [AjBool*] ajTrue = can access wild/query entries
1716 ** @param [w] all [AjBool*] ajTrue = can access all entries
1717 ** @param [w] comment [AjPStr*] comment about server
1718 ** @param [w] svrversion [AjPStr*] Server version
1719 ** @param [w] methods [AjPStr*] server access methods formatted
1720 ** @param [w] defined [AjPStr*] server definition file short name
1721 ** @param [w] cachedirectory [AjPStr*] cache directory name
1722 ** @param [w] cachefile [AjPStr*] cache file name
1723 ** @param [w] url [AjPStr*] server URL
1724 ** @return [AjBool] ajTrue if server details were found
1725 **
1726 ** @release 6.4.0
1727 ** @@
1728 ******************************************************************************/
1729 
ajNamSvrDetails(const AjPStr name,AjPStr * type,AjPStr * scope,AjBool * id,AjBool * qry,AjBool * all,AjPStr * comment,AjPStr * svrversion,AjPStr * methods,AjPStr * defined,AjPStr * cachedirectory,AjPStr * cachefile,AjPStr * url)1730 AjBool ajNamSvrDetails(const AjPStr name, AjPStr* type, AjPStr *scope,
1731                        AjBool* id, AjBool* qry, AjBool* all,
1732                        AjPStr* comment, AjPStr* svrversion,
1733                        AjPStr* methods, AjPStr* defined,
1734                        AjPStr *cachedirectory, AjPStr* cachefile,
1735                        AjPStr *url)
1736 {
1737     NamPType namtype = NULL;
1738     NamPEntry fnew = NULL;
1739     AjPTable svrtable = NULL;
1740     ajint i;
1741     ajint qryscope;
1742     AjPStr attrname  = NULL;
1743     const AjPStr attrval  = NULL;
1744     const AjPStr svrtype  = NULL;
1745     AjBool typetested = ajFalse;
1746     AjPStrTok handle = NULL;
1747     AjPStr nexttype = NULL;
1748 
1749     AjPFile cacheopen = NULL;
1750 
1751     AjBool *datatype;
1752 
1753     *id = *qry = *all = ajFalse;
1754 
1755     ajStrDelStatic(scope);
1756     ajStrDelStatic(type);
1757     ajStrDelStatic(comment);
1758     ajStrDelStatic(methods);
1759     ajStrDelStatic(defined);
1760     ajStrDelStatic(cachedirectory);
1761     ajStrDelStatic(cachefile);
1762     ajStrDelStatic(svrversion);
1763     ajStrDelStatic(url);
1764 
1765     fnew = ajTableFetchmodS(namSvrMasterTable, name);
1766 
1767     if(fnew)
1768     {
1769 	ajDebug("ajNamSvrDetails '%S' found\n", name);
1770 
1771 	ajStrAssignS(defined, fnew->file);
1772 
1773 	svrtable = (AjPTable) fnew->data;
1774         svrtype = ajTableFetchmodC(svrtable, "type");
1775 
1776 	for(i=0; namSvrAttrs[i].Name; i++)
1777 	{
1778 	    if(namSvrAttrs[i].Type != ATTR_STR)
1779                 continue;
1780 
1781             ajStrAssignC(&attrname, namSvrAttrs[i].Name);
1782             attrval = ajTableFetchmodS(svrtable, attrname);
1783                 ajDebug("Attribute name = %S, value = %S\n",
1784                         attrname, attrval);
1785 
1786 	    if(ajStrGetLen(attrval))
1787 	    {
1788                 if(ajStrMatchC(attrname, "type"))
1789                 {
1790                     ajStrTokenAssignC(&handle, attrval, " ,;");
1791                     ajStrAssignC(type, "");
1792                     ajStrAssignC(scope, "");
1793                     AJCNEW0(datatype, AJDATATYPE_MAX);
1794 
1795                     while(ajStrTokenNextParse(handle, &nexttype))
1796                     {
1797                         if(ajStrGetLen(*type))
1798                             ajStrAppendK(type, ' ');
1799 
1800                         if(ajStrMatchCaseC(attrval, "N"))
1801                             ajStrAppendC(type, "Nucleotide");
1802                         else if(ajStrMatchCaseC(attrval, "P"))
1803                             ajStrAppendC(type, "Protein");
1804                         else
1805                         {
1806                             ajStrFmtCapital(&nexttype);
1807                             ajStrAppendS(type, nexttype);
1808                         }
1809 
1810                         typetested = ajTrue;
1811                         namtype = ajTableFetchmodS(namDbTypeTable, nexttype);
1812 
1813                         if(namtype)
1814                         {
1815                             if(!datatype[namtype->DataType]++)
1816                             {
1817                                 if(ajStrGetLen(*scope))
1818                                     ajStrAppendK(scope, ' ');
1819 
1820                                 ajStrAppendC(scope, namtype->Scope);
1821                             }
1822                         }
1823                         else
1824                             ajWarn("Server '%S' type '%S' unknown scope",
1825                                    name, nexttype);
1826                     }
1827                     ajStrTokenDel(&handle);
1828                     AJFREE(datatype);
1829                     ajStrDel(&nexttype);
1830                 }
1831 
1832 		if(ajStrMatchC(attrname, "method"))
1833 		{
1834 		    qryscope = namMethod2Scope(attrval, svrtype);
1835 
1836 		    if(qryscope & AJMETHOD_ENTRY)
1837                         *id = ajTrue;
1838 
1839 		    if(qryscope & AJMETHOD_QUERY)
1840                         *qry = ajTrue;
1841 
1842 		    if(qryscope & AJMETHOD_ALL)
1843                         *all = ajTrue;
1844 
1845 		    ajStrAppendS(methods, attrval);
1846 		}
1847 
1848 		if(ajStrMatchC(attrname, "methodentry"))
1849 		{
1850                     qryscope = namMethod2Scope(attrval, svrtype);
1851 
1852 		    if(qryscope & AJMETHOD_ENTRY)
1853                         *id = ajTrue;
1854 
1855 		    if(ajStrGetLen(*methods))
1856 			ajStrAppendC(methods, ",");
1857 
1858 		    ajStrAppendS(methods, attrval);
1859 		    ajStrAppendC(methods, "(id)");
1860 		}
1861 
1862 		if(ajStrMatchC(attrname, "methodquery"))
1863 		{
1864 		    qryscope = namMethod2Scope(attrval, svrtype);
1865 
1866 		    if(qryscope & AJMETHOD_ENTRY)
1867                         *id = ajTrue;
1868 
1869 		    if(qryscope & AJMETHOD_QUERY)
1870                         *qry = ajTrue;
1871 
1872 		    if(ajStrGetLen(*methods))
1873 			ajStrAppendC(methods, ",");
1874 
1875 		    ajStrAppendS(methods, attrval);
1876 		    ajStrAppendC(methods, "(qry)");
1877 		}
1878 
1879 		if(ajStrMatchC(attrname, "methodall"))
1880 		{
1881 		    qryscope = namMethod2Scope(attrval, svrtype);
1882 
1883 		    if(qryscope & AJMETHOD_ALL)
1884                         *all = ajTrue;
1885 
1886 		    if(ajStrGetLen(*methods))
1887 			ajStrAppendC(methods, ",");
1888 
1889 		    ajStrAppendS(methods, attrval);
1890 		    ajStrAppendC(methods, "(all)");
1891 		}
1892 
1893                 if(ajStrMatchC(attrname, "comment"))
1894 		    ajStrAssignS(comment, attrval);
1895 
1896                 if(ajStrMatchC(attrname, "serverversion"))
1897 		    ajStrAssignS(svrversion, attrval);
1898 
1899                 if(ajStrMatchC(attrname, "cachedirectory"))
1900 		    ajStrAssignS(cachedirectory, attrval);
1901 
1902                 if(ajStrMatchC(attrname, "cachefile"))
1903 		    ajStrAssignS(cachefile, attrval);
1904 
1905                 if(ajStrMatchC(attrname, "url"))
1906 		    ajStrAssignS(url, attrval);
1907 	    }
1908 	}
1909 
1910 	if(!typetested)
1911 	{
1912 	    ajDebug("Bad server definition for %S: No type. 'P' assumed\n",
1913 		   name);
1914 	    ajWarn("Bad server definition for %S: No type. 'P' assumed",
1915 		   name);
1916 	    ajStrAssignC(type, "P");
1917 	}
1918 
1919 	if(!*id && !*qry && !*all)
1920         {
1921 	    ajDebug("Bad server definition for %S: No method(s) for access\n",
1922 		   name);
1923 	    ajWarn("Bad server definition for %S: No method(s) for access",
1924 		   name);
1925 	}
1926 
1927         ajStrDel(&attrname);
1928 
1929         if(ajStrGetLen(*cachefile))
1930         {
1931             cacheopen = namSvrCacheOpen(*cachefile);
1932             if(cacheopen)
1933             {
1934                 ajFmtPrintS(cachefile, "%F", cacheopen);
1935                 ajFileClose(&cacheopen);
1936             }
1937         }
1938 
1939 	return ajTrue;
1940     }
1941 
1942     ajDebug("  '%S' not found\n", name);
1943 
1944     ajStrDel(&attrname);
1945 
1946     return ajFalse;
1947 }
1948 
1949 
1950 
1951 
1952 /* @func ajNamDbGetAttrC ******************************************************
1953 **
1954 ** Return the value for a database attribute
1955 **
1956 ** @param [r] name [const AjPStr] database name
1957 ** @param [r] attribute [const char *] database attribute name
1958 ** @param [w] value [AjPStr *] attribute value
1959 **
1960 ** @return [AjBool] true if found
1961 **
1962 ** @release 6.4.0
1963 ** @@
1964 ******************************************************************************/
1965 
ajNamDbGetAttrC(const AjPStr name,const char * attribute,AjPStr * value)1966 AjBool ajNamDbGetAttrC(const AjPStr name, const char *attribute,
1967                        AjPStr *value)
1968 {
1969     ajint j;
1970     NamPEntry fnew = NULL;
1971     AjPTable dbtable;
1972     const AjPStr dbvalue;
1973 
1974     ajDebug("ajNamDbGetAttrC '%S' '%s'\n", name, attribute);
1975 
1976     fnew = ajTableFetchmodS(namDbMasterTable, name);
1977 
1978     if(!fnew)
1979     {
1980         ajWarn("unknown database '%S'",
1981                name);
1982 	return ajFalse;
1983     }
1984 
1985     dbtable = (AjPTable) fnew->data;
1986     j = namDbAttrC(attribute);
1987 
1988     if(j < 0)
1989     {
1990 	ajWarn("unknown attribute '%s' requested for database '%S'",
1991                attribute, name);
1992         return ajFalse;
1993     }
1994 
1995     dbvalue = ajTableFetchmodC(dbtable, attribute);
1996 
1997     if(ajStrGetLen(dbvalue))
1998     {
1999 	ajStrAssignS(value,dbvalue);
2000 
2001 	return ajTrue;
2002     }
2003 
2004     return ajFalse;
2005 }
2006 
2007 
2008 
2009 
2010 /* @func ajNamDbGetAttrS ******************************************************
2011 **
2012 ** Return the value for a database attribute
2013 **
2014 ** @param [r] name [const AjPStr] database name
2015 ** @param [r] attribute [const AjPStr] database attribute name
2016 ** @param [w] value [AjPStr *] attribute value
2017 **
2018 ** @return [AjBool] true if found
2019 **
2020 ** @release 6.4.0
2021 ** @@
2022 ******************************************************************************/
2023 
ajNamDbGetAttrS(const AjPStr name,const AjPStr attribute,AjPStr * value)2024 AjBool ajNamDbGetAttrS(const AjPStr name, const AjPStr attribute,
2025                        AjPStr *value)
2026 {
2027     return ajNamDbGetAttrC(name, MAJSTRGETPTR(attribute), value);
2028 }
2029 
2030 
2031 
2032 
2033 /* @func ajNamDbGetAttrSpecialC ***********************************************
2034 **
2035 ** Return the value for the first occurrence of a named special attribute
2036 **
2037 ** @param [r] name [const AjPStr] database name
2038 ** @param [r] attribute [const char*] special attribute name
2039 ** @param [w] value [AjPStr*] value
2040 **
2041 ** @return [ajuint] Number of matching special values
2042 **
2043 ** @release 6.5.0
2044 ** @@
2045 ******************************************************************************/
2046 
ajNamDbGetAttrSpecialC(const AjPStr name,const char * attribute,AjPStr * value)2047 ajuint ajNamDbGetAttrSpecialC(const AjPStr name, const char *attribute,
2048                               AjPStr* value)
2049 {
2050     ajuint ret = 0;
2051     ajint j;
2052     NamPEntry fnew = NULL;
2053     AjPTable dbtable;
2054     AjPList dbvalue;
2055     AjIList iter;
2056     const AjPStr tmpstr = NULL;
2057     ajuint attrlen = 0;
2058 
2059     ajDebug("ajNamDbGetAttrSpecial '%S' '%s'\n", name, attribute);
2060 
2061     attrlen = strlen(attribute);
2062 
2063     fnew = ajTableFetchmodS(namDbMasterTable, name);
2064 
2065     if(!fnew)
2066     {
2067         ajWarn("unknown database '%S'",
2068                name);
2069 	return ajFalse;
2070     }
2071 
2072     dbtable = (AjPTable) fnew->data;
2073     j = namDbAttrC("special");
2074 
2075     if(j < 0)
2076     {
2077 	ajWarn("unknown attribute '%s' requested for database '%S'",
2078                "special", name);
2079         return ajFalse;
2080     }
2081 
2082     dbvalue = ajTableFetchmodC(dbtable, "special");
2083 
2084     if(ajListGetLength(dbvalue))
2085     {
2086         iter = ajListIterNewread(dbvalue);
2087 
2088         while(!ajListIterDone(iter))
2089         {
2090             tmpstr = ajListIterGet(iter);
2091             if(ajStrPrefixC(tmpstr, attribute) &&
2092                ajStrGetCharPos(tmpstr, attrlen) == '=')
2093             {
2094                 if(!ret++)
2095                 {
2096                     ajStrAssignS(value, tmpstr);
2097                     ajStrCutStart(value, attrlen+1);
2098                 }
2099             }
2100         }
2101 
2102         ajListIterDel(&iter);
2103     }
2104 
2105     return ret;
2106 }
2107 
2108 
2109 
2110 
2111 /* @func ajNamDbGetAttrSpecialS ***********************************************
2112 **
2113 ** Return the value for the first occurrence of a named special attribute
2114 **
2115 ** @param [r] name [const AjPStr] database name
2116 ** @param [r] attribute [const AjPStr] special attribute name
2117 ** @param [w] value [AjPStr*] value
2118 **
2119 ** @return [ajuint] Number of matching special values
2120 **
2121 ** @release 6.5.0
2122 ** @@
2123 ******************************************************************************/
2124 
ajNamDbGetAttrSpecialS(const AjPStr name,const AjPStr attribute,AjPStr * value)2125 ajuint ajNamDbGetAttrSpecialS(const AjPStr name, const AjPStr attribute,
2126                               AjPStr* value)
2127 {
2128     return ajNamDbGetAttrSpecialC(name, MAJSTRGETPTR(attribute), value);
2129 }
2130 
2131 
2132 
2133 
2134 /* @func ajNamDbGetAttrlist ***************************************************
2135 **
2136 ** Return a list of names and values for all of a database defined attributes
2137 **
2138 ** @param [r] name [const AjPStr] database name
2139 **
2140 ** @return [AjPList] Tag-value list
2141 **
2142 ** @release 6.4.0
2143 ** @@
2144 ******************************************************************************/
2145 
ajNamDbGetAttrlist(const AjPStr name)2146 AjPList ajNamDbGetAttrlist(const AjPStr name)
2147 {
2148     AjPList ret = NULL;
2149     AjPTagval tagval = NULL;
2150     NamPEntry fnew = NULL;
2151     AjPTable dbtable = NULL;
2152     const char* dbattr = NULL;
2153     NamOAttr attr;
2154     void* dbvalue;
2155     const AjPStr tmpstr;
2156     ajuint i;
2157     AjIList iter;
2158 
2159     fnew = ajTableFetchmodS(namDbMasterTable, name);
2160 
2161     if(!fnew)
2162     {
2163 	return NULL;
2164     }
2165 
2166     ret = ajListNew();
2167     dbtable = (AjPTable) fnew->data;
2168 
2169     for(i=0; namDbAttrs[i].Name; i++)
2170     {
2171         attr = namDbAttrs[i];
2172         dbattr = attr.Name;
2173 
2174         dbvalue = ajTableFetchmodC(dbtable, dbattr);
2175 
2176         if(dbvalue)
2177         {
2178             switch(attr.Type)
2179             {
2180                 case ATTR_LIST:
2181                     iter = ajListIterNewread(dbvalue);
2182 
2183                     while(!ajListIterDone(iter))
2184                     {
2185                         tmpstr = ajListIterGet(iter);
2186                         tagval = ajTagvalNewC(dbattr, MAJSTRGETPTR(tmpstr));
2187                         ajListPushAppend(ret, tagval);
2188                     }
2189 
2190                     ajListIterDel(&iter);
2191                     break;
2192                 default:
2193                     tagval = ajTagvalNewC(dbattr, ajStrGetPtr(dbvalue));
2194                     ajListPushAppend(ret, tagval);
2195                    break;
2196             }
2197         }
2198     }
2199 
2200     return ret;
2201 
2202 }
2203 
2204 
2205 
2206 
2207 /* @func ajNamDbGetAttrlistSvr ************************************************
2208 **
2209 ** Return a list of names and values for all of a database defined attributes
2210 ** where the database is defined for a server
2211 **
2212 ** @param [r] name [const AjPStr] database name
2213 ** @param [r] svrname [const AjPStr] server name
2214 **
2215 ** @return [AjPList] Tag-value list
2216 **
2217 ** @release 6.5.0
2218 ** @@
2219 ******************************************************************************/
2220 
ajNamDbGetAttrlistSvr(const AjPStr name,const AjPStr svrname)2221 AjPList ajNamDbGetAttrlistSvr(const AjPStr name, const AjPStr svrname)
2222 {
2223     AjPList ret = NULL;
2224     AjPTagval tagval = NULL;
2225     NamPEntry svdata = NULL;
2226     NamPEntry fnew = NULL;
2227     const AjPTable dbtable = NULL;
2228     const AjPTable svtable = NULL;
2229     const char* dbattr = NULL;
2230     NamOAttr attr;
2231     void* dbvalue;
2232     const AjPStr tmpstr;
2233     ajuint i;
2234     AjIList iter;
2235 
2236     svdata = ajTableFetchmodS(namSvrDatabaseTable, svrname);
2237     if(!svdata)
2238         return NULL;
2239 
2240     fnew = ajTableFetchmodS(svdata->data, name);
2241 
2242     if(!fnew)
2243 	return NULL;
2244 
2245     ret = ajListNew();
2246     dbtable = (const AjPTable) fnew->data;
2247 
2248     svdata = ajTableFetchmodS(namSvrMasterTable, svrname);
2249     svtable = svdata->data;
2250 
2251     for(i=0; namDbAttrs[i].Name; i++)
2252     {
2253         attr = namDbAttrs[i];
2254         dbattr = attr.Name;
2255 
2256         dbvalue = ajTableFetchmodC(dbtable, dbattr);
2257         if(!dbvalue)
2258             dbvalue = ajTableFetchmodC(svtable, dbattr);
2259 
2260         if(dbvalue)
2261         {
2262             switch(attr.Type)
2263             {
2264                 case ATTR_LIST:
2265                     iter = ajListIterNewread(dbvalue);
2266 
2267                     while(!ajListIterDone(iter))
2268                     {
2269                         tmpstr = ajListIterGet(iter);
2270                         tagval = ajTagvalNewC(dbattr, MAJSTRGETPTR(tmpstr));
2271                         ajListPushAppend(ret, tagval);
2272                     }
2273 
2274                     ajListIterDel(&iter);
2275                     break;
2276                 default:
2277                     tagval = ajTagvalNewC(dbattr, ajStrGetPtr(dbvalue));
2278                     ajListPushAppend(ret, tagval);
2279                    break;
2280             }
2281         }
2282     }
2283 
2284     return ret;
2285 
2286 }
2287 
2288 
2289 
2290 
2291 /* @funcstatic namDbtablePutAttrS *********************************************
2292 **
2293 ** Store the value for a database attribute
2294 **
2295 ** @param [u] dbtable [AjPTable] Database attribute table
2296 ** @param [u] Pattribute [AjPStr *] database attribute name
2297 ** @param [u] Pvalue [AjPStr*] attribute value
2298 **
2299 ** @return [AjBool] true if found
2300 **
2301 ** @release 6.4.0
2302 ** @@
2303 ******************************************************************************/
2304 
namDbtablePutAttrS(AjPTable dbtable,AjPStr * Pattribute,AjPStr * Pvalue)2305 static AjBool namDbtablePutAttrS(AjPTable dbtable, AjPStr *Pattribute,
2306                                  AjPStr *Pvalue)
2307 {
2308     void *oldval;
2309     NamPAttr attr;
2310     AjPList fdlist = NULL;
2311 
2312     attr  = ajTableFetchmodS(namDbAttrTable, *Pattribute);
2313     namUser("store db attr '%S' => '%S'\n", *Pattribute, *Pvalue);
2314 
2315     switch(attr->Type)
2316     {
2317         case ATTR_LIST:
2318             fdlist = ajTableFetchmodS(dbtable, *Pattribute);
2319 
2320             if(!fdlist)
2321             {
2322                 fdlist = ajListstrNew();
2323                 ajTablePut(dbtable, (AjPStr) *Pattribute, (AjPList) fdlist);
2324                 *Pattribute = NULL;
2325             }
2326             else
2327                 ajStrDel(Pattribute);
2328 
2329             ajListstrPushAppend(fdlist, *Pvalue);
2330             break;
2331 
2332         default:
2333             oldval = ajTablePut(dbtable, (AjPStr) *Pattribute,
2334                                 (AjPStr) *Pvalue);
2335             if(oldval)
2336                 ajWarn("duplicate db keyword value for '%S' = '%S'",
2337                        *Pattribute, (AjPStr) oldval);
2338 
2339             *Pattribute = NULL;
2340             break;
2341     }
2342 
2343     *Pvalue = NULL;
2344 
2345     return ajTrue;
2346 }
2347 
2348 
2349 
2350 
2351 /* @funcstatic namRstablePutAttrS *********************************************
2352 **
2353 ** Store the value for a resource attribute
2354 **
2355 ** @param [u] rstable [AjPTable] Resource attribute table
2356 ** @param [u] Pattribute [AjPStr*] resource attribute name
2357 ** @param [u] Pvalue [AjPStr*] attribute value
2358 **
2359 ** @return [AjBool] true if found
2360 **
2361 ** @release 6.4.0
2362 ** @@
2363 ******************************************************************************/
2364 
namRstablePutAttrS(AjPTable rstable,AjPStr * Pattribute,AjPStr * Pvalue)2365 static AjBool namRstablePutAttrS(AjPTable rstable, AjPStr *Pattribute,
2366                                  AjPStr *Pvalue)
2367 {
2368     void *oldval;
2369     NamPAttr attr;
2370     AjPList fdlist = NULL;
2371 
2372     attr  = ajTableFetchmodS(namResAttrTable, *Pattribute);
2373     namUser("store resource attr '%S' => '%S\n", *Pattribute, *Pvalue);
2374 
2375     if(!attr)
2376         ajTablePut(rstable, (AjPStr) *Pattribute,
2377                    (AjPStr) *Pvalue);
2378     else
2379     {
2380         switch(attr->Type)
2381         {
2382             case ATTR_LIST:
2383                 fdlist = ajTableFetchmodS(rstable, *Pattribute);
2384 
2385                 if(!fdlist)
2386                 {
2387                     fdlist = ajListstrNew();
2388                     ajTablePut(rstable, (AjPStr) *Pattribute, (AjPList) fdlist);
2389                     *Pattribute = NULL;
2390                 }
2391                 else
2392                     ajStrDel(Pattribute);
2393 
2394                 ajListstrPushAppend(fdlist, *Pvalue);
2395             break;
2396 
2397             default:
2398                 oldval = ajTablePut(rstable, (AjPStr) *Pattribute,
2399                                     (AjPStr) *Pvalue);
2400                 if(oldval)
2401                     ajWarn("duplicate resource keyword value for '%S' = '%S'",
2402                            *Pattribute, (AjPStr) oldval);
2403 
2404                 *Pattribute = NULL;
2405                 break;
2406         }
2407     }
2408 
2409     *Pvalue = NULL;
2410 
2411     return ajTrue;
2412 }
2413 
2414 
2415 
2416 
2417 /* @funcstatic namSvrtablePutAttrS ********************************************
2418 **
2419 ** Store the value for a server attribute
2420 **
2421 ** @param [u] svrtable [AjPTable] Server attribute table
2422 ** @param [u] Pattribute [AjPStr*] server attribute name
2423 ** @param [u] Pvalue [AjPStr*] attribute value
2424 **
2425 ** @return [AjBool] true if found
2426 **
2427 ** @release 6.4.0
2428 ** @@
2429 ******************************************************************************/
2430 
namSvrtablePutAttrS(AjPTable svrtable,AjPStr * Pattribute,AjPStr * Pvalue)2431 static AjBool namSvrtablePutAttrS(AjPTable svrtable, AjPStr *Pattribute,
2432                                   AjPStr *Pvalue)
2433 {
2434     void *oldval;
2435     NamPAttr attr;
2436     AjPList fdlist = NULL;
2437 
2438     attr  = ajTableFetchmodS(namSvrAttrTable, *Pattribute);
2439     namUser("store server attr '%S' => '%S\n", *Pattribute, *Pvalue);
2440 
2441     switch(attr->Type)
2442     {
2443         case ATTR_LIST:
2444             fdlist = ajTableFetchmodS(svrtable, *Pattribute);
2445 
2446             if(!fdlist)
2447             {
2448                 fdlist = ajListstrNew();
2449                 ajTablePut(svrtable, (AjPStr) *Pattribute, (AjPList) fdlist);
2450                 *Pattribute = NULL;
2451             }
2452             else
2453                 ajStrDel(Pattribute);
2454 
2455             ajListstrPushAppend(fdlist, *Pvalue);
2456             break;
2457 
2458         default:
2459             oldval = ajTablePut(svrtable, (AjPStr) *Pattribute,
2460                                 (AjPStr) *Pvalue);
2461             if(oldval)
2462                 ajWarn("duplicate server keyword value for '%S' = '%S'",
2463                        *Pattribute, (AjPStr) oldval);
2464 
2465             *Pattribute = NULL;
2466             break;
2467     }
2468 
2469     *Pvalue = NULL;
2470 
2471     return ajTrue;
2472 }
2473 
2474 
2475 
2476 
2477 /* @func ajNamDbDetails *******************************************************
2478 **
2479 ** Returns database access method information
2480 **
2481 ** @param [r] name [const AjPStr] Database name
2482 ** @param [w] type [AjPStr*] sequence type
2483 ** @param [w] id [AjBool*] ajTrue = can access single entries
2484 ** @param [w] qry [AjBool*] ajTrue = can access wild/query entries
2485 ** @param [w] all [AjBool*] ajTrue = can access all entries
2486 ** @param [w] comment [AjPStr*] comment about database
2487 ** @param [w] release [AjPStr*] database release date
2488 ** @param [w] methods [AjPStr*] database access methods formatted
2489 ** @param [w] defined [AjPStr*] database definition file short name
2490 ** @return [AjBool] ajTrue if database details were found
2491 **
2492 ** @release 1.0.0
2493 ** @@
2494 ******************************************************************************/
2495 
ajNamDbDetails(const AjPStr name,AjPStr * type,AjBool * id,AjBool * qry,AjBool * all,AjPStr * comment,AjPStr * release,AjPStr * methods,AjPStr * defined)2496 AjBool ajNamDbDetails(const AjPStr name, AjPStr* type, AjBool* id,
2497 		      AjBool* qry, AjBool* all,
2498 		      AjPStr* comment, AjPStr* release,
2499 		      AjPStr* methods, AjPStr* defined)
2500 {
2501     NamPEntry fnew = NULL;
2502     AjPTable dbtable = NULL;
2503     ajint i;
2504     ajint scope;
2505     AjPStr attrname  = NULL;
2506     const AjPStr attrval  = NULL;
2507     const AjPStr dbtype  = NULL;
2508     AjBool typetested = ajFalse;
2509 
2510     *id = *qry = *all = ajFalse;
2511 
2512     ajStrDelStatic(type);
2513     ajStrDelStatic(comment);
2514     ajStrDelStatic(release);
2515     ajStrDelStatic(methods);
2516     ajStrDelStatic(defined);
2517 
2518     fnew = ajTableFetchmodS(namDbMasterTable, name);
2519 
2520     if(fnew)
2521     {
2522 	ajDebug("ajNamDbDetails: '%S' found\n", name);
2523 
2524 	ajStrAssignS(defined, fnew->file);
2525 
2526 	dbtable = (AjPTable) fnew->data;
2527         dbtype = ajTableFetchmodC(dbtable, "type");
2528 
2529 	for(i=0; namDbAttrs[i].Name; i++)
2530 	{
2531             if(namDbAttrs[i].Type != ATTR_STR)
2532                 continue;
2533 
2534             ajStrAssignC(&attrname, namDbAttrs[i].Name);
2535 
2536             attrval = ajTableFetchmodS(dbtable, attrname);
2537 	    ajDebug("Attribute name = %S, value = %S\n",
2538                     attrname, attrval);
2539 
2540 	    if(ajStrGetLen(attrval))
2541 	    {
2542 		if(ajStrMatchC(attrname, "type"))
2543                 {
2544                     if(ajStrMatchCaseC(attrval, "N"))
2545                         ajStrAssignC(type, "Nucleotide");
2546                     else if(ajStrMatchCaseC(attrval, "P"))
2547                         ajStrAssignC(type, "Protein");
2548                     else
2549                     {
2550                         ajStrAssignS(type, attrval);
2551                         ajStrFmtCapital(type);
2552                     }
2553 
2554                     typetested = ajTrue;
2555                 }
2556 
2557 		if(ajStrMatchC(attrname, "method"))
2558 		{
2559 		    scope = namMethod2Scope(attrval, dbtype);
2560 
2561 		    if(scope & AJMETHOD_ENTRY)
2562                         *id = ajTrue;
2563 
2564 		    if(scope & AJMETHOD_QUERY)
2565                         *qry = ajTrue;
2566 
2567 		    if(scope & AJMETHOD_ALL)
2568                         *all = ajTrue;
2569 
2570 		    ajStrAppendS(methods, attrval);
2571 		}
2572 
2573 		if(ajStrMatchC(attrname, "methodentry"))
2574 		{
2575                     scope = namMethod2Scope(attrval, dbtype);
2576 
2577 		    if(scope & AJMETHOD_ENTRY)
2578                         *id = ajTrue;
2579 
2580 		    if(ajStrGetLen(*methods))
2581 			ajStrAppendC(methods, ",");
2582 
2583 		    ajStrAppendS(methods, attrval);
2584 		    ajStrAppendC(methods, "(id)");
2585 		}
2586 
2587 		if(ajStrMatchC(attrname, "methodquery"))
2588 		{
2589 		    scope = namMethod2Scope(attrval, dbtype);
2590 
2591 		    if(scope & AJMETHOD_ENTRY)
2592                         *id = ajTrue;
2593 
2594 		    if(scope & AJMETHOD_QUERY)
2595                         *qry = ajTrue;
2596 
2597 		    if(ajStrGetLen(*methods))
2598 			ajStrAppendC(methods, ",");
2599 
2600 		    ajStrAppendS(methods, attrval);
2601 		    ajStrAppendC(methods, "(qry)");
2602 		}
2603 
2604 		if(ajStrMatchC(attrname, "methodall"))
2605 		{
2606 		    scope = namMethod2Scope(attrval, dbtype);
2607 
2608 		    if(scope & AJMETHOD_ALL)
2609                         *all = ajTrue;
2610 
2611 		    if(ajStrGetLen(*methods))
2612 			ajStrAppendC(methods, ",");
2613 
2614 		    ajStrAppendS(methods, attrval);
2615 		    ajStrAppendC(methods, "(all)");
2616 		}
2617 
2618                 if(ajStrMatchC(attrname, "comment"))
2619 		    ajStrAssignS(comment, attrval);
2620 
2621 		if(ajStrMatchC(attrname, "release"))
2622 		    ajStrAssignS(release, attrval);
2623 	    }
2624 	}
2625 
2626 	if(!typetested)
2627 	{
2628 	    ajDebug("Bad database definition for %S: No type. 'P' assumed\n",
2629 		   name);
2630 	    ajWarn("Bad database definition for %S: No type. 'P' assumed",
2631 		   name);
2632 	    ajStrAssignC(type, "P");
2633 	}
2634 
2635 	if(!*id && !*qry && !*all)
2636         {
2637 	    ajDebug("Bad database definition for %S: No method(s) for access\n",
2638 		   name);
2639 	    ajWarn("Bad database definition for %S: No method(s) for access",
2640 		   name);
2641 	}
2642 
2643         ajStrDel(&attrname);
2644 
2645 	return ajTrue;
2646     }
2647 
2648     ajDebug("ajNamDbDetails: FAILED '%S' not found\n", name);
2649 
2650     ajStrDel(&attrname);
2651 
2652     return ajFalse;
2653 }
2654 
2655 
2656 
2657 
2658 /* @func ajNamDbDetailsSvr ***************************************************
2659 **
2660 ** Returns database access method information for a database on a server
2661 **
2662 ** @param [r] name [const AjPStr] Database name
2663 ** @param [r] svrname [const AjPStr] Server name
2664 ** @param [w] type [AjPStr*] sequence type
2665 ** @param [w] id [AjBool*] ajTrue = can access single entries
2666 ** @param [w] qry [AjBool*] ajTrue = can access wild/query entries
2667 ** @param [w] all [AjBool*] ajTrue = can access all entries
2668 ** @param [w] comment [AjPStr*] comment about database
2669 ** @param [w] release [AjPStr*] database release date
2670 ** @param [w] methods [AjPStr*] database access methods formatted
2671 ** @param [w] defined [AjPStr*] database definition file short name
2672 ** @return [AjBool] ajTrue if database details were found
2673 **
2674 ** @release 6.5.0
2675 ** @@
2676 ******************************************************************************/
2677 
ajNamDbDetailsSvr(const AjPStr name,const AjPStr svrname,AjPStr * type,AjBool * id,AjBool * qry,AjBool * all,AjPStr * comment,AjPStr * release,AjPStr * methods,AjPStr * defined)2678 AjBool ajNamDbDetailsSvr(const AjPStr name, const AjPStr svrname,
2679                          AjPStr* type, AjBool* id,
2680                          AjBool* qry, AjBool* all,
2681                          AjPStr* comment, AjPStr* release,
2682                          AjPStr* methods, AjPStr* defined)
2683 {
2684     const NamPEntry svdata = NULL;
2685     const NamPEntry dbdata = NULL;
2686     const AjPTable svrtable = NULL;
2687     const AjPTable dbtable = NULL;
2688     ajint i;
2689     ajint scope;
2690     AjPStr attrname  = NULL;
2691     const AjPStr attrval  = NULL;
2692     const AjPStr dbtype  = NULL;
2693     const AjPStr svrtype  = NULL;
2694     AjBool typetested = ajFalse;
2695 
2696     *id = *qry = *all = ajFalse;
2697 
2698     ajStrDelStatic(type);
2699     ajStrDelStatic(comment);
2700     ajStrDelStatic(release);
2701     ajStrDelStatic(methods);
2702     ajStrDelStatic(defined);
2703 
2704     /* make sure we have read the server cache file */
2705 
2706     if(!ajStrGetLen(svrname))
2707     {
2708         dbdata = ajTableFetchmodS(namDbMasterTable, name);
2709     }
2710     else
2711     {
2712         if(!ajNamDatabaseServer(name, svrname))
2713             return ajFalse;
2714 
2715         svdata = ajTableFetchS(namSvrDatabaseTable, svrname);
2716         svrtable = (const AjPTable) svdata->data;
2717 
2718         dbdata = ajTableFetchS(svrtable, name);
2719 
2720         svdata = ajTableFetchS(namSvrMasterTable, svrname);
2721         svrtable = (const AjPTable) svdata->data;
2722 
2723         svrtype = ajTableFetchmodC(svrtable, "type");
2724 
2725 	for(i=0; namSvrAttrs[i].Name; i++)
2726 	{
2727             if(namSvrAttrs[i].Type != ATTR_STR)
2728                 continue;
2729 
2730             ajStrAssignC(&attrname, namSvrAttrs[i].Name);
2731 
2732             attrval = ajTableFetchmodS(svrtable, attrname);
2733 	    ajDebug("Attribute name = %S, value = %S\n",
2734                     attrname, attrval);
2735 
2736 	    if(ajStrGetLen(attrval))
2737 	    {
2738 		if(ajStrMatchC(attrname, "type"))
2739                 {
2740                     if(ajStrMatchCaseC(attrval, "N"))
2741                         ajStrAssignC(type, "Nucleotide");
2742                     else if(ajStrMatchCaseC(attrval, "P"))
2743                         ajStrAssignC(type, "Protein");
2744                     else
2745                     {
2746                         ajStrAssignS(type, attrval);
2747                         ajStrFmtCapital(type);
2748                     }
2749 
2750                     typetested = ajTrue;
2751                 }
2752 
2753 		if(ajStrMatchC(attrname, "method"))
2754 		{
2755 		    scope = namMethod2Scope(attrval, svrtype);
2756 
2757 		    if(scope & AJMETHOD_ENTRY)
2758                         *id = ajTrue;
2759 
2760 		    if(scope & AJMETHOD_QUERY)
2761                         *qry = ajTrue;
2762 
2763 		    if(scope & AJMETHOD_ALL)
2764                         *all = ajTrue;
2765 
2766 		    ajStrAppendS(methods, attrval);
2767 		}
2768 
2769 		if(ajStrMatchC(attrname, "methodentry"))
2770 		{
2771                     scope = namMethod2Scope(attrval, svrtype);
2772 
2773 		    if(scope & AJMETHOD_ENTRY)
2774                         *id = ajTrue;
2775 
2776 		    if(ajStrGetLen(*methods))
2777 			ajStrAppendC(methods, ",");
2778 
2779 		    ajStrAppendS(methods, attrval);
2780 		    ajStrAppendC(methods, "(id)");
2781 		}
2782 
2783 		if(ajStrMatchC(attrname, "methodquery"))
2784 		{
2785 		    scope = namMethod2Scope(attrval, svrtype);
2786 
2787 		    if(scope & AJMETHOD_ENTRY)
2788                         *id = ajTrue;
2789 
2790 		    if(scope & AJMETHOD_QUERY)
2791                         *qry = ajTrue;
2792 
2793 		    if(ajStrGetLen(*methods))
2794 			ajStrAppendC(methods, ",");
2795 
2796 		    ajStrAppendS(methods, attrval);
2797 		    ajStrAppendC(methods, "(qry)");
2798 		}
2799 
2800 		if(ajStrMatchC(attrname, "methodall"))
2801 		{
2802 		    scope = namMethod2Scope(attrval, svrtype);
2803 
2804 		    if(scope & AJMETHOD_ALL)
2805                         *all = ajTrue;
2806 
2807 		    if(ajStrGetLen(*methods))
2808 			ajStrAppendC(methods, ",");
2809 
2810 		    ajStrAppendS(methods, attrval);
2811 		    ajStrAppendC(methods, "(all)");
2812 		}
2813 
2814                 if(ajStrMatchC(attrname, "comment"))
2815 		    ajStrAssignS(comment, attrval);
2816 
2817 		if(ajStrMatchC(attrname, "release"))
2818 		    ajStrAssignS(release, attrval);
2819 	    }
2820 	}
2821 
2822         ajStrDel(&attrname);
2823     }
2824 
2825 
2826     if(dbdata)
2827     {
2828 	ajDebug("ajNamDbDetails: '%S' found\n", name);
2829 
2830 	ajStrAssignS(defined, dbdata->file);
2831 
2832 	dbtable = (const AjPTable) dbdata->data;
2833         dbtype = ajTableFetchmodC(dbtable, "type");
2834         if(!dbtype)
2835             dbtype = svrtype;
2836 
2837 	for(i=0; namDbAttrs[i].Name; i++)
2838 	{
2839             if(namDbAttrs[i].Type != ATTR_STR)
2840                 continue;
2841 
2842             ajStrAssignC(&attrname, namDbAttrs[i].Name);
2843 
2844             attrval = ajTableFetchmodS(dbtable, attrname);
2845 	    ajDebug("Attribute name = %S, value = %S\n",
2846                     attrname, attrval);
2847 
2848 	    if(ajStrGetLen(attrval))
2849 	    {
2850 		if(ajStrMatchC(attrname, "type"))
2851                 {
2852                     if(ajStrMatchCaseC(attrval, "N"))
2853                         ajStrAssignC(type, "Nucleotide");
2854                     else if(ajStrMatchC(attrval, "P"))
2855                         ajStrAssignC(type, "Protein");
2856                     else
2857                     {
2858                         ajStrAssignS(type, attrval);
2859                         ajStrFmtCapital(type);
2860                     }
2861 
2862                     typetested = ajTrue;
2863                 }
2864 
2865 		if(ajStrMatchC(attrname, "method"))
2866 		{
2867 		    scope = namMethod2Scope(attrval, dbtype);
2868 
2869 		    if(scope & AJMETHOD_ENTRY)
2870                         *id = ajTrue;
2871 
2872 		    if(scope & AJMETHOD_QUERY)
2873                         *qry = ajTrue;
2874 
2875 		    if(scope & AJMETHOD_ALL)
2876                         *all = ajTrue;
2877 
2878 		    ajStrAppendS(methods, attrval);
2879 		}
2880 
2881 		if(ajStrMatchC(attrname, "methodentry"))
2882 		{
2883                     scope = namMethod2Scope(attrval, dbtype);
2884 
2885 		    if(scope & AJMETHOD_ENTRY)
2886                         *id = ajTrue;
2887 
2888 		    if(ajStrGetLen(*methods))
2889 			ajStrAppendC(methods, ",");
2890 
2891 		    ajStrAppendS(methods, attrval);
2892 		    ajStrAppendC(methods, "(id)");
2893 		}
2894 
2895 		if(ajStrMatchC(attrname, "methodquery"))
2896 		{
2897 		    scope = namMethod2Scope(attrval, dbtype);
2898 
2899 		    if(scope & AJMETHOD_ENTRY)
2900                         *id = ajTrue;
2901 
2902 		    if(scope & AJMETHOD_QUERY)
2903                         *qry = ajTrue;
2904 
2905 		    if(ajStrGetLen(*methods))
2906 			ajStrAppendC(methods, ",");
2907 
2908 		    ajStrAppendS(methods, attrval);
2909 		    ajStrAppendC(methods, "(qry)");
2910 		}
2911 
2912 		if(ajStrMatchC(attrname, "methodall"))
2913 		{
2914 		    scope = namMethod2Scope(attrval, dbtype);
2915 
2916 		    if(scope & AJMETHOD_ALL)
2917                         *all = ajTrue;
2918 
2919 		    if(ajStrGetLen(*methods))
2920 			ajStrAppendC(methods, ",");
2921 
2922 		    ajStrAppendS(methods, attrval);
2923 		    ajStrAppendC(methods, "(all)");
2924 		}
2925 
2926                 if(ajStrMatchC(attrname, "comment"))
2927 		    ajStrAssignS(comment, attrval);
2928 
2929 		if(ajStrMatchC(attrname, "release"))
2930 		    ajStrAssignS(release, attrval);
2931 	    }
2932 	}
2933 
2934 	if(!typetested)
2935 	{
2936 	    ajDebug("Bad database definition for %S: No type. 'P' assumed\n",
2937 		   name);
2938 	    ajWarn("Bad database definition for %S: No type. 'P' assumed",
2939 		   name);
2940 	    ajStrAssignC(type, "P");
2941 	}
2942 
2943 	if(!*id && !*qry && !*all)
2944         {
2945 	    ajDebug("Bad database definition for %S: No method(s) for access\n",
2946 		   name);
2947 	    ajWarn("Bad database definition for %S: No method(s) for access",
2948 		   name);
2949 	}
2950 
2951         ajStrDel(&attrname);
2952 
2953 	return ajTrue;
2954     }
2955 
2956     ajDebug("ajNamDbDetails: FAILED '%S' not found\n", name);
2957 
2958     ajStrDel(&attrname);
2959 
2960     return ajFalse;
2961 }
2962 
2963 
2964 
2965 
2966 /* @funcstatic namAccessTest **************************************************
2967 **
2968 ** Tests whether a named access method is known for a given data type
2969 **
2970 ** @param [r] method [const AjPStr] Access method name
2971 ** @param [r] dbtype [const AjPStr] Database type
2972 ** @return [AjBool] True if found
2973 **
2974 ** @release 6.4.0
2975 ** @@
2976 ******************************************************************************/
2977 
namAccessTest(const AjPStr method,const AjPStr dbtype)2978 static AjBool namAccessTest(const AjPStr method, const AjPStr dbtype)
2979 {
2980     AjBool result;
2981     NamPType namtype;
2982 
2983     result = ajTextaccessMethodTest(method);
2984 
2985     if(!result)
2986     {
2987         namtype = ajTableFetchmodS(namDbTypeTable, dbtype);
2988 
2989         if(!namtype)
2990             return result;
2991 
2992         if(namtype->DataType == AJDATATYPE_ASSEMBLY)
2993             result = ajAssemaccessMethodTest(method);
2994         else if(namtype->DataType == AJDATATYPE_FEATURES)
2995             result = ajFeattabaccessMethodTest(method);
2996         else if(namtype->DataType == AJDATATYPE_OBO)
2997             result = ajOboaccessMethodTest(method);
2998         else if(namtype->DataType == AJDATATYPE_REFSEQ)
2999             result = ajRefseqaccessMethodTest(method);
3000         else if(namtype->DataType == AJDATATYPE_RESOURCE)
3001             result = ajResourceaccessMethodTest(method);
3002         else if(namtype->DataType == AJDATATYPE_SEQUENCE)
3003             result = ajSeqaccessMethodTest(method);
3004         else if(namtype->DataType == AJDATATYPE_TAXON)
3005             result = ajTaxaccessMethodTest(method);
3006         else if(namtype->DataType == AJDATATYPE_URL)
3007             result = ajUrlaccessMethodTest(method);
3008         else if(namtype->DataType == AJDATATYPE_VARIATION)
3009             result = ajVaraccessMethodTest(method);
3010         else if(namtype->DataType == AJDATATYPE_XML)
3011             result = ajXmlaccessMethodTest(method);
3012     }
3013 
3014     return result;
3015 }
3016 
3017 
3018 
3019 
3020 /* @funcstatic namInformatTest ************************************************
3021 **
3022 ** Tests whether a named data input format is known for a given data type
3023 **
3024 ** @param [r] format [const AjPStr] Format name
3025 ** @param [r] dbtype [const AjPStr] Database type
3026 ** @return [AjBool] True if found
3027 **
3028 ** @release 6.4.0
3029 ** @@
3030 ******************************************************************************/
3031 
namInformatTest(const AjPStr format,const AjPStr dbtype)3032 static AjBool namInformatTest(const AjPStr format, const AjPStr dbtype)
3033 {
3034     AjBool result = ajFalse;
3035     NamPType namtype;
3036 
3037     namtype = ajTableFetchmodS(namDbTypeTable, dbtype);
3038 
3039     if(!namtype)
3040         return ajFalse;
3041 
3042     ajDebug("namInformatTest format '%S' dbtype '%S' namtype '%s'\n",
3043             format, dbtype, namtype->Name);
3044 
3045     if(namtype->DataType == AJDATATYPE_ASSEMBLY)
3046         result = ajAsseminformatTest(format);
3047     else if(namtype->DataType == AJDATATYPE_FEATURES)
3048         result = ajFeattabinformatTest(format);
3049     else if(namtype->DataType == AJDATATYPE_OBO)
3050         result = ajOboinformatTest(format);
3051     else if(namtype->DataType == AJDATATYPE_REFSEQ)
3052         result = ajRefseqinformatTest(format);
3053     else if(namtype->DataType == AJDATATYPE_RESOURCE)
3054         result = ajResourceinformatTest(format);
3055     else if(namtype->DataType == AJDATATYPE_SEQUENCE)
3056         result = ajSeqinformatTest(format);
3057     else if(namtype->DataType == AJDATATYPE_TAXON)
3058         result = ajTaxinformatTest(format);
3059     else if(namtype->DataType == AJDATATYPE_TEXT)
3060         result = ajTextinformatTest(format);
3061     else if(namtype->DataType == AJDATATYPE_URL)
3062         result = ajUrlinformatTest(format);
3063     else if(namtype->DataType == AJDATATYPE_VARIATION)
3064         result = ajVarinformatTest(format);
3065     else if(namtype->DataType == AJDATATYPE_XML)
3066         result = ajXmlinformatTest(format);
3067 
3068     return result;
3069 }
3070 
3071 
3072 
3073 
3074 /* @funcstatic namMethod2Qlinks ***********************************************
3075 **
3076 ** Returns known query link operators
3077 ** for the various types of access method for databases.
3078 **
3079 ** @param [r] method [const AjPStr] Access method string
3080 ** @param [r] datatype [ajint] Enumerated database type
3081 ** @return [const char*] Query link operators
3082 **
3083 ** @release 6.4.0
3084 ** @@
3085 ******************************************************************************/
3086 
namMethod2Qlinks(const AjPStr method,ajint datatype)3087 static const char* namMethod2Qlinks(const AjPStr method, ajint datatype)
3088 {
3089     const char* result = NULL;
3090 
3091     result = ajTextaccessMethodGetQlinks(method);
3092 
3093     if(ajCharMatchC(result, "DATA"))
3094        result = namDatatype2Qlinks(datatype);
3095 
3096     ajDebug("namMethod2Qlinks method: '%S' datatype: %d text: '%s'\n",
3097            method, datatype, result);
3098 
3099     if(datatype == AJDATATYPE_TEXT)
3100         return result;
3101 
3102     if(!result)
3103     {
3104         if(datatype == AJDATATYPE_ASSEMBLY)
3105             result = ajAssemaccessMethodGetQlinks(method);
3106         else if(datatype == AJDATATYPE_FEATURES)
3107             result = ajFeattabaccessMethodGetQlinks(method);
3108         else if(datatype == AJDATATYPE_OBO)
3109             result = ajOboaccessMethodGetQlinks(method);
3110         else if(datatype == AJDATATYPE_RESOURCE)
3111             result = ajResourceaccessMethodGetQlinks(method);
3112         else if(datatype == AJDATATYPE_SEQUENCE)
3113             result = ajSeqaccessMethodGetQlinks(method);
3114         else if(datatype == AJDATATYPE_TAXON)
3115             result = ajTaxaccessMethodGetQlinks(method);
3116         else if(datatype == AJDATATYPE_URL)
3117             result = ajUrlaccessMethodGetQlinks(method);
3118         else if(datatype == AJDATATYPE_VARIATION)
3119             result = ajVaraccessMethodGetQlinks(method);
3120         else if(datatype == AJDATATYPE_XML)
3121             result = ajXmlaccessMethodGetQlinks(method);
3122     }
3123 
3124     return result;
3125 }
3126 
3127 
3128 
3129 
3130 /* @funcstatic namMethod2Scope ************************************************
3131 **
3132 ** Returns OR'ed values of AJMETHOD_ENTRY, AJMETHOD_QUERY and AJMETHOD_ALL
3133 ** for the various types of access method for databases.
3134 **
3135 ** @param [r] method [const AjPStr] Access method string
3136 ** @param [r] dbtype [const AjPStr] Database type
3137 ** @return [ajuint] OR'ed values for the valid scope of the access method given
3138 **
3139 ** @release 1.0.0
3140 ** @@
3141 ******************************************************************************/
3142 
namMethod2Scope(const AjPStr method,const AjPStr dbtype)3143 static ajuint namMethod2Scope(const AjPStr method, const AjPStr dbtype)
3144 {
3145     ajuint result = 0;
3146     NamPType namtype;
3147     AjPStrTok handle = NULL;
3148     AjPStr nexttype = NULL;
3149 
3150     result = ajTextaccessMethodGetScope(method);
3151 
3152     if(!result)
3153     {
3154         ajStrTokenAssignC(&handle, dbtype, " ,;");
3155 
3156         while(ajStrTokenNextParse(handle, &nexttype))
3157         {
3158             namtype = ajTableFetchmodS(namDbTypeTable, nexttype);
3159 
3160             if(!namtype)
3161                 return result;
3162 
3163             if(namtype->DataType == AJDATATYPE_ASSEMBLY)
3164                 result |= ajAssemaccessMethodGetScope(method);
3165             else if(namtype->DataType == AJDATATYPE_FEATURES)
3166                 result |= ajFeattabaccessMethodGetScope(method);
3167             else if(namtype->DataType == AJDATATYPE_OBO)
3168                 result |= ajOboaccessMethodGetScope(method);
3169             else if(namtype->DataType == AJDATATYPE_REFSEQ)
3170                 result |= ajRefseqaccessMethodGetScope(method);
3171             else if(namtype->DataType == AJDATATYPE_RESOURCE)
3172                 result |= ajResourceaccessMethodGetScope(method);
3173             else if(namtype->DataType == AJDATATYPE_SEQUENCE)
3174                 result |= ajSeqaccessMethodGetScope(method);
3175             else if(namtype->DataType == AJDATATYPE_TAXON)
3176                 result |= ajTaxaccessMethodGetScope(method);
3177             else if(namtype->DataType == AJDATATYPE_URL)
3178                 result |= ajUrlaccessMethodGetScope(method);
3179             else if(namtype->DataType == AJDATATYPE_VARIATION)
3180                 result |= ajVaraccessMethodGetScope(method);
3181             else if(namtype->DataType == AJDATATYPE_XML)
3182                 result |= ajXmlaccessMethodGetScope(method);
3183         }
3184     }
3185 
3186     ajStrDel(&nexttype);
3187     ajStrTokenDel(&handle);
3188 
3189     return result;
3190 }
3191 
3192 
3193 
3194 
3195 /* @funcstatic namDatatype2Fields *********************************************
3196 **
3197 ** Returns the list of fields that can be processed by the "Read"
3198 ** file parsing function for a specified datatype
3199 **
3200 ** @param [r] datatype [ajint] Enumerated data type
3201 ** @return [const char*] Field name list
3202 **
3203 ** @release 6.4.0
3204 ** @@
3205 ******************************************************************************/
3206 
namDatatype2Fields(ajint datatype)3207 static const char* namDatatype2Fields(ajint datatype)
3208 {
3209     const char* result = NULL;
3210 
3211     if(datatype == AJDATATYPE_ASSEMBLY)
3212         result = ajAsseminTypeGetFields();
3213     else if(datatype == AJDATATYPE_FEATURES)
3214         result = ajFeattabinTypeGetFields();
3215     else if(datatype == AJDATATYPE_OBO)
3216         result = ajOboinTypeGetFields();
3217     else if(datatype == AJDATATYPE_RESOURCE)
3218         result = ajResourceinTypeGetFields();
3219     else if(datatype == AJDATATYPE_SEQUENCE)
3220         result = ajSeqinTypeGetFields();
3221     else if(datatype == AJDATATYPE_TAXON)
3222         result = ajTaxinTypeGetFields();
3223     else if(datatype == AJDATATYPE_URL)
3224         result = ajUrlinTypeGetFields();
3225     else if(datatype == AJDATATYPE_VARIATION)
3226         result = ajVarinTypeGetFields();
3227     else if(datatype == AJDATATYPE_XML)
3228         result = ajXmlinTypeGetFields();
3229 
3230     if(!result)
3231         result = ajTextinTypeGetFields();
3232 
3233     return result;
3234 }
3235 
3236 
3237 
3238 
3239 /* @funcstatic namDatatype2Qlinks *********************************************
3240 **
3241 ** Returns the list of query links that can be processed by the "Read"
3242 ** file parsing function for a specified datatype
3243 **
3244 ** @param [r] datatype [ajint] Enumerated data type
3245 ** @return [const char*] Known query link operators
3246 **
3247 ** @release 6.4.0
3248 ** @@
3249 ******************************************************************************/
3250 
namDatatype2Qlinks(ajint datatype)3251 static const char* namDatatype2Qlinks(ajint datatype)
3252 {
3253     const char* result = NULL;
3254 
3255     if(datatype == AJDATATYPE_ASSEMBLY)
3256         result = ajAsseminTypeGetQlinks();
3257     else if(datatype == AJDATATYPE_FEATURES)
3258         result = ajFeattabinTypeGetQlinks();
3259     else if(datatype == AJDATATYPE_OBO)
3260         result = ajOboinTypeGetQlinks();
3261     else if(datatype == AJDATATYPE_RESOURCE)
3262         result = ajResourceinTypeGetQlinks();
3263     else if(datatype == AJDATATYPE_SEQUENCE)
3264         result = ajSeqinTypeGetQlinks();
3265     else if(datatype == AJDATATYPE_TAXON)
3266         result = ajTaxinTypeGetQlinks();
3267     else if(datatype == AJDATATYPE_URL)
3268         result = ajUrlinTypeGetQlinks();
3269     else if(datatype == AJDATATYPE_VARIATION)
3270         result = ajVarinTypeGetQlinks();
3271     else if(datatype == AJDATATYPE_XML)
3272         result = ajXmlinTypeGetQlinks();
3273 
3274     if(!result)
3275         result = ajTextinTypeGetQlinks();
3276 
3277     return result;
3278 }
3279 
3280 
3281 
3282 
3283 /* @func ajNamDebugOrigin *****************************************************
3284 **
3285 ** Writes a simple list of where the internal tables came from..
3286 **
3287 ** @return [void]
3288 **
3289 ** @release 1.13.0
3290 ** @@
3291 ******************************************************************************/
3292 
ajNamDebugOrigin(void)3293 void ajNamDebugOrigin(void)
3294 {
3295     ajDebug("Defaults and .rc files: %S\n", namFileOrig);
3296 
3297     return;
3298 }
3299 
3300 
3301 
3302 
3303 /* @func ajNamDebugServers ****************************************************
3304 **
3305 ** Writes a simple debug report of all servers in the internal table.
3306 **
3307 ** @return [void]
3308 **
3309 ** @release 6.4.0
3310 ** @@
3311 ******************************************************************************/
3312 
ajNamDebugServers(void)3313 void ajNamDebugServers(void)
3314 {
3315     ajDebug("SERVER servers\n");
3316     ajDebug("==============\n");
3317     namDebugMaster(namSvrMasterTable, TYPE_SVR);
3318     ajDebug("[SVR done]\n\n");
3319 
3320     return;
3321 }
3322 
3323 
3324 
3325 
3326 /* @func ajNamDebugDatabases **************************************************
3327 **
3328 ** Writes a simple debug report of all databases in the internal table.
3329 **
3330 ** @return [void]
3331 **
3332 ** @release 1.13.0
3333 ** @@
3334 ******************************************************************************/
3335 
ajNamDebugDatabases(void)3336 void ajNamDebugDatabases(void)
3337 {
3338     ajDebug("DB databases\n");
3339     ajDebug("============\n");
3340     namDebugMaster(namDbMasterTable, TYPE_DB);
3341     ajDebug("[DB done]\n\n");
3342 
3343     return;
3344 }
3345 
3346 
3347 
3348 
3349 /* @func ajNamDebugResources **************************************************
3350 **
3351 ** Writes a simple debug report of all databases in the internal table.
3352 **
3353 ** @return [void]
3354 **
3355 ** @release 2.7.0
3356 ** @@
3357 ******************************************************************************/
3358 
ajNamDebugResources(void)3359 void ajNamDebugResources(void)
3360 {
3361     ajDebug("RES resources\n");
3362     ajDebug("=============\n");
3363     namDebugMaster(namResMasterTable, TYPE_RESOURCE);
3364     ajDebug("[RES done]\n\n");
3365 
3366     return;
3367 }
3368 
3369 
3370 
3371 
3372 /* @func ajNamDebugVariables **************************************************
3373 **
3374 ** Writes a simple debug report of all environment variables
3375 ** in the internal table.
3376 **
3377 ** @return [void]
3378 **
3379 ** @release 2.7.0
3380 ** @@
3381 ******************************************************************************/
3382 
ajNamDebugVariables(void)3383 void ajNamDebugVariables(void)
3384 {
3385     ajDebug("ENV variables\n");
3386     ajDebug("=============\n");
3387     namDebugMaster(namVarMasterTable, TYPE_ENV);
3388     ajDebug("[ENV done]\n\n");
3389 
3390     return;
3391 }
3392 
3393 
3394 
3395 
3396 /* @func ajNamDebugAliases ****************************************************
3397 **
3398 ** Writes a simple debug report of all aliases
3399 ** in the internal table.
3400 **
3401 ** @return [void]
3402 **
3403 ** @release 6.4.0
3404 ** @@
3405 ******************************************************************************/
3406 
ajNamDebugAliases(void)3407 void ajNamDebugAliases(void)
3408 {
3409     ajDebug("ALIAS names\n");
3410     ajDebug("=============\n");
3411     namDebugMaster(namAliasMasterTable, TYPE_ALIAS);
3412     ajDebug("[ALIAS done]\n\n");
3413 
3414     return;
3415 }
3416 
3417 
3418 
3419 
3420 /* @func ajNamListListServers *************************************************
3421 **
3422 ** Creates a AjPList list of all servers in the internal table.
3423 **
3424 ** @param [w] svrnames [AjPList] Str List of names to be populated
3425 ** @return [void]
3426 **
3427 ** @release 6.4.0
3428 ** @@
3429 ******************************************************************************/
3430 
ajNamListListServers(AjPList svrnames)3431 void ajNamListListServers(AjPList svrnames)
3432 {
3433     ajint i;
3434     NamPEntry fnew;
3435     void **valarray =  NULL;
3436 
3437     ajTableToarrayValues(namSvrMasterTable, &valarray);
3438     ajDebug("ajNamListListSevers\n");
3439 
3440     for(i = 0; valarray[i]; i++)
3441     {
3442 	fnew = (NamPEntry) valarray[i];
3443 	ajDebug("SVR: %S\n", fnew->name);
3444 	ajListstrPushAppend(svrnames, fnew->name);
3445     }
3446 
3447     AJFREE(valarray);
3448 
3449     return;
3450 }
3451 
3452 
3453 
3454 
3455 /* @func ajNamListFindAliases *************************************************
3456 **
3457 ** Creates a list of alias for a named database in the internal table.
3458 **
3459 ** @param [r] dbname [const AjPStr] Database name
3460 ** @param [w] dbnames [AjPList] Str List of names to be populated
3461 ** @return [void]
3462 **
3463 ** @release 6.6.0
3464 ** @@
3465 ******************************************************************************/
3466 
ajNamListFindAliases(const AjPStr dbname,AjPList dbnames)3467 void ajNamListFindAliases(const AjPStr dbname, AjPList dbnames)
3468 {
3469     ajint i;
3470     NamPEntry fnew;
3471     AjPStr testname = ajStrNewS(dbname);
3472     void **valarray =  NULL;
3473 
3474     ajStrFmtLower(&testname);
3475 
3476     ajTableToarrayValues(namAliasMasterTable, &valarray);
3477     ajDebug("ajNamListFindAliases '%S'\n", dbname);
3478 
3479     for(i = 0; valarray[i]; i++)
3480     {
3481 	fnew = (NamPEntry) valarray[i];
3482 
3483         if(!ajStrMatchS(testname, fnew->value))
3484             continue;
3485 
3486 	ajDebug("ALIAS: %S %S\n", fnew->name, fnew->value);
3487 	ajListstrPushAppend(dbnames, fnew->name);
3488     }
3489 
3490     ajListSort(dbnames, ajStrVcmp);
3491 
3492     ajStrDel(&testname);
3493     AJFREE(valarray);
3494 
3495     return;
3496 }
3497 
3498 
3499 
3500 
3501 /* @func ajNamListListAliases *************************************************
3502 **
3503 ** Creates a AjPList list of all databases in the internal table.
3504 **
3505 ** @param [w] dbnames [AjPList] Str List of names to be populated
3506 ** @return [void]
3507 **
3508 ** @release 6.6.0
3509 ** @@
3510 ******************************************************************************/
3511 
ajNamListListAliases(AjPList dbnames)3512 void ajNamListListAliases(AjPList dbnames)
3513 {
3514     ajint i;
3515     NamPEntry fnew;
3516     void **valarray =  NULL;
3517 
3518     ajTableToarrayValues(namAliasMasterTable, &valarray);
3519     ajDebug("ajNamListListAliases\n");
3520 
3521     for(i = 0; valarray[i]; i++)
3522     {
3523 	fnew = (NamPEntry) valarray[i];
3524 	ajDebug("ALIAS: %S %S\n", fnew->name, fnew->value);
3525 	ajListstrPushAppend(dbnames, fnew->name);
3526     }
3527 
3528     ajListSort(dbnames, ajStrVcmp);
3529 
3530     AJFREE(valarray);
3531 
3532     return;
3533 }
3534 
3535 
3536 
3537 
3538 /* @func ajNamListListDatabases ***********************************************
3539 **
3540 ** Creates a AjPList list of all databases in the internal table.
3541 **
3542 ** @param [w] dbnames [AjPList] Str List of names to be populated
3543 ** @return [void]
3544 **
3545 ** @release 1.0.0
3546 ** @@
3547 ******************************************************************************/
3548 
ajNamListListDatabases(AjPList dbnames)3549 void ajNamListListDatabases(AjPList dbnames)
3550 {
3551     ajint i;
3552     NamPEntry fnew;
3553     void **valarray =  NULL;
3554 
3555     ajTableToarrayValues(namDbMasterTable, &valarray);
3556     ajDebug("ajNamListListDatabases\n");
3557 
3558     for(i = 0; valarray[i]; i++)
3559     {
3560 	fnew = (NamPEntry) valarray[i];
3561 	ajDebug("DB: %S\n", fnew->name);
3562 	ajListstrPushAppend(dbnames, fnew->name);
3563     }
3564 
3565     ajListSort(dbnames, ajStrVcmp);
3566 
3567     AJFREE(valarray);
3568 
3569     return;
3570 }
3571 
3572 
3573 
3574 
3575 /* @func ajNamListListResources ***********************************************
3576 **
3577 ** Creates a AjPList list of all databases in the internal table.
3578 **
3579 ** @param [w] rsnames [AjPList] Str List of names to be populated
3580 ** @return [void]
3581 **
3582 ** @release 2.7.0
3583 ** @@
3584 ******************************************************************************/
3585 
ajNamListListResources(AjPList rsnames)3586 void ajNamListListResources(AjPList rsnames)
3587 {
3588     ajint i;
3589     NamPEntry fnew;
3590     void **valarray = NULL;
3591 
3592     ajTableToarrayValues(namResMasterTable, &valarray);
3593 
3594     for(i = 0; valarray[i]; i++)
3595     {
3596 	fnew = (NamPEntry) valarray[i];
3597 	ajDebug("RES: %S\n", fnew->name);
3598 	ajListstrPushAppend(rsnames, fnew->name);
3599     }
3600 
3601     AJFREE(valarray);
3602 
3603     return;
3604 }
3605 
3606 
3607 
3608 
3609 /* @funcstatic namDebugVariables **********************************************
3610 **
3611 ** Writes a simple list of all variables in the internal table.
3612 **
3613 ** @return [void]
3614 **
3615 ** @release 2.7.0
3616 ** @@
3617 ******************************************************************************/
3618 
namDebugVariables(void)3619 static void namDebugVariables(void)
3620 {
3621     namUser("ENV---------->\n");
3622     namDebugMaster(namVarMasterTable, TYPE_ENV);
3623     namUser("ENV---------->\n");
3624     namUser("\n");
3625 
3626     return;
3627 }
3628 
3629 
3630 
3631 
3632 /* @funcstatic namDebugAliases ************************************************
3633 **
3634 ** Writes a simple list of all aliases in the internal table.
3635 **
3636 ** @return [void]
3637 **
3638 ** @release 6.4.0
3639 ** @@
3640 ******************************************************************************/
3641 
namDebugAliases(void)3642 static void namDebugAliases(void)
3643 {
3644     namUser("ALIAS---------->\n");
3645     namDebugMaster(namAliasMasterTable, TYPE_ALIAS);
3646     namUser("ALIAS---------->\n");
3647     namUser("\n");
3648 
3649     return;
3650 }
3651 
3652 
3653 
3654 
3655 /* @funcstatic namListParse ***************************************************
3656 **
3657 ** Parse the text in a list of tokens read from the input file.
3658 ** Derive environment variable and database definitions. Store
3659 ** all these in the internal tables.
3660 **
3661 ** @param [u] listwords [AjPList] String list of word tokens to parse
3662 ** @param [u] listcount [AjPList] List of word counts per line for
3663 **                                generating error messages
3664 ** @param [u] file [AjPFile] Input file only for name in messages
3665 ** @param [r] shortname [const AjPStr] Definition file short name
3666 ** @return [void]
3667 **
3668 ** @release 1.0.0
3669 ** @@
3670 ******************************************************************************/
3671 
namListParse(AjPList listwords,AjPList listcount,AjPFile file,const AjPStr shortname)3672 static void namListParse(AjPList listwords, AjPList listcount,
3673 			 AjPFile file, const AjPStr shortname)
3674 {
3675     static char* tabname   = NULL;
3676     static AjPStr name     = NULL;
3677     AjPStr value    = NULL;
3678     static NamPAttr attrvalue  = NULL;
3679     static char quoteopen  = '\0';
3680     static char quoteclose = '\0';
3681     static AjPTable svattr  = NULL;
3682     static AjPTable dbattr  = NULL;
3683     static AjPTable rsattr  = NULL;
3684     static ajint  svr_input = -1;
3685     static ajint  db_input = -1;
3686     static ajint  rs_input = -1;
3687     AjPStr rs_name = NULL;
3688     AjPTable saveTable = NULL;
3689 
3690     NamPEntry fnew  = NULL;
3691     NamPEntry entry = NULL;
3692 
3693     AjBool svrsave = ajFalse;
3694     AjBool dbsave = ajFalse;
3695     AjBool rssave = ajFalse;
3696     AjBool saveit = ajFalse;
3697     AjBool saveifblock = ajFalse;
3698     static ajint nsvrattr = 0;
3699     static ajint ndbattr = 0;
3700     static ajint ndbtype = 0;
3701     static ajint nrsattr = 0;
3702 
3703     AjPStr includefn = NULL;
3704     AjPFile iinf     = NULL;
3705     AjPStr key       = NULL;
3706     AjPStr val       = NULL;
3707     AjPStr oldval    = NULL;
3708 
3709     static AjPTable Ifiles = NULL;
3710     AjPStr curword = NULL;
3711 
3712     ajint wordcount = 0;
3713     ajint linecount = 0;
3714     ajint lineword  = 0;
3715     ajint *iword    = NULL;
3716     AjBool namstatus;
3717     AjPStr saveshortname = NULL;
3718     AjPStr saveword = NULL;
3719     AjPStr teststr = NULL;
3720 
3721     namUser("namListParse shortname: '%S'\n", shortname);
3722 
3723     /* ndbtype = count database types*/
3724     if(!ndbtype)
3725     {
3726         if(!namDbTypeTable)
3727             namDbTypeTable = ajTablestrNewCase(30);
3728 
3729 	for(ndbtype=0; namDbTypes[ndbtype].Name; ndbtype++)
3730         {
3731             name = ajStrNewC(namDbTypes[ndbtype].Name);
3732             ajTablePut(namDbTypeTable, name, &namDbTypes[ndbtype]);
3733          }
3734 
3735         name = NULL;
3736     }
3737 
3738     /* nsvrattr = count server attributes */
3739     if(!nsvrattr)
3740     {
3741         if(!namSvrAttrTable)
3742             namSvrAttrTable = ajTablestrNew(30);
3743 
3744 	for(nsvrattr=0; namSvrAttrs[nsvrattr].Name; nsvrattr++)
3745         {
3746             name = ajStrNewC(namSvrAttrs[nsvrattr].Name);
3747             attrvalue = &namSvrAttrs[nsvrattr];
3748             oldval = ajTablePut(namSvrAttrTable, name, attrvalue);
3749             namUser("store server default '%S' => '%s\n",
3750                     name, attrvalue->Defval);
3751 
3752             if(oldval)
3753             {
3754                 ajWarn("duplicate server attr value for '%S' = '%S'",
3755                        name, oldval);
3756                 ajStrDel(&oldval);
3757             }
3758         }
3759 
3760         name = NULL;
3761         value = NULL;
3762     }
3763 
3764     /* ndbattr = count database attributes */
3765     if(!ndbattr)
3766     {
3767         if(!namDbAttrTable)
3768             namDbAttrTable = ajTablestrNew(30);
3769 
3770 	for(ndbattr=0; namDbAttrs[ndbattr].Name; ndbattr++)
3771         {
3772             name = ajStrNewC(namDbAttrs[ndbattr].Name);
3773             attrvalue = &namDbAttrs[ndbattr];
3774             oldval = ajTablePut(namDbAttrTable, name, attrvalue);
3775             namUser("store database default '%S' => '%s\n",
3776                     name, attrvalue->Defval);
3777 
3778             if(oldval)
3779             {
3780                 ajWarn("duplicate db attr value for '%S' = '%S'",
3781                        name, oldval);
3782                 ajStrDel(&oldval);
3783             }
3784         }
3785 
3786         name = NULL;
3787         value = NULL;
3788     }
3789 
3790     /* nrsattr = count resource attributes */
3791     if(!nrsattr)
3792     {
3793         if(!namResAttrTable)
3794             namResAttrTable = ajTablestrNew(30);
3795 
3796 	for(nrsattr=0; namRsAttrs[nrsattr].Name; nrsattr++)
3797         {
3798             name = ajStrNewC(namRsAttrs[nrsattr].Name);
3799             attrvalue = &namRsAttrs[nrsattr];
3800             oldval = ajTablePut(namResAttrTable, name, attrvalue);
3801             namUser("store resource default '%S' => '%s\n",
3802                     name, attrvalue->Defval);
3803 
3804             if(oldval)
3805             {
3806                 ajWarn("duplicate res attr value for '%S' = '%S'",
3807                        name, oldval);
3808                 ajStrDel(&oldval);
3809             }
3810         }
3811 
3812         name = NULL;
3813         value = NULL;
3814     }
3815 
3816     ajStrAssignS(&saveshortname, shortname);
3817     ajStrDel(&name);
3818     ajStrDel(&value);
3819     quoteopen  = '\0';
3820     quoteclose = '\0';
3821 
3822     namLine = 1;
3823     namUser("namListParse of %F '%S' words: %Lu lines: %Lu\n",
3824 	    file, name, ajListGetLength(listwords), ajListGetLength(listcount));
3825 
3826     while(ajListstrPop(listwords, &curword))
3827     {
3828 	while(ajListGetLength(listcount) && (lineword < wordcount))
3829 	{
3830 	    namUser("ajListPop %d < %d list %Lu\n",
3831 		    lineword, wordcount, ajListGetLength(listcount));
3832 	    ajListPop(listcount, (void**) &iword);
3833 	    lineword = *iword;
3834 	    linecount++;
3835 	    namLine = linecount-1;
3836 	    AJFREE(iword);
3837 	}
3838 
3839 	wordcount++;
3840 
3841 	namUser("namListParse word: %d line: %d (%d) <%S>\n",
3842 		wordcount, namLine, lineword, curword);
3843 
3844 	if(!namParseType)
3845 	{
3846 	    namNoColon(&curword);
3847 	    ajStrFmtLower(&curword);
3848 
3849 	    if(ajCharPrefixS("env", curword))
3850 		namParseType = TYPE_ENV;
3851 	    else if(ajCharPrefixS("setenv", curword))
3852 		namParseType = TYPE_ENV;
3853 	    else if(ajCharPrefixS("server",curword))
3854 		namParseType = TYPE_SVR;
3855 	    else if(ajCharPrefixS("dbname",curword))
3856 		namParseType = TYPE_DB;
3857 	    else if(ajCharPrefixS("resource",curword))
3858 		namParseType = TYPE_RESOURCE;
3859 	    else if(ajCharPrefixS("alias",curword))
3860 		namParseType = TYPE_ALIAS;
3861 	    else if(ajCharPrefixS("include",curword))
3862 		namParseType = TYPE_IFILE;
3863 	    else if(ajCharPrefixS("if",curword))
3864             {
3865                 namParseType = TYPE_IF;
3866                 saveifblock = ajFalse;
3867             }
3868 	    else if(ajCharPrefixS("ifdef",curword))
3869             {
3870                 namParseType = TYPE_IFDEF;
3871                 saveifblock = ajFalse;
3872             }
3873 	    else if(ajCharPrefixS("else",curword))
3874 		namParseType = TYPE_ELSE;
3875 	    else if(ajCharPrefixS("endif",curword))
3876 		namParseType = TYPE_ENDIF;
3877 
3878 	    if(!namParseType)		/* test: badtype.rc */
3879 		namError("Invalid definition type '%S'", curword);
3880 
3881 	    namUser("type set to %s curword '%S'\n",
3882 		    namTypes[namParseType], curword);
3883 	}
3884 	else if(quoteopen && ajStrMatchC(curword, "]"))
3885 	{				/* test; dbnoquote.rc */
3886 	    namError("']' found, unclosed quotes in '%S'", value);
3887 	    quoteopen    = '\0';
3888 	    namParseType = 0;
3889 	}
3890 	else if(quoteopen)
3891 	{
3892 	    /*
3893 	    ** quote is open, so append word until close quote is found,
3894 	    ** and set the appropriate save flag
3895 	    */
3896 	    namUser("<%c>..<%c> quote processing\n", quoteopen, quoteclose);
3897 	    ajStrAppendC(&value," ");
3898 	    ajStrAppendS(&value,curword);
3899 
3900 	    /* close quote here ?? */
3901 	    if(ajStrGetCharLast(curword) == quoteclose)
3902 	    {
3903 		namUser("close quotes\n");
3904 		ajStrCutEnd(&value, 1);
3905 		quoteopen = quoteclose = '\0';
3906 
3907 		if(namParseType == TYPE_ENV) /* set save flag, value found */
3908 		    saveit = ajTrue;
3909 		else if(namParseType == TYPE_SVR)
3910 		    svrsave = ajTrue;
3911 		else if(namParseType == TYPE_DB)
3912 		    dbsave = ajTrue;
3913 		else if(namParseType == TYPE_RESOURCE)
3914 		    rssave = ajTrue;
3915 		else if(namParseType == TYPE_ALIAS)
3916 		    saveit = ajTrue;
3917 		else if(namParseType == TYPE_IFDEF)
3918 		    saveifblock = ajTrue;
3919 		else if(namParseType == TYPE_IF)
3920 		    saveifblock = ajTrue;
3921 	    }
3922 	}
3923 	else if(namParseType == TYPE_IF || namParseType == TYPE_IFDEF )
3924 	{
3925             if(ajStrGetCharFirst(curword) == '\'')
3926                 quoteopen = quoteclose = '\'';
3927             else if(ajStrGetCharFirst(curword) == '\"')
3928                 quoteopen = quoteclose = '\"';
3929 
3930             ajStrAssignS(&value, curword);
3931 
3932             if(quoteopen)
3933             {
3934                 /* trim the opening quote */
3935                 ajStrCutStart(&value, 1);
3936 
3937                 if(!ajStrGetLen(value))
3938                     ajErr("Bare quote %c found in namListParse",
3939                           quoteopen);
3940             }
3941             else
3942                 saveifblock = ajTrue;
3943 
3944             if(ajStrGetCharLast(curword) == quoteclose)
3945             {
3946                 /* end of quote on same word */
3947                 quoteopen = quoteclose = '\0';
3948                 /* remove quote at the end */
3949                 ajStrCutEnd(&value, 1);
3950                 saveifblock = ajTrue;
3951             }
3952 
3953             namUser("if: save value '%S' saveif: %B\n", value, saveifblock);
3954         }
3955 	else if(namParseType == TYPE_ENV)
3956 	{
3957 	    if(name && value)
3958 		saveit= ajTrue;
3959 	    else if(name)
3960 	    {
3961 		/* if name already got then it must be the value */
3962 		if(ajStrGetCharFirst(curword) == '\'')
3963 		    quoteopen = quoteclose = '\'';
3964 		else if(ajStrGetCharFirst(curword) == '\"')
3965 		    quoteopen = quoteclose = '\"';
3966 
3967 		ajStrAssignS(&value, curword);
3968 
3969 		if(quoteopen)
3970 		{
3971 		    /* trim the opening quote */
3972 		    ajStrCutStart(&value, 1);
3973 
3974 		    if(!ajStrGetLen(value))
3975 			ajErr("Bare quote %c found in namListParse",
3976 			       quoteopen);
3977 		}
3978 		else
3979 		    saveit = ajTrue;
3980 
3981 		if(ajStrGetCharLast(curword) == quoteclose)
3982 		{
3983 		    /* end of quote on same word */
3984 		    quoteopen = quoteclose = '\0';
3985 		    saveit= ajTrue;
3986 		    /* remove quote at the end */
3987 		    ajStrCutEnd(&value, 1);
3988 		}
3989 
3990                 if(saveit)
3991                     ajNamResolve(&value);
3992 		namUser("save value '%S' saveit: %B\n", value, saveit);
3993 	    }
3994 	    else
3995 	    {
3996 		ajStrAssignS(&name, curword);
3997 		namUser("save name '%S'\n", name);
3998 	    }
3999 	}
4000 
4001         else if(namParseType == TYPE_ALIAS)
4002 	{
4003             namUser("ALIAS saveit: %B name: '%S' value '%S' "
4004                     "quoteopen: '%c'\n",
4005                     saveit, name, value, quoteopen);
4006 	    if(name && value)
4007 		saveit= ajTrue;
4008 	    else if(name)
4009 	    {
4010 		/* if name already got then it must be the value */
4011 		if(ajStrGetCharFirst(curword) == '\'')
4012 		    quoteopen = quoteclose = '\'';
4013 		else if(ajStrGetCharFirst(curword) == '\"')
4014 		    quoteopen = quoteclose = '\"';
4015 
4016 		ajStrAssignS(&value, curword);
4017 
4018 		if(quoteopen)
4019 		{
4020 		    /* trim the opening quote */
4021 		    ajStrCutStart(&value, 1);
4022 
4023 		    if(!ajStrGetLen(value))
4024 			ajErr("Bare quote %c found in namListParse",
4025 			       quoteopen);
4026 		}
4027 		else
4028 		    saveit = ajTrue;
4029 
4030 		if(ajStrGetCharLast(curword) == quoteclose)
4031 		{
4032 		    /* end of quote on same word */
4033 		    quoteopen = quoteclose = '\0';
4034 		    saveit= ajTrue;
4035 		    /* remove quote at the end */
4036 		    ajStrCutEnd(&value, 1);
4037 		}
4038 
4039                 if(saveit)
4040                     ajNamResolve(&value);
4041 		namUser("save alias value '%S' saveit: %B\n", value, saveit);
4042 	    }
4043 	    else
4044 	    {
4045 		ajStrAssignS(&name, curword);
4046 		namUser("save alias name '%S'\n", name);
4047 	    }
4048 	}
4049 
4050 
4051 	else if(namParseType == TYPE_SVR)
4052 	{
4053 	    if(ajStrMatchC(curword, "[")) /* [ therefore new server */
4054 		svattr = ajTablestrNew(100); /* new server obj */
4055 	    else if(ajStrMatchC(curword, "]"))	/* ] therefore end of server */
4056 		saveit = ajTrue;
4057 	    else if(name)
4058 	    {
4059 		if(svr_input >= 0)
4060 		{
4061 		    /* So if keyword type has been set */
4062 		    if(ajStrGetCharFirst(curword) == '\'')
4063 		    {
4064 			/* is there a quote? If so expect the */
4065 			/* same at the end. No ()[] etc here*/
4066 			quoteopen = quoteclose = '\'';
4067 		    }
4068 		    else if(ajStrGetCharFirst(curword) == '\"')
4069 			quoteopen = quoteclose = '\"';
4070 
4071 		    ajStrAssignS(&value, curword);
4072 
4073 		    if(quoteopen)
4074 		    {
4075 			ajStrCutStart(&value, 1); /* trim opening quote */
4076 
4077 			if(!ajStrGetLen(value))
4078 			    ajErr("Bare quote %c found in namListParse",
4079 				   quoteopen);
4080 		    }
4081 		    else
4082 			svrsave = ajTrue; /* we are done - simple word */
4083 
4084 		    if(ajStrGetCharLast(curword) == quoteclose)
4085 		    {
4086 			quoteopen = quoteclose = '\0';
4087 			ajStrCutEnd(&value,1); /* trim closing quote */
4088 			svrsave = ajTrue;
4089 		    }
4090 
4091 		    if(!quoteopen)     /* if we just reset it above */
4092 			svrsave = ajTrue;
4093 
4094                     if(svrsave)
4095                         ajNamResolve(&value);
4096 		}
4097 		else if(ajStrGetCharLast(curword) == ':')
4098 		{
4099 		    /* if last character is : then its a keyword */
4100 		    ajStrFmtLower(&curword); /* make it lower case */
4101 		    namNoColon(&curword);
4102 		    svr_input = namSvrAttrS(curword);
4103 
4104 		    if(svr_input < 0)
4105 			ajWarn("%F: bad attribute '%S' for server '%S'",
4106 				file, curword, name);
4107 		}
4108                 else
4109                 {
4110                     ajWarn("%F: unexpected token '%S' for server '%S'",
4111                            file, curword, name);
4112                 }
4113 	    }
4114 	    else
4115 	    {
4116 		ajStrAssignS(&name, curword);
4117 
4118 		if(!ajNamIsDbname(name))
4119 		    ajErr("Invalid server name '%S'", name);
4120 
4121 		namUser("saving svr name '%S'\n", name);
4122 	    }
4123 	}
4124 
4125 	else if(namParseType == TYPE_DB)
4126 	{
4127 	    if(ajStrMatchC(curword, "[")) /* [ therefore new database */
4128 		dbattr = ajTablestrNew(100); /* new db obj */
4129 	    else if(ajStrMatchC(curword, "]"))	/* ] therefore end of db */
4130 		saveit = ajTrue;
4131 	    else if(name)
4132 	    {
4133 		if(db_input >= 0)
4134 		{
4135 		    /* So if keyword type has been set */
4136 		    if(ajStrGetCharFirst(curword) == '\'')
4137 		    {
4138 			/* is there a quote? If so expect the */
4139 			/* same at the end. No ()[] etc here*/
4140 			quoteopen = quoteclose = '\'';
4141 		    }
4142 		    else if(ajStrGetCharFirst(curword) == '\"')
4143 			quoteopen = quoteclose = '\"';
4144 
4145 		    ajStrAssignS(&value, curword);
4146 
4147 		    if(quoteopen)
4148 		    {
4149 			ajStrCutStart(&value, 1); /* trim opening quote */
4150 
4151 			if(!ajStrGetLen(value))
4152 			    ajErr("Bare quote %c found in namListParse",
4153 				   quoteopen);
4154 		    }
4155 		    else
4156 			dbsave = ajTrue; /* we are done - simple word */
4157 
4158 		    if(ajStrGetCharLast(curword) == quoteclose)
4159 		    {
4160 			quoteopen = quoteclose = '\0';
4161 			ajStrCutEnd(&value,1); /* trim closing quote */
4162 			dbsave = ajTrue;
4163 		    }
4164 
4165 		    if(!quoteopen)     /* if we just reset it above */
4166 			dbsave = ajTrue;
4167 
4168                     if(dbsave)
4169                         ajNamResolve(&value);
4170 		}
4171 		else if(ajStrGetCharLast(curword) == ':')
4172                 {
4173                     /* if last character is : then its a keyword */
4174                     ajStrFmtLower(&curword); /* make it lower case */
4175                     namNoColon(&curword);
4176                     db_input = namDbAttrS(curword);
4177 
4178                     if(db_input < 0)
4179                         ajWarn("%F: bad attribute '%S' for database '%S'",
4180                                file, curword, name);
4181                 }
4182                 else
4183                 {
4184                     ajWarn("%F: unexpected token '%S' for database '%S'",
4185                            file, curword, name);
4186                 }
4187             }
4188 	    else
4189 	    {
4190 		ajStrAssignS(&name, curword);
4191 
4192 		if(!ajNamIsDbname(name))
4193 		    ajErr("Invalid database name '%S'", name);
4194 
4195 		namUser("saving db name '%S'\n", name);
4196 	    }
4197 	}
4198 
4199 
4200 	else if(namParseType == TYPE_RESOURCE)
4201 	{
4202 	    if(ajStrMatchC(curword, "[")) /* [ therefore new resource */
4203 		rsattr = ajTablestrNew(100); /* new resource*/
4204 	    else if(ajStrMatchC(curword, "]"))	/* ] end of resource */
4205 		saveit = ajTrue;
4206 	    else if(name)
4207 	    {
4208                 /* if last character is : */
4209 		if(ajStrGetCharLast(curword) == ':')
4210 		{		     	     /* then it is a keyword */
4211 		    ajStrFmtLower(&curword); /* make it lower case */
4212 		    namNoColon(&curword);
4213 		    rs_input = namRsAttrS(curword);
4214                     ajStrDel(&rs_name);
4215 
4216 		    if(rs_input < 0)	/* test: badresattr.rc */
4217                     {
4218                         if(namRsAttrFieldS(rsattr, curword))
4219                         {
4220                             rs_name = ajStrNewRef(curword);
4221                         }
4222                         else
4223                             namError("Bad attribute '%S' for resource '%S'",
4224                                      curword, name);
4225                     }
4226 		}
4227 		else if(rs_name || rs_input >= 0)
4228 		{		 /* So if keyword type has been set */
4229 		    if(ajStrGetCharFirst(curword) == '\'')
4230 		    {	      /* is there a quote? If so expect the */
4231 			/* same at the end. No ()[] etc here */
4232 			quoteopen = quoteclose = '\'';
4233 		    }
4234 		    else if(ajStrGetCharFirst(curword) == '\"')
4235 			quoteopen = quoteclose = '\"';
4236 
4237 		    ajStrAssignS(&value, curword);
4238 
4239 		    if(quoteopen)
4240 		    {
4241 			ajStrCutStart(&value, 1); /* trim opening quote */
4242 
4243 			if(!ajStrGetLen(value))
4244 			    ajErr("Bare quote %c found in namListParse",
4245 				   quoteopen);
4246 		    }
4247 		    else
4248 			rssave = ajTrue;
4249 
4250 		    if(ajStrGetCharLast(curword) == quoteclose)
4251 		    {
4252 			quoteopen = quoteclose = '\0';
4253 			ajStrCutEnd(&value,1); /* ignore quote if */
4254 					             /* one at end */
4255 			rssave = ajTrue;
4256 		    }
4257 
4258 		    if(!quoteopen)
4259 			rssave = ajTrue;
4260 		}
4261 
4262                 if(rssave)
4263                     ajNamResolve(&value);
4264 	    }
4265 	    else
4266 	    {
4267 		ajStrAssignS(&name, curword);
4268 		namUser("saving resource name '%S'\n", name);
4269 	    }
4270 	}
4271 
4272 
4273 	else if(namParseType == TYPE_IFILE)
4274 	{
4275 	    if(!Ifiles)
4276 		Ifiles = ajTablestrNew(NAM_INCLUDE_ESTIMATE);
4277 	    namParseType = 0;
4278 
4279             ajStrAssignS(&saveword, curword);
4280 
4281             ajNamResolve(&curword);
4282 
4283 	    if(ajTableFetchmodS(Ifiles,curword)) /* test: includeagain.rc */
4284             {
4285 		if(ajStrMatchS(curword, saveword))
4286                     namError("%S already read ... skipping", curword);
4287                 else
4288                     namError("%S (%S) already read ... skipping",
4289                              saveword, curword);
4290             }
4291 	    else
4292 	    {
4293 		includefn = ajStrNew();
4294 		ajStrAssignS(&includefn,curword);
4295 
4296 		if(namFileOrig)
4297 		    ajStrAppendC(&namFileOrig,", ");
4298 		ajStrAppendS(&namFileOrig,includefn);
4299 
4300 		key = ajStrNewS(includefn);
4301 		val = ajStrNewS(includefn);
4302 		oldval = ajTablePut(Ifiles,key,val);
4303                 namUser("store file '%S' => '%S\n", key, val);
4304 
4305                 if(oldval)
4306                 {
4307                     ajWarn("duplicate include value for '%S' = '%S'",
4308                            key, oldval);
4309                     ajStrDel(&key);
4310                     ajStrDel(&oldval);
4311                 }
4312 
4313                 /* test: badinclude.rc */
4314 		if(!(iinf = ajFileNewInNameS(includefn)))
4315 		{
4316                     if(ajStrMatchS(includefn, saveword))
4317                         namError("Failed to open include file '%S'",
4318                                  includefn);
4319                     else
4320                         namError("Failed to open include file '%S' (%S)",
4321                                  saveword, includefn);
4322 		    ajStrAppendC(&namFileOrig,"(Failed)");
4323 		}
4324 		else
4325 		{
4326 		    ajStrAppendC(&namFileOrig,"(OK)");
4327                     /* replaces namFile */
4328                     ajStrAssignS(&name, includefn);
4329                     ajFilenameTrimPath(&name);
4330 		    namstatus = namProcessFile(iinf, name);
4331 		    ajFmtPrintS(&namFileName, "%F",file);/* reset saved name */
4332 		    namLine = linecount-1;
4333 
4334 		    if(!namstatus)	/* test: badsummary.rc */
4335                     {
4336                         if(ajStrMatchS(includefn, saveword))
4337                             namError("Error(s) found in included file %F",
4338                                      iinf);
4339                         else
4340                             namError("Error(s) found in included file %S (%F)",
4341                                      saveword, iinf);
4342                     }
4343 
4344 
4345 		    ajFileClose(&iinf);
4346 		}
4347 
4348 		ajStrDel(&includefn);
4349 	    }
4350 
4351 	    namListParseOK = ajTrue;
4352 	}
4353 
4354 
4355 	if(svrsave)
4356 	{
4357 	    /* Save the keyword value */
4358             key = ajStrNewC(namSvrAttrs[svr_input].Name);
4359             namUser("store svr attr '%S' => '%S\n", key, value);
4360             namSvrtablePutAttrS(svattr, &key, &value);
4361 
4362 	    svr_input =-1;
4363 	    svrsave = ajFalse;
4364 	}
4365 
4366 	if(dbsave)
4367 	{
4368 	    /* Save the keyword value */
4369             key = ajStrNewC(namDbAttrs[db_input].Name);
4370             namDbtablePutAttrS(dbattr, &key, &value);
4371 
4372 	    db_input =-1;
4373 	    dbsave = ajFalse;
4374 	}
4375 
4376 	if(rssave)
4377 	{
4378             if(rs_input >= 0)
4379                 /* Save the keyword value */
4380                 key = ajStrNewC(namRsAttrs[rs_input].Name);
4381             else
4382                 key = ajStrNewS(rs_name);
4383             namUser("store resource attr '%S' => '%S\n", key, value);
4384             namRstablePutAttrS(rsattr, &key, &value);
4385 
4386 	    rs_input =-1;
4387             ajStrDel(&rs_name);
4388 	    rssave = ajFalse;
4389 	}
4390 
4391 	namListParseOK = saveit;
4392 
4393         if(namParseType == TYPE_ENDIF)
4394         {
4395             if(!namIfBlock)
4396             {
4397                 namError("endif not in if-block");
4398             }
4399             else
4400             {
4401                 --namIfBlock;
4402                 ajListPop(namIfList, (void**) &namIfValue);
4403                 namUser("endif restore %B (block %u)\n",
4404                        namIfValue, namIfBlock);
4405 
4406                 if(*namIfValue)
4407                     namIfNow = ajTrue;
4408                 else
4409                     namIfNow = ajFalse;
4410             }
4411             namUser("endif %B (block %u)\n", namIfNow, /* FIXME teststr, */ namIfBlock);
4412             ajStrDel(&teststr);
4413             namParseType = 0;
4414 	    namListParseOK = ajTrue;
4415         }
4416         else if(namParseType == TYPE_ELSE)
4417         {
4418             namIfNow = !namIfNow;
4419             namUser("else %B (block %u)\n", namIfNow, namIfBlock);
4420             namParseType = 0;
4421 	    namListParseOK = ajTrue;
4422         }
4423 
4424 	if(saveifblock)
4425 	{
4426             if(namParseType == TYPE_IF || namParseType == TYPE_IFDEF )
4427             {
4428                 ajNamResolve(&value);
4429 
4430                 namUser("if: '%S'\n", value);
4431 
4432                 if(!namIfList)
4433                     namIfList = ajListNew();
4434 
4435                 if(namIfNow)
4436                     ajListPush(namIfList, (void*) &namTrue);
4437                 else
4438                     ajListPush(namIfList, (void*) &namFalse);
4439 
4440                 ++namIfBlock;
4441 
4442                 if(namParseType == TYPE_IF)
4443                 {
4444                     ajNamGetValueS(value, &teststr);
4445                     namUser("if '%S' '%S'\n", value, teststr);
4446                     if(!ajStrToBool(teststr, &namIfNow))
4447                         namIfNow = ajFalse;
4448                 }
4449                 else
4450                 {
4451                     namUser("ifdef '%S'\n", value);
4452                     if(ajNamGetValueS(value, &teststr))
4453                         namIfNow = ajTrue;
4454                     else
4455                         namIfNow = ajFalse;
4456                 }
4457 
4458                 namUser("if value '%S' '%S' %B (block %u)\n",
4459                        value, teststr, namIfNow, namIfBlock);
4460                 namParseType = 0;
4461                 ajStrDel(&teststr);
4462                 namListParseOK = ajTrue;
4463                 ajStrDel(&value);
4464             }
4465             saveifblock = ajFalse;
4466         }
4467 
4468 	else if(saveit)
4469 	{
4470             if(!namIfNow)
4471             {
4472                 namUser("skipping type %d name '%S' value '%S' line:%d\n",
4473                         namParseType, name, value, namLine);
4474                 ajStrDel(&name);
4475                 saveTable = NULL;
4476 
4477 		namSvrAttrtableFree(&svattr);
4478                 namDbAttrtableFree(&dbattr);
4479                 namRsAttrtableFree(&rsattr);
4480             }
4481             else
4482             {
4483                 namUser("saving type %d name '%S' value '%S' line:%d\n",
4484                         namParseType, name, value, namLine);
4485                 AJNEW0(fnew);
4486                 tabname = ajCharNewS(name);
4487                 fnew->name = name;
4488                 name = NULL;
4489                 fnew->value = value;
4490                 value = NULL;
4491                 fnew->file = ajStrNewRef(saveshortname);
4492 
4493                 if(namParseType == TYPE_SVR)
4494                 {
4495                     fnew->data = (AjPTable) svattr;
4496                     saveTable = namSvrMasterTable;
4497                     svattr = NULL;
4498                 }
4499                 else if(namParseType == TYPE_DB)
4500                 {
4501                     fnew->data = (AjPTable) dbattr;
4502                     saveTable = namDbMasterTable;
4503                     dbattr = NULL;
4504                 }
4505                 else if(namParseType == TYPE_RESOURCE)
4506                 {
4507                     fnew->data = (AjPTable) rsattr;
4508                     saveTable = namResMasterTable;
4509                     rsattr = NULL;
4510                 }
4511                 else if(namParseType == TYPE_ENV)
4512                 {
4513                     fnew->data = NULL;
4514                     saveTable = namVarMasterTable;
4515                 }
4516                 else if(namParseType == TYPE_ALIAS)
4517                 {
4518                     fnew->data = NULL;
4519                     saveTable = namAliasMasterTable;
4520                 }
4521                 else
4522                 {
4523                     fnew->data = NULL;
4524                 }
4525 
4526                 /* Validate the master table entry */
4527 
4528                 if(namDoValid)
4529                     namValid(fnew, namParseType);
4530 
4531                 /*
4532                 ** Add new one to table
4533                 ** be very careful that everything in the table
4534                 ** is not about to be deallocated - so do not use "name" here
4535                 */
4536 
4537                 entry = ajTablePut(saveTable, tabname, fnew);
4538                 namUser("store entry '%s' '%S' (%S)\n",
4539                         tabname, fnew->name, fnew->file);
4540                 if(entry)
4541                 {
4542                     /* it existed so over wrote previous table entry
4543                     ** Only a namUser message - redefining EMBOSSRC in
4544                     ** QA testing can give too many warnings
4545                     */
4546                     namUser("namTypes: [%d] '%s'\n",
4547                             namParseType, namTypes[namParseType]);
4548                     namUser("shortname: '%S'\n",
4549                             shortname);
4550                     namUser("entry: '%S' in file '%S'\n",
4551                             entry->name, entry->file);
4552                     namUser("%S: replaced %s %S definition from %S\n",
4553                             shortname,
4554                             namTypes[namParseType],
4555                             entry->name,
4556                             entry->file);
4557                     namEntryDelete(&entry, namParseType); /* previous entry */
4558                 }
4559 	    }
4560 
4561 	    saveit = ajFalse;
4562 	    namParseType = 0;
4563             saveTable = NULL;
4564 	}
4565 
4566 	ajStrDel(&curword);
4567     }
4568 
4569     if(namParseType)
4570     {
4571 	/* test: badset.rc baddb.rc  */
4572 	namError("Unexpected end of file in %s definition",
4573 		 namTypes[namParseType]);
4574 	namParseType = 0;
4575     }
4576 
4577     if(ajListGetLength(listcount))	/* cleanup the wordcount list */
4578     {
4579 	namUser("** remaining wordcount items: %lu\n",
4580                 ajListGetLength(listcount));
4581 
4582 	while(ajListGetLength(listcount))
4583 	{
4584 	    ajListPop(listcount, (void**) &iword);
4585 	    AJFREE(iword);
4586 	}
4587     }
4588 
4589     if(value)
4590 	namUser("++ namListParse value %x '%S'", value, value);
4591 
4592     ajStrDel(&saveword);
4593     ajStrDel(&saveshortname);
4594     ajTablestrFree(&Ifiles);
4595 
4596     return;
4597 }
4598 
4599 
4600 
4601 
4602 /* @func ajNamIsDbname ********************************************************
4603 **
4604 ** Returns true if the name is a valid database (or server) name.
4605 **
4606 ** Database names must start with a letter, and have 1 or more letters,
4607 ** numbers or underscores. No other characters are permitted.
4608 **
4609 ** @param [r] name [const AjPStr] character string to find in getenv list
4610 ** @return [AjBool] True if name was defined.
4611 **
4612 ** @release 3.0.0
4613 ** @@
4614 **
4615 ******************************************************************************/
4616 
ajNamIsDbname(const AjPStr name)4617 AjBool ajNamIsDbname(const AjPStr name)
4618 {
4619     const char* cp = ajStrGetPtr(name);
4620 
4621     if (!*cp)
4622 	return ajFalse;
4623 
4624     if (!isalpha((int)*cp++))
4625 	return ajFalse;
4626 
4627     if (!*cp)
4628 	return ajFalse;
4629 
4630     while (*cp)
4631     {
4632 	if(!isalnum((int)*cp) && (*cp != '_'))
4633 	    return ajFalse;
4634 
4635 	cp++;
4636     }
4637 
4638     return ajTrue;
4639 }
4640 
4641 
4642 
4643 
4644 /* @func ajNamGetenvC *********************************************************
4645 **
4646 ** Looks for name as an environment variable.
4647 ** the AjPStr for this in "value". If not found returns value as NULL;
4648 **
4649 ** @param [r] name [const char*] character string to find in getenv list
4650 ** @param [w] value [AjPStr*] String for the value.
4651 ** @return [AjBool] True if name was defined.
4652 **
4653 ** @release 2.9.0
4654 ** @@
4655 **
4656 ******************************************************************************/
4657 
ajNamGetenvC(const char * name,AjPStr * value)4658 AjBool ajNamGetenvC(const char* name,
4659 		    AjPStr* value)
4660 {
4661     char *envval;
4662 
4663     envval = getenv(name);
4664 
4665     if(envval)
4666     {
4667 	ajStrAssignC(value, envval);
4668 
4669 	return ajTrue;
4670     }
4671 
4672     ajStrDel(value);
4673 
4674     return ajFalse;
4675 }
4676 
4677 
4678 
4679 
4680 /* @func ajNamGetenvS *********************************************************
4681 **
4682 ** Looks for name as an environment variable.
4683 ** the AjPStr for this in "value". If not found returns NULL;
4684 **
4685 ** @param [r] name [const AjPStr] character string to find in getenv list
4686 ** @param [w] value [AjPStr*] String for the value.
4687 ** @return [AjBool] True if name was defined.
4688 **
4689 ** @release 6.1.0
4690 ** @@
4691 **
4692 ******************************************************************************/
4693 
ajNamGetenvS(const AjPStr name,AjPStr * value)4694 AjBool ajNamGetenvS(const AjPStr name,
4695 		    AjPStr* value)
4696 {
4697     return ajNamGetenvC(ajStrGetPtr(name), value);
4698 }
4699 
4700 
4701 
4702 
4703 /* @func ajNamGetAliasC *******************************************************
4704 **
4705 ** Looks for name as an alias in the hash table and if found returns
4706 ** the AjPStr for this in "value". If not found returns NULL;
4707 **
4708 ** @param [r] name [const char*] character string find in hash table.
4709 ** @param [w] value [AjPStr*] Str for the value.
4710 ** @return [AjBool] True if name was defined.
4711 **
4712 ** @release 6.4.0
4713 ** @@
4714 **
4715 ******************************************************************************/
4716 
ajNamGetAliasC(const char * name,AjPStr * value)4717 AjBool ajNamGetAliasC(const char* name, AjPStr* value)
4718 {
4719     NamPEntry fnew       = NULL;
4720 
4721     fnew = ajTableFetchmodC(namAliasMasterTable, name);
4722 
4723     if(fnew)
4724     {
4725         ajDebug("Found alias '%s' value '%S' (%S)\n",
4726                 name, fnew->value, fnew->file);
4727 	ajStrAssignS(value, fnew->value);
4728 
4729 	return ajTrue;
4730     }
4731 
4732     return ajFalse;
4733 }
4734 
4735 
4736 
4737 
4738 /* @func ajNamGetAliasS *******************************************************
4739 **
4740 ** Looks for name as an alias in the hash table and if found returns
4741 ** the AjPStr for this in "value". If not found returns NULL;
4742 **
4743 ** @param [r] namestr [const AjPStr] character string find in hash table.
4744 ** @param [w] value [AjPStr*] Str for the value.
4745 ** @return [AjBool] True if name was defined.
4746 **
4747 ** @release 6.4.0
4748 ** @@
4749 **
4750 ******************************************************************************/
4751 
ajNamGetAliasS(const AjPStr namestr,AjPStr * value)4752 AjBool ajNamGetAliasS(const AjPStr namestr, AjPStr* value)
4753 {
4754     NamPEntry fnew       = NULL;
4755 
4756     fnew = ajTableFetchmodS(namAliasMasterTable, namestr);
4757 
4758     if(fnew)
4759     {
4760         ajDebug("Found alias '%S' value '%S' (%S)\n",
4761                 namestr, fnew->value, fnew->file);
4762 	ajStrAssignS(value, fnew->value);
4763 
4764 	return ajTrue;
4765     }
4766 
4767     return ajFalse;
4768 }
4769 
4770 
4771 
4772 
4773 /* @func ajNamGetValueC *******************************************************
4774 **
4775 ** Looks for name as an (upper case) environment variable,
4776 ** and then as-is in the hash table and if found returns
4777 ** the AjPStr for this in "value". If not found returns NULL;
4778 **
4779 ** @param [r] name [const char*] character string find in hash table.
4780 ** @param [w] value [AjPStr*] Str for the value.
4781 ** @return [AjBool] True if name was defined.
4782 **
4783 ** @release 1.0.0
4784 ** @@
4785 **
4786 ******************************************************************************/
4787 
ajNamGetValueC(const char * name,AjPStr * value)4788 AjBool ajNamGetValueC(const char* name, AjPStr* value)
4789 {
4790     NamPEntry fnew       = NULL;
4791     AjBool hadPrefix     = ajFalse;
4792     AjBool ret           = ajFalse;
4793 
4794     ajDebug("ajNamGetValueC '%s'\n", name);
4795 
4796     if(ajCharPrefixCaseS(name, namPrefixStr)) /* may already have the prefix */
4797     {
4798 	ajStrAssignC(&namValNameTmp, name);
4799 	hadPrefix = ajTrue;
4800     }
4801     else
4802     {
4803 	ajStrAssignS(&namValNameTmp, namPrefixStr);
4804 	ajStrAppendC(&namValNameTmp, name);
4805     }
4806 
4807     /* upper case for ENV, otherwise don't care */
4808     ajStrFmtUpper(&namValNameTmp);
4809 
4810     ajDebug("ajNamGetValueC search for '%S': ", namValNameTmp);
4811 
4812     /* first test for an ENV variable */
4813 
4814     ret = ajNamGetenvS(namValNameTmp, value);
4815 
4816     if(ret)
4817     {
4818         ajDebug("Found environment variable value '%S'\n", *value);
4819 	return ajTrue;
4820     }
4821 
4822     /* then test the table definitions - with the prefix */
4823 
4824     fnew = ajTableFetchmodS(namVarMasterTable, namValNameTmp);
4825 
4826     if(fnew)
4827     {
4828         ajDebug("Found %S prefix set variable '%S' value '%S' (%S)\n",
4829                 namPrefixStr, namValNameTmp, fnew->value, fnew->file);
4830 	ajStrAssignS(value, fnew->value);
4831 
4832 	return ajTrue;
4833     }
4834 
4835     if(!hadPrefix)
4836     {
4837 
4838 	/* then test the table definitions - as originally specified */
4839 
4840 	fnew = ajTableFetchmodC(namVarMasterTable, name);
4841 
4842 	if(fnew)
4843 	{
4844             ajDebug("Found %S noprefix set variable '%s' value '%S' (%S)\n",
4845                     namPrefixStr, name, fnew->value, fnew->file);
4846 	    ajStrAssignS(value, fnew->value);
4847 
4848 	    return ajTrue;
4849 	}
4850     }
4851 
4852     if(ajStrMatchC(namValNameTmp, "EMBOSS_INSTALLDIRECTORY"))
4853     {
4854         ajStrAssignS(value, ajNamValueInstalldir());
4855         ajDebug("Found builtin variable '%S' value '%S'\n",
4856                 namValNameTmp, *value);
4857         return ajTrue;
4858     }
4859 
4860     if(ajStrMatchC(namValNameTmp, "EMBOSS_ROOTDIRECTORY"))
4861     {
4862         ajStrAssignS(value, ajNamValueRootdir());
4863         ajDebug("Found builtin variable '%S' value '%S'\n",
4864                 namValNameTmp, *value);
4865         return ajTrue;
4866     }
4867 
4868     if(ajStrMatchC(namValNameTmp, "EMBOSS_BASEDIRECTORY"))
4869     {
4870         ajStrAssignS(value, ajNamValueBasedir());
4871         ajDebug("Found builtin variable '%S' value '%S'\n",
4872                 namValNameTmp, *value);
4873         return ajTrue;
4874     }
4875 
4876     ajDebug("%S not found\n", namValNameTmp);
4877 
4878     return ajFalse;
4879 }
4880 
4881 
4882 
4883 
4884 /* @func ajNamGetValueS *******************************************************
4885 **
4886 ** Looks for name as an (upper case) environment variable,
4887 ** and then as-is in the hash table and if found returns
4888 ** the AjPStr for this in "value". If not found returns NULL;
4889 **
4890 ** @param [r] name [const AjPStr] character string find in hash table.
4891 ** @param [w] value [AjPStr*] String for the value.
4892 ** @return [AjBool] True if name was defined.
4893 **
4894 ** @release 6.1.0
4895 ** @@
4896 **
4897 ******************************************************************************/
4898 
ajNamGetValueS(const AjPStr name,AjPStr * value)4899 AjBool ajNamGetValueS(const AjPStr name, AjPStr* value)
4900 {
4901     return ajNamGetValueC(ajStrGetPtr(name), value);
4902 }
4903 
4904 
4905 
4906 
4907 /* @func ajNamServer **********************************************************
4908 **
4909 ** Looks for name in the server hash table and if found returns
4910 ** the attribute for this. If not found returns  NULL;
4911 **
4912 ** @param [r] name [const AjPStr] character string find in hash table.
4913 ** @return [AjBool] true if server name is valid.
4914 ** @error  NULL if name not found in the table
4915 **
4916 ** @release 6.4.0
4917 ** @@
4918 **
4919 ******************************************************************************/
4920 
ajNamServer(const AjPStr name)4921 AjBool ajNamServer(const AjPStr name)
4922 {
4923     const NamPEntry fnew = NULL;
4924 
4925     /* ajDebug("ajNamServer '%S'\n", name); */
4926 
4927     fnew = ajTableFetchS(namSvrMasterTable, name);
4928 
4929     if(fnew)
4930     {
4931 	/* ajDebug("  '%S' found\n", name); */
4932 	return ajTrue;
4933     }
4934 
4935     /* ajDebug("  '%S' not found\n", name); */
4936     return ajFalse;
4937 }
4938 
4939 
4940 
4941 
4942 /* @func ajNamDatabase ********************************************************
4943 **
4944 ** Looks for name in the database hash table and if found returns
4945 ** true.
4946 **
4947 ** @param [r] name [const AjPStr] character string find in hash table.
4948 ** @return [AjBool] true if database name is valid.
4949 ** @error  NULL if name not found in the table
4950 **
4951 ** @release 1.0.0
4952 ** @@
4953 **
4954 ******************************************************************************/
4955 
ajNamDatabase(const AjPStr name)4956 AjBool ajNamDatabase(const AjPStr name)
4957 {
4958     const NamPEntry fnew = NULL;
4959 
4960     /* ajDebug("ajNamDatabase '%S'\n", name); */
4961 
4962     fnew = ajTableFetchS(namDbMasterTable, name);
4963 
4964     if(fnew)
4965     {
4966 	/* ajDebug("  '%S' found\n", name); */
4967 	return ajTrue;
4968     }
4969 
4970     /* ajDebug("  '%S' not found\n", name); */
4971     return ajFalse;
4972 }
4973 
4974 
4975 
4976 
4977 /* @func ajNamAliasDatabase ***************************************************
4978 **
4979 ** Looks for name in the database hash table and the database alias hash
4980 ** table and if found returns the true name for this. If not found
4981 ** returns false and leaves the original name unchanged
4982 **
4983 ** @param [u] Pname [AjPStr*] character string to find in hash table.
4984 ** @return [AjBool] true if database name is valid.
4985 **
4986 ** @release 6.4.0
4987 ** @@
4988 **
4989 ******************************************************************************/
4990 
ajNamAliasDatabase(AjPStr * Pname)4991 AjBool ajNamAliasDatabase(AjPStr *Pname)
4992 {
4993     const NamPEntry fnew = NULL;
4994     AjPStr alias = NULL;
4995     const AjPStr tryname = *Pname;
4996 
4997     /* ajDebug("ajNamAliasDatabase '%S'\n", *Pname); */
4998 
4999     fnew = ajTableFetchS(namDbMasterTable, *Pname);
5000 
5001     if(fnew)
5002     {
5003 	/* ajDebug("  '%S' found\n", *Pname); */
5004 	return ajTrue;
5005     }
5006 
5007     while(ajNamGetAliasS(tryname, &alias))
5008     {
5009         fnew = ajTableFetchS(namDbMasterTable, alias);
5010         if(fnew)
5011         {
5012             ajStrAssignS(Pname, alias);
5013             /*ajDebug("  '%S' found as '%S'\n", name, alias);*/
5014             ajStrDel(&alias);
5015             return ajTrue;
5016         }
5017         tryname = alias;
5018     }
5019 
5020     ajStrDel(&alias);
5021     /* ajDebug("  '%S' not found\n", name); */
5022     return ajFalse;
5023 }
5024 
5025 
5026 
5027 
5028 /* @func ajNamDatabaseServer **************************************************
5029 **
5030 ** Looks for a database name for a specific server.
5031 ** Reads the server cache file to find the database.
5032 **
5033 ** @param [r] name [const AjPStr] Database name to find for server
5034 ** @param [r] server [const AjPStr] Server name
5035 ** @return [AjBool] true if database name is valid.
5036 ** @error  NULL if name not found in the table
5037 **
5038 ** @release 6.4.0
5039 ** @@
5040 **
5041 ******************************************************************************/
5042 
ajNamDatabaseServer(const AjPStr name,const AjPStr server)5043 AjBool ajNamDatabaseServer(const AjPStr name, const AjPStr server)
5044 {
5045     AjBool ret = ajTrue;
5046     const NamPEntry svdata = NULL;
5047     const NamPEntry dbdata = NULL;
5048     const NamPEntry sdbdata = NULL;
5049     AjPTable svrtable;
5050     AjPTable dbtable;
5051     const AjPStr svrval = NULL;
5052     AjPStr cachefile = NULL;
5053 
5054     ajDebug("ajNamDatabaseServer '%S' for server '%S'\n",
5055             name, server);
5056 
5057     svdata = ajTableFetchS(namSvrMasterTable, server);
5058 
5059     if(!svdata)
5060     {
5061 	ajErr("Server '%S' not found, unable to search for database '%S'",
5062               server, name);
5063 	return ajFalse;
5064     }
5065 
5066     dbdata = ajTableFetchS(namSvrDatabaseTable,server);
5067 
5068     if(!dbdata)
5069     {
5070 
5071         /* pick up the cache file name for this server */
5072         svrtable = (AjPTable) svdata->data;
5073         svrval = ajTableFetchmodC(svrtable, "cachefile");
5074 
5075         if(ajStrGetLen(svrval))
5076             cachefile = ajStrNewS(svrval);
5077         else
5078         {
5079             cachefile = ajStrNewC("server.");
5080             ajStrAppendS(&cachefile, server);
5081         }
5082 
5083         namSvrCacheRead(server, cachefile);
5084         dbdata = ajTableFetchS(namSvrDatabaseTable, server);
5085 
5086         ajStrDel(&cachefile);
5087     }
5088 
5089     if(!dbdata)
5090     {
5091         ajWarn("Server '%S' has no databases", server);
5092         return ajFalse;
5093     }
5094 
5095     dbtable = (AjPTable) dbdata->data;
5096     sdbdata = ajTableFetchS(dbtable, name);
5097 
5098     if(!sdbdata)
5099     {
5100         ajWarn("Server '%S' has no database '%S'", server, name);
5101         return ajFalse;
5102     }
5103 
5104     ajDebug("Found database '%S' on server '%S'\n", name, server);
5105 
5106     /* ajDebug("  '%S' not found\n", name); */
5107     return ret;
5108 }
5109 
5110 
5111 
5112 
5113 /* @func ajNamAliasServer *****************************************************
5114 **
5115 ** Looks for a database name for a specific server.
5116 ** Reads the server cache file to find the database.
5117 **
5118 ** @param [u] Pname [AjPStr*] character string to find in hash table.
5119 ** @param [r] server [const AjPStr] Server name
5120 ** @return [AjBool] true if database name is valid.
5121 **
5122 ** @release 6.4.0
5123 ** @@
5124 **
5125 ******************************************************************************/
5126 
ajNamAliasServer(AjPStr * Pname,const AjPStr server)5127 AjBool ajNamAliasServer(AjPStr *Pname, const AjPStr server)
5128 {
5129     const NamPEntry svdata = NULL;
5130     const NamPEntry dbdata = NULL;
5131     const NamPEntry sdbdata = NULL;
5132     const NamPEntry alidata = NULL;
5133     const NamPEntry salidata = NULL;
5134     AjPTable svrtable;
5135     AjPTable dbtable;
5136     AjPTable alitable;
5137     const AjPStr svrval = NULL;
5138     AjPStr cachefile = NULL;
5139     AjPStr alias = NULL;
5140     AjBool hasAlias = ajFalse;
5141 
5142     ajDebug("ajNamAliasServer '%S' for server '%S'\n",
5143             *Pname, server);
5144 
5145     svdata = ajTableFetchS(namSvrMasterTable, server);
5146 
5147     if(!svdata)
5148     {
5149 	ajErr("Server '%S' not found, unable to search for database '%S'",
5150               server, *Pname);
5151 	return ajFalse;
5152     }
5153 
5154     dbdata = ajTableFetchS(namSvrDatabaseTable,server);
5155     alidata = ajTableFetchS(namSvrAliasTable,server);
5156 
5157     if(!dbdata)
5158     {
5159 
5160         /* pick up the cache file name for this server */
5161         svrtable = (AjPTable) svdata->data;
5162         svrval = ajTableFetchmodC(svrtable, "cachefile");
5163 
5164         if(ajStrGetLen(svrval))
5165         {
5166             cachefile = ajStrNewS(svrval);
5167         }
5168         else
5169         {
5170             cachefile = ajStrNewC("server.");
5171             ajStrAppendS(&cachefile, server);
5172         }
5173 
5174         namSvrCacheRead(server, cachefile);
5175         dbdata = ajTableFetchS(namSvrDatabaseTable, server);
5176         alidata = ajTableFetchS(namSvrAliasTable, server);
5177 
5178         ajStrDel(&cachefile);
5179     }
5180 
5181     if(!dbdata)
5182     {
5183         ajWarn("Server '%S' has no databases", server);
5184         return ajFalse;
5185     }
5186 
5187    ajStrAssignS(&alias, *Pname);
5188 
5189     alitable = (AjPTable) alidata->data;
5190     salidata = ajTableFetchS(alitable, alias);
5191 
5192     while(salidata)
5193     {
5194         hasAlias = ajTrue;
5195         ajStrAssignS(&alias,salidata->value);
5196         salidata = ajTableFetchS(alitable, alias);
5197     }
5198 
5199     dbtable = (AjPTable) dbdata->data;
5200     sdbdata = ajTableFetchS(dbtable, alias);
5201     if(!sdbdata)
5202     {
5203         if(hasAlias)
5204             ajWarn("Server '%S' has no database '%S' (alias '%S')",
5205                    server, *Pname, alias);
5206         else
5207             ajWarn("Server '%S' has no database '%S'", server, *Pname);
5208 
5209         ajStrDel(&alias);
5210         return ajFalse;
5211     }
5212 
5213     ajDebug("Found database '%S' (alias '%S') on server '%S'\n",
5214             *Pname, alias, server);
5215 
5216     ajStrAssignS(Pname, alias);
5217 
5218     ajStrDel(&alias);
5219 
5220     return ajTrue;
5221 }
5222 
5223 
5224 
5225 
5226 /* @funcstatic namSvrCacheParse ***********************************************
5227 **
5228 ** Parses a database cachefile for a server
5229 **
5230 ** @param [u] cachefile [AjPFile] Cache file
5231 ** @param [u] dbtable [AjPTable] Database table for server
5232 ** @param [u] alitable [AjPTable] Alias table for server
5233 ** @return [AjBool] True on success
5234 **
5235 **
5236 ** @release 6.4.0
5237 ******************************************************************************/
5238 
namSvrCacheParse(AjPFile cachefile,AjPTable dbtable,AjPTable alitable)5239 static AjBool namSvrCacheParse(AjPFile cachefile, AjPTable dbtable,
5240                                AjPTable alitable)
5241 {
5242     AjBool ret = ajTrue;
5243     AjPStr rdline = NULL;
5244     AjPStr word   = NULL;
5245     const char *ptr;
5246     ajint i = 0;
5247     ajint len;
5248     char quote = '\0';
5249     AjPList listwords;
5250     AjPList listcount;
5251     AjPStr wordptr;
5252     ajint iline = 0;
5253     ajint *k    = NULL;
5254 
5255     ajDebug("namSvrCacheParse '%F'\n", cachefile);
5256 
5257     ajFmtPrintS(&namFileName, "%F",cachefile);
5258 
5259     listwords = ajListstrNew();
5260     listcount = ajListNew();
5261     word      = ajStrNewRes(128);
5262 
5263     /* Read in the settings. */
5264     while(ajReadlineTrim(cachefile, &rdline))
5265     {
5266 	iline++;
5267  	AJNEW0(k);
5268 	*k = (ajuint) ajListGetLength(listwords);
5269 	ajListPushAppend(listcount, k);
5270 
5271 	if(!ajStrCutCommentsStart(&rdline))
5272 	    continue;
5273 
5274 	len = ajStrGetLen(rdline);
5275 
5276 	/* now create a linked list of the "words" */
5277 	if(len)
5278 	{
5279 	    ptr = ajStrGetPtr(rdline);
5280 	    i = 0;
5281 
5282 	    while(*ptr && i < len)
5283 	    {
5284 		if(*ptr == ' ' || *ptr == '\t')
5285 		{
5286 		    if(ajStrGetLen(word))
5287 		    {
5288 			wordptr = ajStrNewS(word);
5289 			ajListstrPushAppend(listwords, wordptr);
5290 			ajStrAssignClear(&word);
5291 		    }
5292 
5293 		    i++;
5294 		    ptr++;
5295 		    continue;
5296 		}
5297 		else if(*ptr == '\'' || *ptr == '\"')
5298 		{
5299 		    ajStrAppendK(&word,*ptr);
5300 
5301 		    if(quote)
5302 		    {
5303 			if(quote == *ptr)
5304 			    quote = '\0';
5305 		    }
5306 		    else
5307 			quote = *ptr;
5308 		}
5309 		else if(!quote && ajStrGetLen(word) && *ptr == ']')
5310 		{
5311 		    wordptr = ajStrNewS(word);
5312 		    ajListstrPushAppend(listwords, wordptr);
5313 		    ajStrAssignClear(&word);
5314 		    wordptr = ajStrNewC("]");
5315 		    ajListstrPushAppend(listwords, wordptr);
5316 		    ajStrAssignClear(&word);
5317 		}
5318 		else
5319 		    ajStrAppendK(&word,*ptr);
5320 
5321 		i++;
5322                 ptr++;
5323 	    }
5324 
5325 	    if(ajStrGetLen(word))
5326 	    {
5327 		wordptr = ajStrNewS(word);
5328 		ajListstrPushAppend(listwords, wordptr);
5329 		ajStrAssignClear(&word);
5330 	    }
5331 
5332 	}
5333     }
5334 
5335     ajStrDel(&rdline);
5336 
5337     AJNEW0(k);
5338     *k = (ajuint) ajListGetLength(listwords);
5339     ajListPushAppend(listcount, k);
5340 
5341     if(!namSvrCacheParseList(listwords, listcount, cachefile,
5342                              dbtable, alitable))
5343     {
5344 	ajErr("%F: Unexpected end of file in %S at line %d\n",
5345               cachefile, iline); /* FIXME */
5346         ret = ajFalse;
5347     }
5348 
5349     ajListFree(&listwords);
5350     ajListFree(&listcount);
5351     ajStrDel(&word);
5352 
5353     return ret;
5354 }
5355 
5356 
5357 
5358 
5359 /* @funcstatic namSvrCacheParseList *******************************************
5360 **
5361 ** Parse the text in a list of tokens read from the server cache file.
5362 ** Derive server database definitions. Store all these in the server's
5363 ** internal table.
5364 **
5365 ** @param [u] listwords [AjPList] String list of word tokens to parse
5366 ** @param [u] listcount [AjPList] List of word counts per line for
5367 **                                generating error messages
5368 ** @param [u] cachefile [AjPFile] Input file only for name in messages
5369 ** @param [u] dbtable [AjPTable] Database table for server
5370 ** @param [u] alitable [AjPTable] Alias table for server
5371 ** @return [AjBool] True on success
5372 **
5373 ** @release 6.4.0
5374 ** @@
5375 ******************************************************************************/
5376 
namSvrCacheParseList(AjPList listwords,AjPList listcount,AjPFile cachefile,AjPTable dbtable,AjPTable alitable)5377 static AjBool namSvrCacheParseList(AjPList listwords, AjPList listcount,
5378                                    AjPFile cachefile,
5379                                    AjPTable dbtable, AjPTable alitable)
5380 {
5381     static char* tabname   = NULL;
5382     static AjPStr name     = NULL;
5383     static AjPStr value    = NULL;
5384     static char quoteopen  = '\0';
5385     static char quoteclose = '\0';
5386     static AjPTable dbattr  = NULL;
5387     static ajint  db_input = -1;
5388     AjPTable saveTable = NULL;
5389 
5390     NamPEntry fnew  = NULL;
5391     NamPEntry entry = NULL;
5392 
5393     AjPStr includefn = NULL;
5394     AjPFile iinf     = NULL;
5395     AjPStr key       = NULL;
5396     AjPStr val       = NULL;
5397     AjPStr oldval    = NULL;
5398     static AjPTable Ifiles = NULL;
5399     AjPStr curword = NULL;
5400 
5401     ajint wordcount = 0;
5402     ajint linecount = 0;
5403     ajint lineword  = 0;
5404     ajint *iword    = NULL;
5405     AjBool namstatus;
5406     AjPStr saveshortname = NULL;
5407     AjPStr saveword = NULL;
5408 
5409     AjBool dbsave = ajFalse;
5410     AjBool saveit = ajFalse;
5411 
5412     ajFmtPrintS(&saveshortname, "%F", cachefile);
5413     quoteopen  = '\0';
5414     quoteclose = '\0';
5415 
5416     namLine = 1;
5417 
5418     while(ajListstrPop(listwords, &curword))
5419     {
5420 	while(ajListGetLength(listcount) && (lineword < wordcount))
5421 	{
5422 	    namUser("ajListPop %d < %d list %Lu\n",
5423 		    lineword, wordcount, ajListGetLength(listcount));
5424 	    ajListPop(listcount, (void**) &iword);
5425 	    lineword = *iword;
5426 	    linecount++;
5427 	    namLine = linecount-1;
5428 	    AJFREE(iword);
5429 	}
5430 
5431 	wordcount++;
5432 
5433 	if(!namParseType)
5434 	{
5435 	    namNoColon(&curword);
5436 	    ajStrFmtLower(&curword);
5437 
5438 	    if(ajCharPrefixS("dbname",curword))
5439 		namParseType = TYPE_DB;
5440 	    if(ajCharPrefixS("alias",curword))
5441 		namParseType = TYPE_ALIAS;
5442 	    else if(ajCharPrefixS("include",curword))
5443 		namParseType = TYPE_IFILE;
5444 
5445 	    if(!namParseType)		/* test: badtype.rc */
5446 		namError("Invalid definition type '%S'", curword);
5447 	}
5448 	else if(quoteopen && ajStrMatchC(curword, "]"))
5449 	{				/* test; dbnoquote.rc */
5450 	    namError("']' found, unclosed quotes in '%S'", value);
5451 	    quoteopen    = '\0';
5452 	    namParseType = 0;
5453 	}
5454 	else if(quoteopen)
5455 	{
5456 	    /*
5457 	    ** quote is open, so append word until close quote is found,
5458 	    ** and set the appropriate save flag
5459 	    */
5460 	    namUser("<%c>..<%c> quote processing\n", quoteopen, quoteclose);
5461 	    ajStrAppendC(&value," ");
5462 	    ajStrAppendS(&value,curword);
5463 
5464 	    /* close quote here ?? */
5465 	    if(ajStrGetCharLast(curword) == quoteclose)
5466 	    {
5467 		namUser("close quotes\n");
5468 		ajStrCutEnd(&value, 1);
5469 		quoteopen = quoteclose = '\0';
5470 
5471 		if(namParseType == TYPE_DB)
5472 		    dbsave = ajTrue;
5473 		if(namParseType == TYPE_ALIAS)
5474 		    dbsave = ajTrue;
5475 	    }
5476 	}
5477 	else if(namParseType == TYPE_ALIAS)
5478 	{
5479 	    namUser("CACHE ALIAS saveit: %B name: '%S' value '%S' "
5480                     "quoteopen: '%c'\n",
5481                     saveit, name, value, quoteopen);
5482 	    if(name && value)
5483 		saveit= ajTrue;
5484 	    else if(name)
5485 	    {
5486 		/* if name already got then it must be the value */
5487 		if(ajStrGetCharFirst(curword) == '\'')
5488 		    quoteopen = quoteclose = '\'';
5489 		else if(ajStrGetCharFirst(curword) == '\"')
5490 		    quoteopen = quoteclose = '\"';
5491 
5492 		ajStrAssignS(&value, curword);
5493 
5494 		if(quoteopen)
5495 		{
5496 		    /* trim the opening quote */
5497 		    ajStrCutStart(&value, 1);
5498 
5499 		    if(!ajStrGetLen(value))
5500 			ajErr("Bare quote %c found in namListParse",
5501 			       quoteopen);
5502 		}
5503 		else
5504 		    saveit = ajTrue;
5505 
5506 		if(ajStrGetCharLast(curword) == quoteclose)
5507 		{
5508 		    /* end of quote on same word */
5509 		    quoteopen = quoteclose = '\0';
5510 		    saveit= ajTrue;
5511 		    /* remove quote at the end */
5512 		    ajStrCutEnd(&value, 1);
5513 		}
5514 
5515                 if(saveit)
5516                     ajNamResolve(&value);
5517 		namUser("save alias value '%S'\n", value);
5518 	    }
5519 	    else
5520 	    {
5521 		ajStrAssignS(&name, curword);
5522 		namUser("save alias name '%S'\n", name);
5523 	    }
5524         }
5525 	else if(namParseType == TYPE_DB)
5526 	{
5527 	    if(ajStrMatchC(curword, "[")) /* [ therefore new database */
5528 		dbattr = ajTablestrNew(100); /* new db obj */
5529 	    else if(ajStrMatchC(curword, "]"))	/* ] therefore end of db */
5530 		saveit = ajTrue;
5531 	    else if(name)
5532 	    {
5533 		if(db_input >= 0)
5534 		{
5535 		    /* So if keyword type has been set */
5536 		    if(ajStrGetCharFirst(curword) == '\'')
5537 		    {
5538 			/* is there a quote? If so expect the */
5539 			/* same at the end. No ()[] etc here*/
5540 			quoteopen = quoteclose = '\'';
5541 		    }
5542 		    else if(ajStrGetCharFirst(curword) == '\"')
5543 			quoteopen = quoteclose = '\"';
5544 
5545 		    ajStrAssignS(&value, curword);
5546 
5547 		    if(quoteopen)
5548 		    {
5549 			ajStrCutStart(&value, 1); /* trim opening quote */
5550 
5551 			if(!ajStrGetLen(value))
5552 			    ajErr("Bare quote %c found in namListParse",
5553 				   quoteopen);
5554 		    }
5555 		    else
5556 			dbsave = ajTrue; /* we are done - simple word */
5557 
5558 		    if(ajStrGetCharLast(curword) == quoteclose)
5559 		    {
5560 			quoteopen = quoteclose = '\0';
5561 			ajStrCutEnd(&value,1); /* trim closing quote */
5562 			dbsave = ajTrue;
5563 		    }
5564 
5565 		    if(!quoteopen)     /* if we just reset it above */
5566 			dbsave = ajTrue;
5567 
5568                     if(dbsave)
5569                         ajNamResolve(&value);
5570 		}
5571 		else if(ajStrGetCharLast(curword) == ':')
5572 		{
5573 		    /* if last character is : then its a keyword */
5574 		    ajStrFmtLower(&curword); /* make it lower case */
5575 		    namNoColon(&curword);
5576 		    db_input = namDbAttrS(curword);
5577 
5578 		    if(db_input < 0)
5579 			ajWarn("%F: bad attribute '%S' for database '%S'",
5580 				cachefile, curword, name);
5581 		}
5582                 else
5583                 {
5584                     ajWarn("%F: unexpected token '%S' for database '%S'",
5585                            cachefile, curword, name);
5586                 }
5587 	    }
5588 	    else
5589 	    {
5590 		ajStrAssignS(&name, curword);
5591 
5592 		if(!ajNamIsDbname(name))
5593 		    ajErr("Invalid database name '%S'", name);
5594 
5595 		namUser("saving db name '%S'\n", name);
5596 	    }
5597 	}
5598 
5599 
5600 	else if(namParseType == TYPE_IFILE)
5601 	{
5602 	    if(!Ifiles)
5603 		Ifiles = ajTablestrNew(NAM_INCLUDE_ESTIMATE);
5604 
5605 	    namParseType = 0;
5606 
5607             ajStrAssignS(&saveword, curword);
5608 
5609             ajNamResolve(&curword);
5610 
5611 	    if(ajTableFetchS(Ifiles,curword)) /* test: includeagain.rc */
5612             {
5613 		if(ajStrMatchS(curword, saveword))
5614                     namError("%S already read ... skipping", curword);
5615                 else
5616                     namError("%S (%S) already read ... skipping",
5617                              saveword, curword);
5618             }
5619 	    else
5620 	    {
5621 		includefn = ajStrNew();
5622 		ajStrAssignS(&includefn,curword);
5623 
5624 		if(namFileOrig)
5625 		    ajStrAppendC(&namFileOrig,", ");
5626 
5627 		ajStrAppendS(&namFileOrig,includefn);
5628 
5629 		key = ajStrNewS(includefn);
5630 		val = ajStrNewS(includefn);
5631 		oldval = ajTablePut(Ifiles,key,val);
5632                 namUser("store file '%S' => '%S\n", key, val);
5633 
5634                 if(oldval)
5635                 {
5636                     ajWarn("duplicate include value for '%S' = '%S'",
5637                            key, oldval);
5638                     ajStrDel(&key);
5639                     ajStrDel(&oldval);
5640                 }
5641 
5642                 /* test: badinclude.rc */
5643 		if(!(iinf = ajFileNewInNameS(includefn)))
5644 		{
5645                     if(ajStrMatchS(includefn, saveword))
5646                         namError("Failed to open include file '%S'",
5647                                  includefn);
5648                     else
5649                         namError("Failed to open include file '%S' (%S)",
5650                                  saveword, includefn);
5651 		    ajStrAppendC(&namFileOrig,"(Failed)");
5652 		}
5653 		else
5654 		{
5655 		    ajStrAppendC(&namFileOrig,"(OK)");
5656                     /* replaces namFile */
5657                     ajStrAssignS(&name, includefn);
5658                     ajFilenameTrimPath(&name);
5659 		    namstatus = namProcessFile(iinf, name);
5660 		    ajFmtPrintS(&namFileName, "%F",
5661                                 cachefile);/* reset saved name */
5662 		    namLine = linecount-1;
5663 
5664 		    if(!namstatus)	/* test: badsummary.rc */
5665                     {
5666                         if(ajStrMatchS(includefn, saveword))
5667                             namError("Error(s) found in included file %F",
5668                                      iinf);
5669                         else
5670                             namError("Error(s) found in included file %S (%F)",
5671                                      saveword, iinf);
5672                     }
5673 
5674 
5675 		    ajFileClose(&iinf);
5676 		}
5677 
5678 		ajStrDel(&includefn);
5679 	    }
5680 
5681 	    namListParseOK = ajTrue;
5682 	}
5683 
5684 
5685 	if(dbsave)
5686 	{
5687 	    /* Save the keyword value */
5688             key = ajStrNewC(namDbAttrs[db_input].Name);
5689             namDbtablePutAttrS(dbattr, &key, &value);
5690 
5691 	    db_input =-1;
5692 	    dbsave = ajFalse;
5693 	}
5694 
5695 	if(saveit)
5696 	{
5697 	    namUser("saving type %d name '%S' value '%S' line:%d\n",
5698 		    namParseType, name, value, namLine);
5699 	    AJNEW0(fnew);
5700 	    tabname = ajCharNewS(name);
5701 	    fnew->name = name;
5702 	    name = NULL;
5703 	    fnew->value = value;
5704 	    value = NULL;
5705 	    fnew->file = ajStrNewRef(saveshortname);
5706 
5707             if(namParseType == TYPE_DB)
5708 	    {
5709 		fnew->data = (AjPTable) dbattr;
5710                 dbattr = NULL;
5711 		saveTable = dbtable;
5712 	    }
5713 	    else if(namParseType == TYPE_ALIAS)
5714 	    {
5715 		fnew->data = NULL;
5716 		saveTable = alitable;
5717 	    }
5718 	    else
5719 	    {
5720 		fnew->data = NULL;
5721 	    }
5722 	    entry = ajTablePut(saveTable, tabname, fnew);
5723             namUser("store entry '%s' '%S' (%S)\n",
5724                     tabname, fnew->name, fnew->file);
5725 
5726 	    if(entry)
5727 	    {
5728 		/* it existed so over wrote previous table entry
5729 		** Only a namUser message - redefining EMBOSSRC in
5730 		** QA testing can give too many warnings
5731 		*/
5732 		ajErr("%F: replaced %s %S definition from %S\n",
5733                       cachefile,
5734                       namTypes[namParseType],
5735                       entry->name,
5736                       entry->file);
5737 		namEntryDelete(&entry, namParseType); /* previous entry */
5738 	    }
5739 
5740 	    saveit = ajFalse;
5741 	    namParseType = 0;
5742         }
5743 	ajStrDel(&curword);
5744     }
5745 
5746     if(namParseType)
5747     {
5748 	/* test: badset.rc baddb.rc  */
5749 	namError("Unexpected end of file in %s definition",
5750 		 namTypes[namParseType]);
5751 	namParseType = 0;
5752     }
5753 
5754     if(ajListGetLength(listcount))	/* cleanup the wordcount list */
5755     {
5756 	namUser("** remaining wordcount items: %Lu\n",
5757                 ajListGetLength(listcount));
5758 
5759 	while(ajListGetLength(listcount))
5760 	{
5761 	    ajListPop(listcount, (void**) &iword);
5762 	    AJFREE(iword);
5763 	}
5764     }
5765 
5766     if(value)
5767 	namUser("++ namListParse value %x '%S'", value, value);
5768 
5769     ajStrDel(&saveword);
5770     ajStrDel(&saveshortname);
5771     ajTablestrFree(&Ifiles);
5772 
5773     return ajTrue;
5774 }
5775 
5776 
5777 
5778 
5779 /* @func ajNamSvrCount ********************************************************
5780 **
5781 ** Reads the database cachefile for a server and counts the number of databases
5782 **
5783 ** Searches emboss_standard and the user directory ~/.embossdata/
5784 ** testing the file data in each file found and parsing the most recent file.
5785 **
5786 ** cache files should all start with a comment line
5787 ** containing the file name and the creation date.
5788 **
5789 ** @param [r] server [const AjPStr] Server name
5790 ** @return [ajuint] Number of databases
5791 **
5792 **
5793 ** @release 6.4.0
5794 ******************************************************************************/
5795 
ajNamSvrCount(const AjPStr server)5796 ajuint ajNamSvrCount(const AjPStr server)
5797 {
5798     const NamPEntry svdata = NULL;
5799     const NamPEntry dbdata = NULL;
5800     AjPTable svrtable;
5801     AjPTable dbtable;
5802     const AjPStr svrcache = NULL;
5803     AjPStr cachefile = NULL;
5804 
5805     dbdata = ajTableFetchS(namSvrDatabaseTable, server);
5806 
5807     if(!dbdata)
5808     {
5809         svdata = ajTableFetchS(namSvrMasterTable, server);
5810 
5811         if(!svdata)
5812         {
5813             ajErr("Server '%S' not found, unable to count databases",
5814                   server);
5815             return 0;
5816         }
5817 
5818         svrtable = (AjPTable) svdata->data;
5819         svrcache = ajTableFetchC(svrtable, "cachefile");
5820 
5821         if(ajStrGetLen(svrcache))
5822             cachefile = ajStrNewS(svrcache);
5823         else
5824         {
5825             cachefile = ajStrNewC("server.");
5826             ajStrAppendS(&cachefile, server);
5827         }
5828 
5829         namSvrCacheRead(server, cachefile);
5830         dbdata = ajTableFetchS(namSvrDatabaseTable, server);
5831 
5832         if(!dbdata)
5833         {
5834             ajDebug("ajNamSvrCount: server '%S' has no databases\n", server);
5835             ajStrDel(&cachefile);
5836             return 0;
5837         }
5838     }
5839 
5840     dbtable = (AjPTable) dbdata->data;
5841 
5842     ajStrDel(&cachefile);
5843     return (ajuint) ajTableGetLength(dbtable);
5844 }
5845 
5846 
5847 
5848 
5849 /* @func ajNamSvrListFindAliases **********************************************
5850 **
5851 ** Reads the cachefile for a server and lists the aliases for a database.
5852 **
5853 ** Searches emboss_standard and the user directory ~/.embossdata/
5854 ** testing the file data in each file found and parsing the most recent file.
5855 **
5856 ** cache files should all start with a comment line
5857 ** containing the file name and the creation date.
5858 **
5859 ** @param [r] server [const AjPStr] Server name
5860 ** @param [r] dbname [const AjPStr] Database name
5861 ** @param [w] dbnames [AjPList] Str List of names to be populated
5862 ** @return [void]
5863 **
5864 **
5865 ** @release 6.6.0
5866 ******************************************************************************/
5867 
ajNamSvrListFindAliases(const AjPStr server,const AjPStr dbname,AjPList dbnames)5868 void ajNamSvrListFindAliases(const AjPStr server, const AjPStr dbname,
5869                              AjPList dbnames)
5870 {
5871     void **valarray =  NULL;
5872     register ajint i = 0;
5873     AjPStr testname = ajStrNewS(dbname);
5874 
5875     const NamPEntry svdata = NULL;
5876     const NamPEntry dbdata = NULL;
5877     NamPEntry fnew   = NULL;
5878     AjPTable svrtable;
5879     AjPTable dbtable;
5880     const AjPStr svrcache = NULL;
5881     AjPStr cachefile = NULL;
5882 
5883     /*
5884     ** TODO: Should server files be read by a separate function?
5885     ** This function is largely a copy of ajNamSvrCount and
5886     ** ajNamListListDatabases so that server files are read by both functions.
5887     */
5888 
5889     ajStrFmtLower(&testname);
5890     dbdata = ajTableFetchS(namSvrAliasTable, server);
5891 
5892     if(!dbdata)
5893     {
5894         svdata = ajTableFetchS(namSvrMasterTable, server);
5895 
5896         if(!svdata)
5897         {
5898             ajErr("Server '%S' not found, unable to count databases",
5899                   server);
5900             return;
5901         }
5902 
5903         svrtable = (AjPTable) svdata->data;
5904         svrcache = ajTableFetchC(svrtable, "cachefile");
5905 
5906         if(ajStrGetLen(svrcache))
5907             cachefile = ajStrNewS(svrcache);
5908         else
5909         {
5910             cachefile = ajStrNewC("server.");
5911             ajStrAppendS(&cachefile, server);
5912         }
5913 
5914         namSvrCacheRead(server, cachefile);
5915         dbdata = ajTableFetchS(namSvrAliasTable, server);
5916 
5917         ajStrDel(&cachefile);
5918 
5919         if(!dbdata)
5920         {
5921             ajWarn("Server '%S' has no databases", server);
5922             return;
5923         }
5924     }
5925 
5926     dbtable = (AjPTable) dbdata->data;
5927 
5928     ajTableToarrayValues(dbtable, &valarray);
5929     ajDebug("ajNamSvrListFindAliases\n");
5930 
5931     for(i = 0; valarray[i]; i++)
5932     {
5933 	fnew = (NamPEntry) valarray[i];
5934 
5935         if(!ajStrMatchS(testname, fnew->value))
5936             continue;
5937 
5938 	ajDebug("ALIAS: %S\n", fnew->name);
5939 	ajListstrPushAppend(dbnames, fnew->name);
5940     }
5941 
5942     ajListSort(dbnames, ajStrVcmp);
5943 
5944     ajStrDel(&testname);
5945     AJFREE(valarray);
5946 
5947     return;
5948 }
5949 
5950 
5951 
5952 
5953 /* @func ajNamSvrListListAliases **********************************************
5954 **
5955 ** Reads the database cachefile for a server and lists the aliases.
5956 **
5957 ** Searches emboss_standard and the user directory ~/.embossdata/
5958 ** testing the file data in each file found and parsing the most recent file.
5959 **
5960 ** cache files should all start with a comment line
5961 ** containing the file name and the creation date.
5962 **
5963 ** @param [r] server [const AjPStr] Server name
5964 ** @param [w] dbnames [AjPList] Str List of names to be populated
5965 ** @return [void]
5966 **
5967 **
5968 ** @release 6.6.0
5969 ******************************************************************************/
5970 
ajNamSvrListListAliases(const AjPStr server,AjPList dbnames)5971 void ajNamSvrListListAliases(const AjPStr server, AjPList dbnames)
5972 {
5973     void **valarray =  NULL;
5974     register ajint i = 0;
5975 
5976     const NamPEntry svdata = NULL;
5977     const NamPEntry dbdata = NULL;
5978     NamPEntry fnew   = NULL;
5979     AjPTable svrtable;
5980     AjPTable dbtable;
5981     const AjPStr svrcache = NULL;
5982     AjPStr cachefile = NULL;
5983 
5984     /*
5985     ** TODO: Should server files be read by a separate function?
5986     ** This function is largely a copy of ajNamSvrCount and
5987     ** ajNamListListDatabases so that server files are read by both functions.
5988     */
5989 
5990     dbdata = ajTableFetchS(namSvrAliasTable, server);
5991 
5992     if(!dbdata)
5993     {
5994         svdata = ajTableFetchS(namSvrMasterTable, server);
5995 
5996         if(!svdata)
5997         {
5998             ajErr("Server '%S' not found, unable to count databases",
5999                   server);
6000             return;
6001         }
6002 
6003         svrtable = (AjPTable) svdata->data;
6004         svrcache = ajTableFetchC(svrtable, "cachefile");
6005 
6006         if(ajStrGetLen(svrcache))
6007             cachefile = ajStrNewS(svrcache);
6008         else
6009         {
6010             cachefile = ajStrNewC("server.");
6011             ajStrAppendS(&cachefile, server);
6012         }
6013 
6014         namSvrCacheRead(server, cachefile);
6015         dbdata = ajTableFetchS(namSvrAliasTable, server);
6016 
6017         ajStrDel(&cachefile);
6018 
6019         if(!dbdata)
6020         {
6021             ajWarn("Server '%S' has no databases", server);
6022             return;
6023         }
6024     }
6025 
6026     dbtable = (AjPTable) dbdata->data;
6027 
6028     ajTableToarrayValues(dbtable, &valarray);
6029     ajDebug("ajNamSvrListListAliases\n");
6030 
6031     for(i = 0; valarray[i]; i++)
6032     {
6033 	fnew = (NamPEntry) valarray[i];
6034 	ajDebug("ALIAS: %S\n", fnew->name);
6035 	ajListstrPushAppend(dbnames, fnew->name);
6036     }
6037 
6038     ajListSort(dbnames, ajStrVcmp);
6039 
6040     AJFREE(valarray);
6041 
6042     return;
6043 }
6044 
6045 
6046 
6047 
6048 /* @func ajNamSvrListListDatabases ********************************************
6049 **
6050 ** Reads the database cachefile for a server and lists the databases.
6051 **
6052 ** Searches emboss_standard and the user directory ~/.embossdata/
6053 ** testing the file data in each file found and parsing the most recent file.
6054 **
6055 ** cache files should all start with a comment line
6056 ** containing the file name and the creation date.
6057 **
6058 ** @param [r] server [const AjPStr] Server name
6059 ** @param [w] dbnames [AjPList] Str List of names to be populated
6060 ** @return [void]
6061 **
6062 **
6063 ** @release 6.4.0
6064 ******************************************************************************/
6065 
ajNamSvrListListDatabases(const AjPStr server,AjPList dbnames)6066 void ajNamSvrListListDatabases(const AjPStr server, AjPList dbnames)
6067 {
6068     void **valarray =  NULL;
6069     register ajint i = 0;
6070 
6071     const NamPEntry svdata = NULL;
6072     const NamPEntry dbdata = NULL;
6073     NamPEntry fnew   = NULL;
6074     AjPTable svrtable;
6075     AjPTable dbtable;
6076     const AjPStr svrcache = NULL;
6077     AjPStr cachefile = NULL;
6078 
6079     /*
6080     ** TODO: Should server files be read by a separate function?
6081     ** This function is largely a copy of ajNamSvrCount and
6082     ** ajNamListListDatabases so that server files are read by both functions.
6083     */
6084 
6085     dbdata = ajTableFetchS(namSvrDatabaseTable, server);
6086 
6087     if(!dbdata)
6088     {
6089         svdata = ajTableFetchS(namSvrMasterTable, server);
6090 
6091         if(!svdata)
6092         {
6093             ajErr("Server '%S' not found, unable to count databases",
6094                   server);
6095             return;
6096         }
6097 
6098         svrtable = (AjPTable) svdata->data;
6099         svrcache = ajTableFetchC(svrtable, "cachefile");
6100 
6101         if(ajStrGetLen(svrcache))
6102             cachefile = ajStrNewS(svrcache);
6103         else
6104         {
6105             cachefile = ajStrNewC("server.");
6106             ajStrAppendS(&cachefile, server);
6107         }
6108 
6109         namSvrCacheRead(server, cachefile);
6110         dbdata = ajTableFetchS(namSvrDatabaseTable, server);
6111 
6112         ajStrDel(&cachefile);
6113 
6114         if(!dbdata)
6115         {
6116             ajWarn("Server '%S' has no databases", server);
6117             return;
6118         }
6119     }
6120 
6121     dbtable = (AjPTable) dbdata->data;
6122 
6123     ajTableToarrayValues(dbtable, &valarray);
6124     ajDebug("ajNamSvrListListDatabases\n");
6125 
6126     for(i = 0; valarray[i]; i++)
6127     {
6128 	fnew = (NamPEntry) valarray[i];
6129 	ajDebug("DB: %S\n", fnew->name);
6130 	ajListstrPushAppend(dbnames, fnew->name);
6131     }
6132 
6133     ajListSort(dbnames, ajStrVcmp);
6134 
6135     AJFREE(valarray);
6136 
6137     return;
6138 }
6139 
6140 
6141 
6142 
6143 /* @funcstatic namSvrCacheOpen ************************************************
6144 **
6145 ** Opens the database cachefile for a server.
6146 **
6147 ** Searches emboss_standard and the user directory ~/.embossdata/
6148 ** testing the file data in each file found and opening the most recent file.
6149 **
6150 ** cache files must all start with a comment line
6151 ** containing the file name and the creation date.
6152 **
6153 ** @param [r] cachename [const AjPStr] Cache file name
6154 ** @return [AjPFile] Filename of selected cache file
6155 **
6156 **
6157 ** @release 6.4.0
6158 ******************************************************************************/
6159 
namSvrCacheOpen(const AjPStr cachename)6160 static AjPFile namSvrCacheOpen(const AjPStr cachename)
6161 {
6162     AjPFile ret = NULL;
6163     AjPFile userfile = NULL;
6164     AjPFile systemfile = NULL;
6165 
6166     AjPStr readline = NULL;
6167     AjPStrTok handle = NULL;
6168     AjPStr token = NULL;
6169     AjPTime usertime = NULL;
6170     AjPTime systemtime = NULL;
6171 
6172     systemfile = ajFileNewInNamePathS(cachename, namStandardDir);
6173     ajDebug("system file '%F' name: '%S' path: '%S'\n",
6174             systemfile, cachename, namStandardDir);
6175 
6176     if(systemfile)
6177     {
6178         ajReadlineTrim(systemfile, &readline);
6179         ajStrTokenAssignC(&handle, readline, "# \t");
6180         ajStrTokenNextParse(handle, &token);
6181 
6182         if(!ajStrMatchS(token, cachename))
6183             ajWarn("%F: Cache file name '%S' expected, '%S' found",
6184                    systemfile, cachename, token);
6185 
6186         ajStrTokenNextParseC(handle, "", &token); /* time */
6187         systemtime = ajTimeNew();
6188         ajTimeSetS(systemtime, token);
6189     }
6190 
6191     userfile = ajFileNewInNamePathS(cachename, namUserDir);
6192     ajDebug("user file '%F' name: '%S' path: '%S'\n",
6193             userfile, cachename, namStandardDir);
6194 
6195     if(userfile)
6196     {
6197         ajReadlineTrim(userfile, &readline);
6198         ajStrTokenAssignC(&handle, readline, "# \t");
6199         ajStrTokenNextParse(handle, &token);
6200 
6201         if(!ajStrMatchS(token, cachename))
6202             ajWarn("%F: Cache file name '%S' expected, '%S' found",
6203                    userfile, cachename, token);
6204 
6205         ajStrTokenNextParseC(handle, "", &token); /* time */
6206         usertime = ajTimeNew();
6207         ajTimeSetS(usertime, token);
6208     }
6209 
6210     if(userfile && (!systemfile || ajTimeDiff(systemtime, usertime) > 0.0))
6211     {
6212         ajFileClose(&systemfile);
6213         ret = userfile;
6214         ajDebug("user file '%F' %D selected\n", userfile, usertime);
6215     }
6216     else
6217     {
6218         ajFileClose(&userfile);
6219         ret = systemfile;
6220         ajDebug("system file '%F' %D selected\n", systemfile, systemtime);
6221     }
6222 
6223     ajStrTokenDel(&handle);
6224     ajStrDel(&readline);
6225     ajStrDel(&token);
6226     ajTimeDel(&systemtime);
6227     ajTimeDel(&usertime);
6228 
6229     return ret;
6230 }
6231 
6232 
6233 
6234 
6235 /* @funcstatic namSvrCacheRead ************************************************
6236 **
6237 ** Reads the database cachefile for a server
6238 **
6239 ** Searches emboss_standard and the user directory ~/.embossdata/
6240 ** testing the file data in each file found and parsing the most recent file.
6241 **
6242 ** cache files must all start with a comment line
6243 ** containing the file name and the creation date.
6244 **
6245 ** @param [r] server [const AjPStr] Server name
6246 ** @param [r] cachename [const AjPStr] Cache file name
6247 ** @return [AjBool] True on success
6248 **
6249 **
6250 ** @release 6.4.0
6251 ******************************************************************************/
6252 
namSvrCacheRead(const AjPStr server,const AjPStr cachename)6253 static AjBool namSvrCacheRead(const AjPStr server, const AjPStr cachename)
6254 {
6255     AjPFile cachefile;
6256     AjPTable dbtable;
6257     AjPTable alitable;
6258     NamPEntry fnew = NULL;
6259 
6260     cachefile = namSvrCacheOpen(cachename);
6261     if(!cachefile)
6262         return ajFalse;
6263 
6264     dbtable = ajTablecharNewCase(30);
6265     alitable = ajTablecharNewCase(30);
6266 
6267     namSvrCacheParse(cachefile, dbtable, alitable);
6268     ajFileClose(&cachefile);
6269 
6270     AJNEW0(fnew);
6271     fnew->name = ajStrNewS(server);
6272     fnew->value = ajStrNewS(cachename);
6273     fnew->data = dbtable;
6274     ajTablePut(namSvrDatabaseTable, ajCharNewS(server), fnew);
6275     fnew = NULL;
6276 
6277     AJNEW0(fnew);
6278     fnew->name = ajStrNewS(server);
6279     fnew->value = ajStrNewS(cachename);
6280     fnew->data = alitable;
6281     ajTablePut(namSvrAliasTable, ajCharNewS(server), fnew);
6282     fnew = NULL;
6283 
6284 
6285     return ajTrue;
6286 }
6287 
6288 
6289 
6290 
6291 /* @funcstatic namProcessFile *************************************************
6292 **
6293 ** Read the definitions file and append each token to the list.
6294 **
6295 ** @param [u] file [AjPFile] Input file object
6296 ** @param [r] shortname [const AjPStr] Definitions file short name
6297 ** @return [AjBool] ajTrue if no error were found
6298 **
6299 ** @release 1.0.0
6300 ** @@
6301 ******************************************************************************/
6302 
namProcessFile(AjPFile file,const AjPStr shortname)6303 static AjBool namProcessFile(AjPFile file, const AjPStr shortname)
6304 {
6305     AjPStr rdline = NULL;
6306     AjPStr word   = NULL;
6307     const char *ptr;
6308     ajint i = 0;
6309     ajint len;
6310     char quote = '\0';
6311     AjPList listwords;
6312     AjPList listcount;
6313     AjPStr wordptr;
6314     ajint iline = 0;
6315     ajint *k    = NULL;
6316 
6317     ajint preverrorcount = namErrorCount;
6318 
6319     listwords = ajListstrNew();
6320     listcount = ajListNew();
6321     word      = ajStrNewRes(128);
6322 
6323     ajFmtPrintS(&namFileName, "%F", file);
6324     namUser("namProcessFile '%F'\n", file);
6325 
6326     /* Read in the settings. */
6327     while(ajReadlineTrim(file, &rdline))
6328     {
6329 	iline++;
6330 	AJNEW0(k);
6331 	*k = (ajuint) ajListGetLength(listwords);
6332 	ajListPushAppend(listcount, k);
6333 
6334         /* Ignore if the line is a comment */
6335 	if(!ajStrCutCommentsStart(&rdline))
6336 	    continue;
6337 
6338 	/* namUser("%S\n",rdline); */
6339 	len = ajStrGetLen(rdline);
6340 
6341 	/* now create a linked list of the "words" */
6342 	if(len)
6343 	{
6344 	    ptr = ajStrGetPtr(rdline);
6345 	    i = 0;
6346 
6347 	    while(*ptr && i < len)
6348 	    {
6349 		if(*ptr == ' ' || *ptr == '\t')
6350 		{
6351 		    if(ajStrGetLen(word))
6352 		    {
6353 			wordptr = ajStrNewS(word);
6354 			ajListstrPushAppend(listwords, wordptr);
6355 			ajStrAssignClear(&word);
6356 		    }
6357 
6358 		    i++;
6359 		    ptr++;
6360 		    continue;
6361 		}
6362 		else if(*ptr == '\'' || *ptr == '\"')
6363 		{
6364 		    ajStrAppendK(&word,*ptr);
6365 
6366 		    if(quote)
6367 		    {
6368 			if(quote == *ptr)
6369 			    quote = '\0';
6370 		    }
6371 		    else
6372 			quote = *ptr;
6373 		}
6374 		else if(!quote && ajStrGetLen(word) && *ptr == ']')
6375 		{
6376 		    wordptr = ajStrNewS(word);
6377 		    ajListstrPushAppend(listwords, wordptr);
6378 		    ajStrAssignClear(&word);
6379 		    wordptr = ajStrNewC("]");
6380 		    ajListstrPushAppend(listwords, wordptr);
6381 		    ajStrAssignClear(&word);
6382 		}
6383 		else
6384 		    ajStrAppendK(&word,*ptr);
6385 		i++;ptr++;
6386 	    }
6387 
6388 	    if(ajStrGetLen(word))
6389 	    {
6390 		wordptr = ajStrNewS(word);
6391 		ajListstrPushAppend(listwords, wordptr);
6392 		ajStrAssignClear(&word);
6393 	    }
6394 
6395 	}
6396     }
6397 
6398     ajStrDel(&rdline);
6399 
6400     AJNEW0(k);
6401     *k = (ajuint) ajListGetLength(listwords);
6402     ajListPushAppend(listcount, k);
6403 
6404     namListParseOK = ajTrue;
6405 
6406     namUser("ready to parse\n");
6407     namListParse(listwords, listcount, file, shortname);
6408 
6409     if(!namListParseOK)
6410 	namUser("Unexpected end of file in %S at line %d\n",
6411 		namRootStr, iline);
6412 
6413     namUser("file read\n");
6414     ajListstrFreeData(&listwords); /* Delete the linked list structure */
6415     namUser("wordlist free\n");
6416     ajListFree(&listcount);	/* Delete the linked list structure */
6417     namUser("countlist free\n");
6418 
6419     namDebugVariables();
6420     namDebugAliases();
6421     ajStrDel(&word);
6422 
6423     namUser("namProcessFile done '%F'\n", file);
6424 
6425     if(namErrorCount > preverrorcount)
6426 	return ajFalse;
6427 
6428     return ajTrue;
6429 }
6430 
6431 
6432 
6433 
6434 /* @func ajNamInit ************************************************************
6435 **
6436 ** Initialise the variable and database definitions. Find the definition
6437 ** files and read them.
6438 **
6439 ** @param [r] prefix [const char*] Default prefix for all file
6440 **                                 and variable names.
6441 ** @return [void]
6442 **
6443 ** @release 1.0.0
6444 ** @@
6445 ******************************************************************************/
6446 
ajNamInit(const char * prefix)6447 void ajNamInit(const char* prefix)
6448 {
6449     const char *prefixRoot;
6450     char *prefixHomedir = NULL;
6451     AjPFile prefixRootFile = NULL;
6452     AjPStr prefixRootStr = NULL;
6453     AjPStr prefixStr     = NULL;
6454     AjPStr prefixCap     = NULL;
6455     AjPStr debugStr      = NULL;
6456     AjPStr debugVal      = NULL;
6457     AjPStr homercVal     = NULL;
6458     AjPStr basename      = NULL;
6459     AjBool root_defined;
6460     AjBool is_windows = ajFalse;
6461     NamPEntry entryAuto  = NULL;
6462 
6463     /*
6464     ** The Windows socket interface must be initialised before any
6465     ** socket calls are made elsewhere in the AJAX library.
6466     ** This must only be done once so here is as good a place
6467     ** as any to do it.
6468     ** Set the winsock version to 1.1
6469     **
6470     ** Also note that EMBOSS_ROOT must be set for ajNamInit to
6471     ** work with Windows. This will be done by the Windows
6472     ** installer but developers must set it manually e,g,
6473     **    set EMBOSS_ROOT C:\emboss\win32
6474     */
6475 #ifdef WIN32
6476     WSADATA wsaData;
6477     AjPStr tmpstr        = NULL;
6478 #endif
6479 
6480     if(namVarMasterTable &&
6481        namAliasMasterTable &&
6482        namSvrMasterTable &&
6483        namDbMasterTable &&
6484        namResMasterTable)
6485 	return;
6486 
6487 #ifdef HAVE_MCHECK
6488     /*
6489     ** mcheck turns on checking of all malloc/calloc/realloc/free calls
6490     **
6491     ** it *must* be called before any other malloc by the main program
6492     **
6493     ** ajMemCheck reports on status. If called via ajMemProbe (AJMPROBE)
6494     ** it can also report the source file line it was invoked from
6495     **
6496     ** This is all specific to glibc and must be turned on with ./configure
6497     */
6498     if(mcheck(ajMemCheck))
6499 	ajWarn("ajNamInit called after first malloc - ajMemCheck ignored");
6500 #endif /* ! HAVE_MCHECK */
6501 
6502 #ifdef WIN32
6503     WSAStartup(MAKEWORD(1, 1), &wsaData);
6504     is_windows = ajTrue;
6505 #endif
6506 
6507 
6508     /*
6509     ** static namPrefixStr is the prefix for all variable names
6510     */
6511 
6512     ajStrAssignC(&namPrefixStr, prefix);
6513 
6514     ajStrAppendC(&namPrefixStr, "_");
6515 
6516     ajClockReset();
6517     ajTimeReset();
6518 
6519     /* create new tables to hold the values */
6520 
6521     namVarMasterTable = ajTablecharNewCase(100);
6522     namAliasMasterTable = ajTablecharNewCase(100);
6523     namSvrMasterTable = ajTablecharNewCase(100);
6524     namDbMasterTable = ajTablecharNewCase(100);
6525     namResMasterTable = ajTablecharNewCase(100);
6526     namSvrDatabaseTable = ajTablecharNewCase(100);
6527     namSvrAliasTable = ajTablecharNewCase(100);
6528 
6529 #ifdef HAVE_AXIS2C
6530     AJNEW0(entryAuto);
6531     entryAuto->name = ajStrNewC("emboss_axis2c");
6532     entryAuto->value = ajStrNewC("1");
6533     entryAuto->file = ajStrNewC("auto");
6534     ajTablePut(namVarMasterTable, ajCharNewC("emboss_axis2c"),
6535                entryAuto);
6536     entryAuto = NULL;
6537 #endif
6538 
6539 #if defined(HAVE_MYSQL) || defined(HAVE_POSTGRESQL)
6540     AJNEW0(entryAuto);
6541     entryAuto->name = ajStrNewC("emboss_sql");
6542     entryAuto->value = ajStrNewC("1");
6543     entryAuto->file = ajStrNewC("auto");
6544     ajTablePut(namVarMasterTable, ajCharNewC("emboss_sql"),
6545                entryAuto);
6546     entryAuto = NULL;
6547 
6548 #ifdef HAVE_MYSQL
6549     AJNEW0(entryAuto);
6550     entryAuto->name = ajStrNewC("emboss_mysql");
6551     entryAuto->value = ajStrNewC("1");
6552     entryAuto->file = ajStrNewC("auto");
6553     ajTablePut(namVarMasterTable, ajCharNewC("emboss_mysql"),
6554                entryAuto);
6555     entryAuto = NULL;
6556 #endif
6557 #ifdef HAVE_POSTGRESQL
6558     AJNEW0(entryAuto);
6559     entryAuto->name = ajStrNewC("emboss_postgresql");
6560     entryAuto->value = ajStrNewC("1");
6561     entryAuto->file = ajStrNewC("auto");
6562     ajTablePut(namVarMasterTable, ajCharNewC("emboss_postgresql"),
6563                entryAuto);
6564     entryAuto = NULL;
6565 #endif
6566 #endif
6567 
6568     /*
6569     ** for each type of file read it and save the values
6570     ** Start at system level then go to user
6571     */
6572 
6573     /*
6574     ** local prefixRoot is the root directory
6575     ** it is the value of (PREFIX)_ROOT (if set) or namFixedRoot
6576     */
6577 
6578     ajStrAssignC(&debugStr, prefix);
6579 
6580     ajStrAppendC(&debugStr, "_namdebug");
6581     ajStrFmtUpper(&debugStr);
6582 
6583     if(ajNamGetenvS(debugStr, &debugVal))
6584 	ajStrToBool(debugVal, &namDoDebug);
6585 
6586     ajStrAssignC(&debugStr, prefix);
6587 
6588     ajStrAppendC(&debugStr, "_namvalid");
6589     ajStrFmtUpper(&debugStr);
6590 
6591     if(ajNamGetenvS(debugStr, &debugVal))
6592 	ajStrToBool(debugVal, &namDoValid);
6593 
6594     ajStrDel(&debugStr);
6595     ajStrDel(&debugVal);
6596 
6597     ajStrAssignC(&prefixStr, prefix);
6598 
6599     ajStrAppendC(&prefixStr, "_ROOT");
6600     ajStrFmtUpper(&prefixStr);
6601 
6602     ajStrAppendC(&prefixCap, prefix);
6603     ajStrFmtUpper(&prefixCap);
6604 
6605     root_defined = ajNamGetenvS(prefixStr, &prefixRootStr);
6606 
6607     if(!root_defined && is_windows)
6608 	ajDie("EMBOSS_ROOT must be defined for Windows");
6609 
6610     if(root_defined)
6611     {
6612 	prefixRoot = ajStrGetPtr(prefixRootStr);
6613 
6614 #ifdef WIN32
6615         /* namInstallRoot undefined for Windows ... use required EMBOSS_ROOT */
6616 
6617         ajStrAssignS(&tmpstr, prefixRootStr);
6618 	ajStrAppendC(&tmpstr, "\\apps\\Release");
6619 
6620         if(ajFilenameExistsDir(tmpstr))
6621             strcpy(namInstallRoot, ajStrGetPtr(tmpstr));
6622         else
6623             strcpy(namInstallRoot,prefixRoot);
6624 
6625         ajStrDel(&tmpstr);
6626 #endif
6627     }
6628     else
6629 	prefixRoot = namFixedRoot;
6630 
6631     /* namFixedBaseStr is the directory above the source root */
6632 
6633     ajStrAssignC(&namFixedRootStr, prefixRoot);
6634     ajStrAssignS(&namFixedBaseStr, namFixedRootStr);
6635 #ifndef WIN32
6636     ajDirnameUp(&namFixedBaseStr);
6637 #endif
6638 
6639     ajStrAssignC(&namFixedPackageStr, namPackage);
6640     ajStrAssignC(&namFixedSystemStr, namSystem);
6641     ajStrAssignC(&namFixedVersionStr, namVersion);
6642     if(ajStrGetLen(namFixedVersionStr) < 7)
6643         ajStrAppendC(&namFixedVersionStr, ".0");
6644 
6645     ajStrAssignC(&namFixedInstallStr, namInstallRoot);
6646 
6647     if(is_windows)
6648     {
6649         ajFmtPrintS(&namStandardDir, "%s",
6650                     namInstallRoot);
6651     }
6652     else
6653     {
6654         ajFmtPrintS(&namStandardDir, "%s%sshare%s%S",
6655                     namInstallRoot, SLASH_STRING, SLASH_STRING, prefixCap);
6656     }
6657     ajFmtPrintS(&namStandardFilename, "%S%s%s.standard",
6658                 namStandardDir, SLASH_STRING, prefix);
6659     prefixRootFile = ajFileNewInNameS(namStandardFilename);
6660     ajStrAssignC(&basename, "standard");
6661 
6662     if(!prefixRootFile)
6663     {
6664 	/* try original directory */
6665         ajStrAssignC(&namStandardDir, prefixRoot);
6666 	    ajFmtPrintS(&namStandardFilename, "%s%s%s.standard", prefixRoot,
6667 			SLASH_STRING,prefix);
6668 
6669 	prefixRootFile = ajFileNewInNameS(namStandardFilename);
6670     }
6671 
6672     if(prefixRootFile)
6673     {
6674         AJNEW0(entryAuto);
6675         entryAuto->name = ajStrNewC("emboss_standard");
6676         entryAuto->value = ajStrNewS(namStandardDir);
6677         entryAuto->file = ajStrNewRef(namStandardFilename);
6678         ajTablePut(namVarMasterTable, ajCharNewC("emboss_standard"),
6679                    entryAuto);
6680         entryAuto = NULL;
6681 
6682 	ajStrAppendC(&namFileOrig, "(OK)");
6683 	namProcessFile(prefixRootFile, basename);
6684 	ajFileClose(&prefixRootFile);
6685 
6686         if(namFileOrig)
6687             ajStrAppendC(&namFileOrig, ", ");
6688 
6689         ajStrAppendS(&namFileOrig, namStandardFilename);
6690     }
6691     else
6692 	ajStrAppendC(&namFileOrig, "(failed)");
6693 
6694     /*
6695     ** EMBOSS is distributed with an emboss.standard file
6696     ** Looks for this file and set EMBOSS_STANDARD variable to its directory
6697     */
6698 
6699     /*
6700     ** look for the site's default file in the install directory as
6701        <install-prefix>/share/PREFIX/emboss.default
6702     **
6703     */
6704 
6705     ajFmtPrintS(&namRootStr, "%s%sshare%s%S%s%s.default",
6706 		 namInstallRoot, SLASH_STRING, SLASH_STRING,
6707                 prefixCap, SLASH_STRING, prefix);
6708     prefixRootFile = ajFileNewInNameS(namRootStr);
6709     ajStrAssignC(&basename, "global");
6710 
6711     /* look for $(PREFIX)_ROOT/../emboss.default */
6712 
6713     if(!prefixRootFile)
6714     {
6715 	/* try original directory */
6716 	    ajFmtPrintS(&namRootStr, "%s%s%s.default", prefixRoot,
6717 			SLASH_STRING,prefix);
6718 
6719 	prefixRootFile = ajFileNewInNameS(namRootStr);
6720 	ajStrAssignC(&basename, "source");
6721     }
6722 
6723     if(namFileOrig)
6724 	ajStrAppendC(&namFileOrig, ", ");
6725 
6726     ajStrAppendS(&namFileOrig, namRootStr);
6727 
6728     if(prefixRootFile)
6729     {
6730 	ajStrAppendC(&namFileOrig, "(OK)");
6731 	namProcessFile(prefixRootFile, basename);
6732 	ajFileClose(&prefixRootFile);
6733     }
6734     else
6735 	ajStrAppendC(&namFileOrig, "(failed)");
6736 
6737 
6738 
6739     /* look for .embossrc in an arbitrary directory */
6740 
6741     prefixRoot= getenv("EMBOSSRC");
6742 
6743     if(prefixRoot)
6744     {
6745 	ajStrAssignC(&namRootStr, prefixRoot);
6746 	ajStrAppendC(&namRootStr, SLASH_STRING);
6747 	ajStrAppendC(&namRootStr, ".");
6748 	ajStrAppendC(&namRootStr, prefix);
6749 	ajStrAppendC(&namRootStr, "rc");
6750 
6751 	if(namFileOrig)
6752 	    ajStrAppendC(&namFileOrig, ", ");
6753 
6754 	ajStrAppendS(&namFileOrig, namRootStr);
6755 
6756 	prefixRootFile = ajFileNewInNameS(namRootStr);
6757 
6758 	if(prefixRootFile)
6759 	{
6760 	    ajStrAssignC(&basename, "special");
6761 	    ajStrAppendC(&namFileOrig, "(OK)");
6762 	    namProcessFile(prefixRootFile, basename);
6763 	    ajFileClose(&prefixRootFile);
6764 	}
6765 	else
6766 	    ajStrAppendC(&namFileOrig, "(failed)");
6767     }
6768 
6769 
6770     /*
6771     ** look for $HOME/.embossrc
6772     **
6773     ** Note that this will not work with Windows as there is
6774     ** no concept of HOME
6775     */
6776 
6777     prefixHomedir = ajSysGetHomedir();
6778 
6779     ajStrAssignC(&namUserDir, prefixHomedir);
6780     ajStrAppendC(&namUserDir, SLASH_STRING);
6781     ajStrAppendC(&namUserDir, ".embossdata");
6782     ajStrAppendC(&namUserDir, SLASH_STRING);
6783 
6784     ajStrAssignC(&prefixStr, prefix);
6785     ajStrAppendC(&prefixStr, "_RCHOME");
6786     ajStrFmtUpper(&prefixStr);
6787 
6788     if(ajNamGetenvS(prefixStr, &homercVal))
6789 	ajStrToBool(homercVal, &namDoHomeRc);
6790 
6791     ajStrDel(&homercVal);
6792 
6793     if(namDoHomeRc && prefixHomedir)
6794     {
6795 	ajStrAssignC(&namRootStr, prefixHomedir);
6796 	ajStrAppendC(&namRootStr, SLASH_STRING);
6797 	ajStrAppendC(&namRootStr, ".");
6798 	ajStrAppendC(&namRootStr, prefix);
6799 	ajStrAppendC(&namRootStr, "rc");
6800 
6801 	if(namFileOrig)
6802 	    ajStrAppendC(&namFileOrig, ", ");
6803 
6804 	ajStrAppendS(&namFileOrig, namRootStr);
6805 
6806 	ajStrAssignC(&basename, "user");
6807 	prefixRootFile = ajFileNewInNameS(namRootStr);
6808 
6809 	if(prefixRootFile)
6810 	{
6811 	    ajStrAppendC(&namFileOrig, "(OK)");
6812 	    namProcessFile(prefixRootFile, basename);
6813 	    ajFileClose(&prefixRootFile);
6814 	}
6815 	else
6816 	    ajStrAppendC(&namFileOrig, "(failed)");
6817     }
6818 
6819     namUser("Files processed: %S\n", namFileOrig);
6820 
6821     ajCharDel(&prefixHomedir);
6822     ajStrDel(&prefixRootStr);
6823     ajStrDel(&basename);
6824     ajStrDel(&prefixStr);
6825     ajStrDel(&prefixCap);
6826 
6827     if(!namFixedSystemStr)
6828         namFixedSystemStr = ajStrNewC(namSystem);
6829 
6830     if(!namFixedVersionStr)
6831     {
6832         namFixedVersionStr = ajStrNewC(namVersion);
6833         if(ajStrGetLen(namFixedVersionStr) < 7)
6834             ajStrAppendC(&namFixedVersionStr, ".0");
6835     }
6836 
6837     if(namErrorCount)		/* test: badsummary.rc */
6838 	ajDie("Error(s) in configuration files");
6839 
6840     return;
6841 }
6842 
6843 
6844 
6845 
6846 /* @funcstatic namNoColon *****************************************************
6847 **
6848 ** Remove any trailing colon ':' in the input string.
6849 **
6850 ** @param [u] thys [AjPStr*] String.
6851 ** @return [void]
6852 **
6853 ** @release 1.0.0
6854 ** @@
6855 ******************************************************************************/
6856 
namNoColon(AjPStr * thys)6857 static void namNoColon(AjPStr* thys)
6858 {
6859     if(ajStrGetCharLast(*thys) == ':')
6860 	ajStrCutEnd(thys, 1);
6861 
6862     return;
6863 }
6864 
6865 
6866 
6867 
6868 /* @funcstatic namDbAttrC *****************************************************
6869 **
6870 ** Return the index for a database attribute name.
6871 **
6872 ** @param [r] str [const char*] Attribute name.
6873 ** @return [ajint] Index in namDbAttrs, or -1 on failure.
6874 **
6875 ** @release 1.0.0
6876 ** @@
6877 ******************************************************************************/
6878 
namDbAttrC(const char * str)6879 static ajint namDbAttrC(const char* str)
6880 {
6881     ajint i = 0;
6882     ajint j = 0;
6883     ajint ifound = 0;
6884 
6885     ajStrAssignC(&namCmpStr, str);
6886     ajStrFmtLower(&namCmpStr);
6887 
6888     for(i=0; namDbAttrs[i].Name; i++)
6889     {
6890 	if(ajStrMatchC(namCmpStr, namDbAttrs[i].Name))
6891 	    return i;
6892 
6893 	if(ajCharPrefixS(namDbAttrs[i].Name, namCmpStr))
6894 	{
6895 	    ifound++;
6896 	    j = i;
6897 	}
6898     }
6899 
6900     if(ifound == 1)
6901 	return j;
6902 
6903     return -1;
6904 }
6905 
6906 
6907 
6908 
6909 /* @funcstatic namDbAttrS *****************************************************
6910 **
6911 ** Return the index for a database attribute name.
6912 **
6913 ** @param [r] thys [const AjPStr] Attribute name.
6914 ** @return [ajint] Index in namDbAttrs, or -1 on failure.
6915 **
6916 ** @release 6.4.0
6917 ** @@
6918 ******************************************************************************/
6919 
namDbAttrS(const AjPStr thys)6920 static ajint namDbAttrS(const AjPStr thys)
6921 {
6922     return namDbAttrC(ajStrGetPtr(thys));
6923 }
6924 
6925 
6926 
6927 
6928 /* @funcstatic namSvrAttrC ****************************************************
6929 **
6930 ** Return the index for a server attribute name.
6931 **
6932 ** @param [r] str [const char*] Attribute name.
6933 ** @return [ajint] Index in namSvrAttrs, or -1 on failure.
6934 **
6935 ** @release 6.4.0
6936 ** @@
6937 ******************************************************************************/
6938 
namSvrAttrC(const char * str)6939 static ajint namSvrAttrC(const char* str)
6940 {
6941     ajint i = 0;
6942     ajint j = 0;
6943     ajint ifound = 0;
6944 
6945     ajStrAssignC(&namCmpStr, str);
6946     ajStrFmtLower(&namCmpStr);
6947 
6948     for(i=0; namSvrAttrs[i].Name; i++)
6949     {
6950 	if(ajStrMatchC(namCmpStr, namSvrAttrs[i].Name))
6951 	    return i;
6952 
6953 	if(ajCharPrefixS(namSvrAttrs[i].Name, namCmpStr))
6954 	{
6955 	    ifound++;
6956 	    j = i;
6957 	}
6958     }
6959 
6960     if(ifound == 1)
6961 	return j;
6962 
6963     return -1;
6964 }
6965 
6966 
6967 
6968 
6969 /* @funcstatic namSvrAttrS ****************************************************
6970 **
6971 ** Return the index for a server attribute name.
6972 **
6973 ** @param [r] thys [const AjPStr] Attribute name.
6974 ** @return [ajint] Index in namSvrAttrs, or -1 on failure.
6975 **
6976 ** @release 6.4.0
6977 ** @@
6978 ******************************************************************************/
6979 
namSvrAttrS(const AjPStr thys)6980 static ajint namSvrAttrS(const AjPStr thys)
6981 {
6982     return namSvrAttrC(ajStrGetPtr(thys));
6983 }
6984 
6985 
6986 
6987 
6988 /* @funcstatic namRsAttrC *****************************************************
6989 **
6990 ** Return the index for a resource attribute name.
6991 **
6992 ** @param [r] str [const char*] Attribute name.
6993 ** @return [ajint] Index in namRsAttrs, or -1 on failure.
6994 **
6995 ** @release 2.7.0
6996 ** @@
6997 ******************************************************************************/
6998 
namRsAttrC(const char * str)6999 static ajint namRsAttrC(const char* str)
7000 {
7001     ajint i = 0;
7002     ajint j = 0;
7003     ajint ifound = 0;
7004 
7005     ajStrAssignC(&namCmpStr, str);
7006     ajStrFmtLower(&namCmpStr);
7007 
7008 
7009     for(i=0; namRsAttrs[i].Name; i++)
7010     {
7011 	if(ajStrMatchC(namCmpStr, namRsAttrs[i].Name))
7012 	    return i;
7013 
7014 	if(ajCharPrefixS(namRsAttrs[i].Name, namCmpStr))
7015 	{
7016 	    ifound++;
7017 	    j = i;
7018 	}
7019     }
7020 
7021     if(ifound == 1)
7022 	return j;
7023 
7024     return -1;
7025 }
7026 
7027 
7028 
7029 
7030 /* @funcstatic namRsAttrS *****************************************************
7031 **
7032 ** Return the index for a resource attribute name.
7033 **
7034 ** @param [r] thys [const AjPStr] Attribute name.
7035 ** @return [ajint] Index in namRsAttrs, or -1 on failure.
7036 **
7037 ** @release 6.4.0
7038 ** @@
7039 ******************************************************************************/
7040 
namRsAttrS(const AjPStr thys)7041 static ajint namRsAttrS(const AjPStr thys)
7042 {
7043     return namRsAttrC(ajStrGetPtr(thys));
7044 }
7045 
7046 
7047 
7048 
7049 /* @funcstatic namRsAttrFieldC ************************************************
7050 **
7051 ** Return the validity of a resource attribute name using a known field prefix
7052 **
7053 ** @param [r] rstable [const AjPTable] Resource table
7054 ** @param [r] str [const char*] Attribute name.
7055 ** @return [AjBool] Attribute name matches a defined field and property
7056 **
7057 ** @release 6.4.0
7058 ** @@
7059 ******************************************************************************/
7060 
namRsAttrFieldC(const AjPTable rstable,const char * str)7061 static AjBool namRsAttrFieldC(const AjPTable rstable, const char* str)
7062 {
7063     AjBool ret = ajFalse;
7064     AjPStr prefix = NULL;
7065     const AjPStr fields = NULL;
7066     AjPStrTok handle = NULL;
7067     AjPStr field = NULL;
7068     const AjPStr type = NULL;
7069     const AjPList fdlist = NULL;
7070     AjIList iter = NULL;
7071     const NamPAttr attr = NULL;
7072 
7073     type = ajTableFetchmodC(rstable, "type");
7074 
7075     if(!ajStrMatchC(type, "Index"))
7076         return ajFalse;
7077 
7078     if(ajCharSuffixC(str, "len"))
7079         ajStrAssignSubC(&prefix, str, 0, -4);
7080     else if(ajCharSuffixC(str, "seccachesize"))
7081         ajStrAssignSubC(&prefix, str, 0, -13);
7082     else if(ajCharSuffixC(str, "cachesize"))
7083         ajStrAssignSubC(&prefix, str, 0, -10);
7084     else if(ajCharSuffixC(str, "secpagesize"))
7085         ajStrAssignSubC(&prefix, str, 0, -12);
7086     else if(ajCharSuffixC(str, "pagesize"))
7087         ajStrAssignSubC(&prefix, str, 0, -9);
7088     else
7089         return ajFalse;
7090 
7091     if(ajStrGetLen(prefix))
7092     {
7093         fields = ajTableFetchmodC(rstable, "fields");
7094 
7095         if(fields)
7096         {
7097             handle = ajStrTokenNewC(fields, " ,;");
7098 
7099             while(ajStrTokenNextParse(handle, &field))
7100                 if(ajStrMatchS(prefix, field))
7101                     ret = ajTrue;
7102         }
7103         else
7104         {
7105             fdlist = ajTableFetchC(rstable, "field");
7106 
7107             if(fdlist)
7108             {
7109                 iter = ajListIterNewread(fdlist);
7110 
7111                 while(!ajListIterDone(iter))
7112                 {
7113                     fields = ajListIterGet(iter);
7114                     ajStrTokenAssignC(&handle, fields, " ,;");
7115 
7116                     while(ajStrTokenNextParse(handle, &field))
7117                     {
7118                         if(ajStrMatchC(field, "!"))
7119                             break;
7120 
7121                         if(ajStrMatchS(prefix, field))
7122                             ret = ajTrue;
7123                     }
7124                 }
7125 
7126                 ajListIterDel(&iter);
7127             }
7128             else
7129             {
7130                 attr = ajTableFetchC(namResAttrTable, "fields");
7131                 handle = ajStrTokenNewcharC(attr->Defval, " ,;");
7132 
7133                 while(ajStrTokenNextParse(handle, &field))
7134                     if(ajStrMatchS(prefix, field))
7135                         ret = ajTrue;
7136             }
7137         }
7138 
7139         ajStrTokenDel(&handle);
7140         ajStrDel(&field);
7141     }
7142 
7143     ajStrDel(&prefix);
7144 
7145     return ret;
7146 }
7147 
7148 
7149 
7150 
7151 /* @funcstatic namRsAttrFieldS ************************************************
7152 **
7153 ** Return the validity of a resource attribute name using a known field prefix
7154 **
7155 ** @param [r] rstable [const AjPTable] Resource table
7156 ** @param [r] str [const AjPStr] Attribute name.
7157 ** @return [AjBool] Attribute name matches a defined field and property
7158 **
7159 ** @release 6.4.0
7160 ** @@
7161 ******************************************************************************/
7162 
namRsAttrFieldS(const AjPTable rstable,const AjPStr str)7163 static AjBool namRsAttrFieldS(const AjPTable rstable, const AjPStr str)
7164 {
7165     AjBool ret = ajFalse;
7166     AjPStr prefix = NULL;
7167     const AjPStr fields = NULL;
7168     AjPStrTok handle = NULL;
7169     AjPStr field = NULL;
7170     const AjPStr type = NULL;
7171     AjPList fdlist = NULL;
7172     AjIList iter = NULL;
7173     const NamPAttr attr = NULL;
7174 
7175     type = ajTableFetchC(rstable, "type");
7176 
7177     if(!ajStrMatchC(type, "Index"))
7178         return ajFalse;
7179 
7180     if(ajStrSuffixC(str, "len"))
7181         ajStrAssignSubS(&prefix, str, 0, -4);
7182     else if(ajStrSuffixC(str, "seccachesize"))
7183         ajStrAssignSubS(&prefix, str, 0, -13);
7184     else if(ajStrSuffixC(str, "cachesize"))
7185         ajStrAssignSubS(&prefix, str, 0, -10);
7186     else if(ajStrSuffixC(str, "secpagesize"))
7187         ajStrAssignSubS(&prefix, str, 0, -12);
7188     else if(ajStrSuffixC(str, "pagesize"))
7189         ajStrAssignSubS(&prefix, str, 0, -9);
7190     else
7191         return ajFalse;
7192 
7193     if(ajStrGetLen(prefix))
7194     {
7195         fields = ajTableFetchC(rstable, "fields");
7196 
7197         if(fields)
7198         {
7199             handle = ajStrTokenNewC(fields, " ,;");
7200 
7201             while(ajStrTokenNextParse(handle, &field))
7202                 if(ajStrMatchS(prefix, field))
7203                     ret = ajTrue;
7204         }
7205         else
7206         {
7207             fdlist = ajTableFetchmodC(rstable, "field");
7208 
7209             if(fdlist)
7210             {
7211                 iter = ajListIterNewread(fdlist);
7212 
7213                 while(!ajListIterDone(iter))
7214                 {
7215                     fields = ajListIterGet(iter);
7216                     ajStrTokenAssignC(&handle, fields, " ,;");
7217 
7218                     while(ajStrTokenNextParse(handle, &field))
7219                     {
7220                         if(ajStrMatchC(field, "!"))
7221                             break;
7222 
7223                         if(ajStrMatchS(prefix, field))
7224                             ret = ajTrue;
7225                     }
7226                 }
7227 
7228                 ajListIterDel(&iter);
7229             }
7230             else
7231             {
7232                 attr = ajTableFetchC(namResAttrTable, "fields");
7233 
7234                 if(attr)
7235                 {
7236                     handle = ajStrTokenNewcharC(attr->Defval, " ,;");
7237 
7238                     while(ajStrTokenNextParse(handle, &field))
7239                         if(ajStrMatchS(prefix, field))
7240                             ret = ajTrue;
7241                 }
7242 
7243             }
7244 
7245         }
7246 
7247 
7248 
7249         ajStrTokenDel(&handle);
7250         ajStrDel(&field);
7251     }
7252 
7253     ajStrDel(&prefix);
7254 
7255     return ret;
7256 }
7257 
7258 
7259 
7260 
7261 /* @func ajNamExit ************************************************************
7262 **
7263 ** Delete the initialisation values in the table.
7264 ** @return [void]
7265 **
7266 ** @release 1.0.0
7267 ** @@
7268 ******************************************************************************/
7269 
ajNamExit(void)7270 void ajNamExit(void)
7271 {
7272     namListMasterDelete(namVarMasterTable, TYPE_ENV); /* Delete elements */
7273     ajTableFree(&namVarMasterTable); /* free table and database structures */
7274     namListMasterDelete(namAliasMasterTable, TYPE_ALIAS); /* Delete elements */
7275     ajTableFree(&namAliasMasterTable); /* free table and database structures */
7276     namListMasterDelete(namSvrMasterTable, TYPE_SVR); /* Delete elements */
7277     ajTableFree(&namSvrMasterTable); /* free table and database structures */
7278     namListMasterDelete(namDbMasterTable, TYPE_DB); /* Delete elements */
7279     ajTableFree(&namDbMasterTable); /* free table and database structures */
7280     namListMasterDelete(namResMasterTable, TYPE_RESOURCE);/* Delete elements */
7281     ajTableFree(&namResMasterTable); /* free table and database structures */
7282     namListMasterDelete(namSvrDatabaseTable, TYPE_SVRDB);/* Delete elements */
7283     ajTableFree(&namSvrDatabaseTable); /* free table and database structures */
7284     namListMasterDelete(namSvrAliasTable, TYPE_SVRALI);/* Delete elements */
7285     ajTableFree(&namSvrAliasTable); /* free table and database structures */
7286 
7287     ajTablestrFreeKey(&namDbTypeTable); /* free table and strings */
7288 
7289     ajTablestrFree(&namSvrAttrTable); /* free table and strings */
7290     ajTablestrFree(&namDbAttrTable); /* free table and strings */
7291     ajTablestrFree(&namResAttrTable); /* free table and strings */
7292 
7293     ajStrDel(&namFixedBaseStr);    /* allocated in ajNamInit */
7294     ajStrDel(&namFixedRootStr);    /* allocated in ajNamInit */
7295     ajStrDel(&namFixedInstallStr); /* allocated in ajNamInit */
7296     ajStrDel(&namFixedPackageStr); /* allocated in ajNamInit */
7297     ajStrDel(&namFixedSystemStr);  /* allocated in ajNamInit */
7298     ajStrDel(&namFixedVersionStr); /* allocated in ajNamInit */
7299     ajStrDel(&namPrefixStr);       /* allocated in ajNamInit */
7300     ajStrDel(&namFileOrig);        /* allocated in ajNamInit */
7301     ajStrDel(&namRootStr);         /* allocated in ajNamInit */
7302 
7303     ajStrDel(&namFileName);		/* allocated in ajNamProcessFile */
7304     ajStrDel(&namValNameTmp);
7305     ajStrDel(&namCmpStr);
7306     ajStrDel(&namStandardDir);
7307     ajStrDel(&namStandardFilename);
7308     ajStrDel(&namUserDir);
7309     ajStrDel(&namUserFilename);
7310 
7311     ajRegFree(&namNameExp);
7312     ajRegFree(&namVarExp);
7313 
7314     ajListFree(&namIfList);
7315 
7316     ajDebug("ajNamExit done\n");
7317 
7318     return;
7319 }
7320 
7321 
7322 
7323 
7324 /* @func ajNamSvrTest *********************************************************
7325 **
7326 ** Looks for a server name in the known definitions.
7327 **
7328 ** @param [r] svrname [const AjPStr] Server name.
7329 ** @return [AjBool] ajTrue on success.
7330 **
7331 ** @release 6.4.0
7332 ** @@
7333 ******************************************************************************/
7334 
ajNamSvrTest(const AjPStr svrname)7335 AjBool ajNamSvrTest(const AjPStr svrname)
7336 {
7337     const NamPEntry data;
7338 
7339     data = ajTableFetchS(namSvrMasterTable, svrname);
7340 
7341     if(!data)
7342 	return ajFalse;
7343 
7344     return ajTrue;
7345 }
7346 
7347 
7348 
7349 
7350 /* @func ajNamSvrGetUrl *******************************************************
7351 **
7352 ** Gets the URL definition for a server definition.
7353 **
7354 ** @param [r] svrname [const AjPStr] Server name.
7355 ** @param [w] url [AjPStr*] URL returned.
7356 ** @return [AjBool] ajTrue if success.
7357 **
7358 ** @release 6.4.0
7359 ** @@
7360 ******************************************************************************/
7361 
ajNamSvrGetUrl(const AjPStr svrname,AjPStr * url)7362 AjBool ajNamSvrGetUrl(const AjPStr svrname, AjPStr* url)
7363 {
7364 
7365     const NamPEntry data;
7366     AjPTable svrtable;
7367     const AjPStr svrval = NULL;
7368 
7369     data = ajTableFetchS(namSvrMasterTable, svrname);
7370 
7371     if(!data)
7372 	ajFatal("%S is not a known server", svrname);
7373 
7374     svrtable = (AjPTable) data->data;
7375 
7376     svrval = ajTableFetchC(svrtable, "url");
7377 
7378     if(ajStrGetLen(svrval))
7379     {
7380 	ajStrAssignS(url, svrval);
7381 
7382 	return ajTrue;
7383     }
7384 
7385     return ajFalse;
7386 }
7387 
7388 
7389 
7390 
7391 /* @func ajNamQueryGetDatatypeC ***********************************************
7392 **
7393 ** Gets the datatype matching a query, and updates the datatype in the query
7394 **
7395 ** @param [r] qry [const AjPQuery] Database query
7396 ** @return [const char*] Database type
7397 **
7398 ** @release 6.4.0
7399 ** @@
7400 ******************************************************************************/
7401 
ajNamQueryGetDatatypeC(const AjPQuery qry)7402 const char* ajNamQueryGetDatatypeC(const AjPQuery qry)
7403 {
7404     ajuint i;
7405     const char* ret = NULL;
7406 
7407     if(ajStrGetLen(qry->DbType))
7408         return MAJSTRGETPTR(qry->DbType);
7409 
7410     for(i=0; namDbTypes[i].Name; i++)
7411         if(namDbTypes[i].DataType == qry->DataType)
7412             ret = namDbTypes[i].Name;
7413 
7414     return ret;
7415 }
7416 
7417 
7418 
7419 
7420 /* @func ajNamQueryGetUrl *****************************************************
7421 **
7422 ** Gets the URL definition for a server definition.
7423 **
7424 ** @param [r] qry [const AjPQuery] Database query
7425 ** @return [const AjPStr] URL value
7426 **
7427 ** @release 6.4.0
7428 ** @@
7429 ******************************************************************************/
7430 
ajNamQueryGetUrl(const AjPQuery qry)7431 const AjPStr ajNamQueryGetUrl(const AjPQuery qry)
7432 {
7433     const AjPStr ret = NULL;
7434     const AjPStr svrval = NULL;
7435     const AjPTable dbtable;
7436 
7437     dbtable = namQuerySvrdata(qry);
7438 
7439     svrval = ajTableFetchC(dbtable, "url");
7440 
7441     if(svrval)
7442         ret = svrval;
7443 
7444     dbtable = namQueryDbdata(qry);
7445 
7446     svrval = ajTableFetchC(dbtable, "url");
7447 
7448     if(svrval)
7449         ret = svrval;
7450 
7451     return ret;
7452 }
7453 
7454 
7455 
7456 
7457 /* @funcstatic namQuerySvrdata ************************************************
7458 **
7459 ** Gets the URL definition for a server definition.
7460 **
7461 ** @param [r] qry [const AjPQuery] Query.
7462 ** @return [const AjPTable] DatabaseServer attributes table
7463 **
7464 ** @release 6.4.0
7465 ** @@
7466 ******************************************************************************/
7467 
namQuerySvrdata(const AjPQuery qry)7468 static const AjPTable namQuerySvrdata(const AjPQuery qry)
7469 {
7470     const NamPEntry data;
7471 
7472     if(!ajStrGetLen(qry->SvrName))
7473         return NULL;
7474 
7475     data = ajTableFetchS(namSvrMasterTable, qry->SvrName);
7476 
7477     if(!data)
7478 	ajFatal("%S is not a known server", qry->SvrName);
7479 
7480     return (const AjPTable) data->data;
7481 
7482 }
7483 
7484 
7485 
7486 
7487 /* @funcstatic namQueryDbdata *************************************************
7488 **
7489 ** Gets the data table for a query database.
7490 **
7491 ** @param [r] qry [const AjPQuery] Database query
7492 ** @return [const AjPTable] Database attributes table
7493 **
7494 ** @release 6.4.0
7495 ** @@
7496 ******************************************************************************/
7497 
namQueryDbdata(const AjPQuery qry)7498 static const AjPTable namQueryDbdata(const AjPQuery qry)
7499 {
7500     const NamPEntry data;
7501     const NamPEntry sdata;
7502     const AjPTable sdbtable;
7503 
7504     if(ajStrGetLen(qry->SvrName))
7505     {
7506         sdata = ajTableFetchS(namSvrDatabaseTable, qry->SvrName);
7507         sdbtable = (const AjPTable) sdata->data;
7508         data = ajTableFetchS(sdbtable, qry->DbName);
7509 
7510         if(!data)
7511             ajFatal("%S is not a known database for server %S",
7512                     qry->DbName, qry->SvrName);
7513     }
7514     else
7515     {
7516         data = ajTableFetchS(namDbMasterTable, qry->DbName);
7517 
7518         if(!data)
7519             ajFatal("%S is not a known database", qry->DbName);
7520     }
7521 
7522     return (const AjPTable) data->data;
7523 }
7524 
7525 
7526 
7527 
7528 /* @func ajNamSvrGetDbalias ***************************************************
7529 **
7530 ** Gets alias names for a server's database.
7531 **
7532 ** @param [r] svrname [const AjPStr] Server name.
7533 ** @param [w] dbalias [AjPStr*] Alias returned.
7534 ** @return [AjBool] ajTrue if success.
7535 **
7536 ** @release 6.4.0
7537 ** @@
7538 ******************************************************************************/
7539 
ajNamSvrGetDbalias(const AjPStr svrname,AjPStr * dbalias)7540 AjBool ajNamSvrGetDbalias(const AjPStr svrname, AjPStr* dbalias)
7541 {
7542     const NamPEntry data;
7543     const AjPTable svrtable;
7544     const AjPStr svrval = NULL;
7545 
7546     data = ajTableFetchS(namSvrMasterTable, svrname);
7547 
7548     if(!data)
7549 	ajFatal("%S is not a known server", svrname);
7550 
7551     svrtable = (AjPTable) data->data;
7552 
7553     svrval = ajTableFetchC(svrtable, "dbalias");
7554 
7555     if(ajStrGetLen(svrval))
7556 	ajStrAssignS(dbalias, svrval);
7557     else
7558     {
7559         ajStrAssignS(dbalias, svrname);
7560         ajStrFmtLower(dbalias);
7561     }
7562 
7563     return ajTrue;
7564 }
7565 
7566 
7567 
7568 
7569 /* @func ajNamSvrData *********************************************************
7570 **
7571 ** Given a query with server name, database name and search fields,
7572 ** fill in the common fields. The query fields are set later.
7573 **
7574 ** This part of the database definition is required (specifically
7575 ** the "fields" definition) for setting the query details.
7576 **
7577 ** See also ajNamSvrQuery, which calls this function if the common
7578 ** query data is not yet set.
7579 **
7580 ** @param [u] qry [AjPQuery] Query structure with at least
7581 **                                    dbname filled in
7582 ** @param [r] argc [ajuint] Number of additional attribute name/value pairs
7583 ** @param [v] [...] Variable length argument list
7584 ** @return [AjBool] ajTrue if success.
7585 **
7586 ** @release 6.4.0
7587 ** @@
7588 ******************************************************************************/
7589 
ajNamSvrData(AjPQuery qry,ajuint argc,...)7590 AjBool ajNamSvrData(AjPQuery qry, ajuint argc, ...)
7591 {
7592 
7593     const NamPEntry data;
7594     const NamPEntry dbdata;
7595 
7596     const AjPTable svrtable;
7597     const AjPTable sdbtable;
7598     const AjPTable dbtable;
7599     AjPStrTok handle = NULL;
7600     AjPStr liststr = NULL;
7601     AjPStr token = NULL;
7602     ajuint i;
7603     const char* varAttrName;
7604     AjPStr* varAttrValue;
7605     va_list ap;
7606     const NamPType namtype;
7607     AjBool ok = ajTrue;
7608     AjEDataType testDataType = AJDATATYPE_UNKNOWN;
7609     AjPStr saveType = NULL;
7610     AjBool donecaseid = ajFalse;
7611     AjBool donehasacc = ajFalse;
7612     AjBool caseid = ajFalse;
7613     AjBool hasacc = ajFalse;
7614 
7615     if(qry->SetServer)
7616         return ajTrue;
7617 
7618     qry->SetServer = ajTrue;
7619 
7620     data = ajTableFetchS(namSvrMasterTable, qry->SvrName);
7621 
7622     if(!data)
7623 	ajFatal("server %S unknown", qry->SvrName);
7624 
7625     svrtable = (const AjPTable) data->data;
7626 
7627     /* general defaults */
7628 
7629     namSvrSetAttrStrC(svrtable, "type", &liststr);
7630     ajStrTokenAssignC(&handle, liststr, " ,;");
7631     ajStrAssignC(&qry->DbType, "");
7632 
7633     ajDebug("Server type: '%S'\n", liststr);
7634 
7635     while(ajStrTokenNextParse(handle, &token))
7636     {
7637         if(!ajStrSuffixCaseC(token,"features"))
7638         {
7639             if(ajStrPrefixCaseC(token, "n"))
7640         	ajStrAssignC(&token, "Nucleotide");
7641             else if(ajStrPrefixCaseC(token, "p"))
7642         	ajStrAssignC(&token, "Protein");
7643         }
7644 
7645         namtype = ajTableFetchS(namDbTypeTable, token);
7646 
7647         ajDebug("testing type '%S' namtype: '%s' \n",
7648 		token, namtype->Name);
7649 
7650         if(!namtype)
7651         {
7652             ajErr("Server %S type '%S' unknown", qry->SvrName, token);
7653             continue;
7654         }
7655 
7656         ajDebug("test server type '%S' qry datatype %u nam "
7657                 "datatype %u unk %u\n",
7658                 token, qry->DataType, namtype->DataType, AJDATATYPE_UNKNOWN);
7659 
7660         if(qry->DataType == AJDATATYPE_UNKNOWN) /* take first available */
7661         {
7662             if(testDataType == AJDATATYPE_UNKNOWN ||
7663                namtype->DataType == AJDATATYPE_TEXT)
7664             {
7665                 testDataType = namtype->DataType;
7666                 ajStrAssignS(&saveType, token);
7667                 ajDebug("Save type %d '%S'\n", testDataType, saveType);
7668             }
7669         }
7670 
7671         if(namtype->DataType == qry->DataType)
7672         {
7673             ajStrAssignS(&qry->DbType, token);
7674             break;
7675         }
7676     }
7677 
7678     if(ajStrGetLen(qry->Formatstr))
7679     {
7680         if(ajStrGetLen(qry->DbType) &&
7681            !ajStrMatchC(qry->DbType, "unknown") &&
7682            !namInformatTest(qry->Formatstr, qry->DbType))
7683         {
7684             ajErr("Query format '%S' does not support datatype '%S'",
7685                   qry->Formatstr, qry->DbType);
7686             ajStrDel(&saveType);
7687             return ajFalse;
7688         }
7689     }
7690     else
7691     {
7692         if(namSvrSetAttrStrC(svrtable, "format", &liststr))
7693         {
7694             ok = ajFalse;
7695             ajStrTokenAssignC(&handle, liststr, " ,;");
7696 
7697             while(ajStrTokenNextParse(handle, &token))
7698             {
7699                 if(namInformatTest(token, qry->DbType))
7700                 {
7701                     ok = ajTrue;
7702                     ajStrAssignS(&qry->Formatstr, token);
7703                 }
7704                 if(saveType && namInformatTest(token, saveType))
7705                 {
7706                     ok = ajTrue;
7707                     ajStrAssignS(&qry->Formatstr, token);
7708                 }
7709             }
7710 
7711             if(!ok)
7712             {
7713                 ajErr("Server %S format(s) '%S' do not support "
7714                       "datatype '%S'",
7715                       qry->SvrName, liststr, qry->DbType);
7716                 ajStrDel(&saveType);
7717                 return ajFalse;
7718             }
7719         }
7720     }
7721 
7722     namSvrSetAttrStrC(svrtable, "method", &qry->Method);
7723     namSvrSetAttrStrC(svrtable, "indexdirectory", &qry->IndexDir);
7724     namSvrSetAttrStrC(svrtable, "indexdirectory", &qry->Directory);
7725     namSvrSetAttrStrC(svrtable, "field", &qry->DbFields);
7726     namSvrSetAttrStrC(svrtable, "url", &qry->DbUrl);
7727     namSvrSetAttrStrC(svrtable, "proxy", &qry->DbProxy);
7728     namSvrSetAttrStrC(svrtable, "httpversion", &qry->DbHttpVer);
7729     namSvrSetAttrStrC(svrtable, "serverversion", &qry->ServerVer);
7730     if(namSvrSetAttrBoolC(svrtable, "caseidmatch", &caseid))
7731     {
7732         donecaseid = ajTrue;
7733         qry->CaseId = caseid;
7734     }
7735     if(namSvrSetAttrBoolC(svrtable, "hasaccession", &hasacc))
7736     {
7737         donehasacc = ajTrue;
7738         qry->HasAcc = hasacc;
7739     }
7740 
7741 #ifdef WIN32
7742     ajStrExchangeKK(&qry->Directory, '/', '\\');
7743     if(ajStrPrefixC(qry->Directory, ".\\"))
7744         ajStrCutStart(&qry->Directory, 2);
7745     ajStrExchangeKK(&qry->IndexDir, '/', '\\');
7746     if(ajStrPrefixC(qry->IndexDir, ".\\"))
7747         ajStrCutStart(&qry->IndexDir, 2);
7748 #endif
7749 
7750     if(argc)
7751     {
7752         va_start(ap, argc);
7753 
7754         for(i=0; i < argc; i++)
7755         {
7756             varAttrName = va_arg(ap, const char*);
7757             varAttrValue = va_arg(ap, AjPStr*);
7758             namSvrSetAttrStrC(svrtable, varAttrName, varAttrValue);
7759         }
7760 
7761         va_end(ap);
7762     }
7763 
7764     ajDebug("ajNamSvrQuery SvrName '%S'\n", qry->SvrName);
7765     ajDebug("    DbName      '%S'\n", qry->DbName);
7766     ajDebug("    DbType      '%S'\n", qry->DbType);
7767     ajDebug("    Method      '%S'\n", qry->Method);
7768     ajDebug("    Formatstr   '%S'\n", qry->Formatstr);
7769     ajDebug("    IndexDir    '%S'\n", qry->IndexDir);
7770     ajDebug("    Directory   '%S'\n", qry->Directory);
7771 
7772     if(ajStrGetLen(qry->DbName))
7773     {
7774         data = ajTableFetchS(namSvrDatabaseTable, qry->SvrName);
7775 
7776         if(!data)
7777         {
7778             ajWarn("server %S has no databases", qry->SvrName);
7779             ajStrDel(&saveType);
7780             return ajFalse;
7781         }
7782 
7783         sdbtable = (const AjPTable) data->data;
7784         dbdata = ajTableFetchS(sdbtable, qry->DbName);
7785 
7786         if(!dbdata)
7787             ajFatal("server %S has no database %S", qry->SvrName, qry->DbName);
7788 
7789         dbtable = (const AjPTable) dbdata->data;
7790 
7791         /* general defaults */
7792 
7793         if(namDbSetAttrStrC(dbtable, "type", &liststr))
7794         {
7795             ajDebug("db type '%S'\n", liststr);
7796 
7797             ajStrTokenAssignC(&handle, liststr, " ,;");
7798             ajStrAssignC(&qry->DbType, "");
7799 
7800             while(ajStrTokenNextParse(handle, &token))
7801             {
7802                 if(!ajStrSuffixCaseC(token,"features"))
7803                 {
7804                     if(ajStrPrefixCaseC(token, "n"))
7805                         ajStrAssignC(&token, "Nucleotide");
7806                     else if(ajStrPrefixCaseC(token, "p"))
7807                         ajStrAssignC(&token, "Protein");
7808                 }
7809 
7810                 ajDebug("test token '%S' list '%S'\n", token, liststr);
7811 
7812                 namtype = ajTableFetchS(namDbTypeTable, token);
7813 
7814                 if(!namtype)
7815                 {
7816                     ajErr("Database %S type '%S' unknown", qry->DbName, token);
7817                     continue;
7818                 }
7819 
7820                 ajDebug("qry->DataType %u namtype->DataType %u type '%s'\n",
7821                         qry->DataType, namtype->DataType, namtype->Name);
7822 
7823                 if(qry->DataType == AJDATATYPE_UNKNOWN) /* take first type */
7824                 {
7825                     if(testDataType == AJDATATYPE_UNKNOWN ||
7826                        namtype->DataType == AJDATATYPE_TEXT)
7827                     {
7828                         testDataType = namtype->DataType;
7829                         ajStrAssignS(&saveType, token);
7830                         ajDebug("Save type %d '%S'\n", testDataType, saveType);
7831                     }
7832                 }
7833 
7834                 if(namtype->DataType == qry->DataType)
7835                 {
7836                     ajStrAssignS(&qry->DbType, token);
7837                     break;
7838                 }
7839             }
7840 
7841         }
7842 
7843         if(qry->DataType == AJDATATYPE_UNKNOWN)
7844         {
7845             qry->DataType = testDataType;
7846             ajStrAssignS(&qry->DbType, saveType);
7847         }
7848 
7849         if(!ajStrGetLen(qry->DbType))
7850         {
7851             ajErr("Server %S database '%S' type(s) '%S' "
7852                   "no match to query type '%s'",
7853                   qry->SvrName, qry->DbName,
7854                   liststr, ajQueryGetDatatype(qry));
7855             ajStrDel(&saveType);
7856             return ajFalse;
7857         }
7858 
7859         if(ajStrGetLen(qry->Formatstr))
7860         {
7861             if(ajStrGetLen(qry->DbType) &&
7862                !ajStrMatchC(qry->DbType, "unknown") &&
7863                !namInformatTest(qry->Formatstr, qry->DbType))
7864             {
7865                 ajErr("Query format '%S' does not support datatype '%S'",
7866                       qry->Formatstr, qry->DbType);
7867                 ajStrDel(&saveType);
7868                 return ajFalse;
7869             }
7870         }
7871         else if (ajStrGetLen(qry->DbType))
7872         {
7873             if(namDbSetAttrStrC(dbtable, "format", &liststr))
7874             {
7875                 ok = ajFalse;
7876                 ajStrTokenAssignC(&handle, liststr, " ,;");
7877 
7878                 while(ajStrTokenNextParse(handle, &token))
7879                 {
7880                     if(namInformatTest(token, qry->DbType))
7881                     {
7882                         ok = ajTrue;
7883                         ajStrAssignS(&qry->Formatstr, token);
7884                         break;
7885                     }
7886                 }
7887 
7888                 if(!ok)
7889                 {
7890                     ajErr("Server %S database %S format(s) '%S' "
7891 			  "do not support datatype '%S'",
7892                           qry->SvrName, qry->DbName, liststr, qry->DbType);
7893                     ajStrDel(&saveType);
7894                     return ajFalse;
7895                 }
7896             }
7897         }
7898 
7899         namDbSetAttrStrC(dbtable, "method", &qry->Method);
7900         namDbSetAttrStrC(dbtable, "app", &qry->Application);
7901         namDbSetAttrStrC(dbtable, "directory", &qry->IndexDir);
7902         namDbSetAttrStrC(dbtable, "indexdirectory", &qry->IndexDir);
7903         namDbSetAttrStrC(dbtable, "indexdirectory", &qry->Directory);
7904         namDbSetAttrStrC(dbtable, "directory", &qry->Directory);
7905         namDbSetAttrStrC(dbtable, "namespace", &qry->Namespace);
7906         namDbSetAttrStrC(dbtable, "organisms", &qry->Organisms);
7907         namDbSetAttrStrC(dbtable, "exclude", &qry->Exclude);
7908         namDbSetAttrStrC(dbtable, "filename", &qry->Filename);
7909         if(!namDbSetAttrStrC(dbtable, "field", &qry->DbFields))
7910             namDbSetAttrStrC(dbtable, "fields", &qry->DbFields);
7911         namDbSetAttrStrC(dbtable, "url", &qry->DbUrl);
7912         namDbSetAttrStrC(dbtable, "proxy", &qry->DbProxy);
7913         namDbSetAttrStrC(dbtable, "httpversion", &qry->DbHttpVer);
7914         namDbSetAttrStrC(dbtable, "serverversion", &qry->ServerVer);
7915         if(namDbSetAttrBoolC(dbtable, "caseidmatch", &caseid))
7916         {
7917             donecaseid = ajTrue;
7918             qry->CaseId = caseid;
7919         }
7920         if(namDbSetAttrBoolC(dbtable, "hasaccession", &hasacc))
7921         {
7922             donehasacc = ajTrue;
7923             qry->HasAcc = hasacc;
7924         }
7925 
7926         namDbSetAttrStrC(dbtable, "identifier", &qry->DbIdentifier);
7927         namDbSetAttrStrC(dbtable, "accession", &qry->DbAccession);
7928         namDbSetAttrStrC(dbtable, "filters", &qry->DbFilter);
7929         namDbSetAttrStrC(dbtable, "return", &qry->DbReturn);
7930 
7931         if(!donecaseid)
7932             qry->CaseId = caseid;
7933         if(!donehasacc)
7934             qry->HasAcc = hasacc;
7935 
7936 #ifdef WIN32
7937 	ajStrExchangeKK(&qry->Directory, '/', '\\');
7938 	if(ajStrPrefixC(qry->Directory, ".\\"))
7939 	  ajStrCutStart(&qry->Directory, 2);
7940 	ajStrExchangeKK(&qry->IndexDir, '/', '\\');
7941 	if(ajStrPrefixC(qry->IndexDir, ".\\"))
7942 	  ajStrCutStart(&qry->IndexDir, 2);
7943 #endif
7944 
7945         if(argc)
7946         {
7947             va_start(ap, argc);
7948 
7949             for(i=0; i < argc; i++)
7950             {
7951                 varAttrName = va_arg(ap, const char*);
7952                 varAttrValue = va_arg(ap, AjPStr*);
7953                 namDbSetAttrStrC(dbtable, varAttrName, varAttrValue);
7954             }
7955 
7956             va_end(ap);
7957         }
7958     }
7959 
7960     ajDebug("ajNamSvrData '%S:%S' method:%S type:%S format:%S\n",
7961             qry->SvrName, qry->DbName, qry->Method, qry->DbType,
7962             qry->Formatstr);
7963 
7964     ajStrDel(&liststr);
7965     ajStrDel(&token);
7966 
7967     ajStrTokenDel(&handle);
7968     ajStrDel(&saveType);
7969 
7970     return ajTrue;
7971 }
7972 
7973 
7974 
7975 
7976 /* @func ajNamSvrQuery ********************************************************
7977 **
7978 ** Given a query with server name and search fields,
7979 ** fill in the access method and some common fields according
7980 ** to the query level.
7981 **
7982 ** @param [u] qry [AjPQuery] Query structure with at least
7983 **                                    svrname filled in
7984 ** @return [AjBool] ajTrue if success.
7985 **
7986 ** @release 6.4.0
7987 ** @@
7988 ******************************************************************************/
7989 
ajNamSvrQuery(AjPQuery qry)7990 AjBool ajNamSvrQuery(AjPQuery qry)
7991 {
7992     const NamPEntry data;
7993     const AjPTable svrtable;
7994 
7995     data = ajTableFetchS(namSvrMasterTable, qry->SvrName);
7996 
7997     if(!data)
7998 	ajFatal("server %S unknown", qry->SvrName);
7999 
8000     svrtable = (const AjPTable) data->data;
8001 
8002     if(!ajStrGetLen(qry->DbType))
8003 	ajNamSvrData(qry, 0);
8004 
8005     if((qry->QueryType == AJQUERY_ALL) ||
8006        ((qry->QueryType == AJQUERY_UNKNOWN) && !ajQueryIsSet(qry)))
8007     {
8008         /* must have a method for all entries */
8009 	namSvrSetAttrStrC(svrtable, "methodall", &qry->Method);
8010 	namSvrSetAttrStrC(svrtable, "formatall", &qry->Formatstr);
8011 	namSvrSetAttrStrC(svrtable, "appall", &qry->Application);
8012 	qry->QueryType = AJQUERY_ALL;
8013     }
8014     else		      /* must be able to query the database */
8015     {
8016 	namSvrSetAttrStrC(svrtable, "methodquery", &qry->Method);
8017 	namSvrSetAttrStrC(svrtable, "formatquery", &qry->Formatstr);
8018 	namSvrSetAttrStrC(svrtable, "appquery", &qry->Application);
8019 
8020 	if((qry->QueryType != AJQUERY_QUERY) &&
8021            !ajQuerySetWild(qry)) /* ID - single entry may be available */
8022 	{
8023 	    namSvrSetAttrStrC(svrtable, "methodentry", &qry->Method);
8024 	    namSvrSetAttrStrC(svrtable, "formatentry", &qry->Formatstr);
8025 	    namSvrSetAttrStrC(svrtable, "appentry", &qry->Application);
8026 	    qry->QueryType = AJQUERY_ENTRY;
8027 	}
8028 	else
8029 	    qry->QueryType = AJQUERY_QUERY;
8030     }
8031 
8032 
8033     if(!ajStrGetLen(qry->Method))
8034     {
8035 	ajErr("No access method for server '%S'",
8036               qry->SvrName);
8037 
8038 	return ajFalse;
8039     }
8040 
8041     return ajTrue;
8042 }
8043 
8044 
8045 
8046 
8047 /* @funcstatic namSvrSetAttrStrC **********************************************
8048 **
8049 ** Sets a named string attribute value from an attribute list.
8050 **
8051 ** @param [r] svrtable [const AjPTable] Attribute definitions table.
8052 ** @param [r] attrib [const char*] Attribute name.
8053 ** @param [w] qrystr [AjPStr*] Returned attribute value.
8054 ** @return [AjBool] ajTrue on success.
8055 **
8056 ** @release 6.4.0
8057 ** @@
8058 ******************************************************************************/
8059 
namSvrSetAttrStrC(const AjPTable svrtable,const char * attrib,AjPStr * qrystr)8060 static AjBool namSvrSetAttrStrC(const AjPTable svrtable, const char* attrib,
8061                                 AjPStr* qrystr)
8062 {
8063     const void* svrval = NULL;
8064     const AjPStr strval = NULL;
8065     const NamPAttr attr = NULL;
8066     const AjPList fdlist = NULL;
8067     AjIList iter = NULL;
8068     AjPStrTok handle = NULL;
8069     AjPStr word = NULL;
8070 
8071     attr = ajTableFetchC(namSvrAttrTable, attrib);
8072 
8073     if(!attr)
8074         ajFatal("unknown attribute '%s' requested",  attrib);
8075 
8076     svrval = ajTableFetchC(svrtable, attrib);
8077 
8078     if(svrval)
8079     {
8080         switch(attr->Type)
8081         {
8082             case ATTR_LIST:
8083                 ajStrAssignC(qrystr, "");
8084                 fdlist = (const AjPList) svrval;
8085                 iter = ajListIterNewread(fdlist);
8086 
8087                 while(!ajListIterDone(iter))
8088                 {
8089                     strval = ajListIterGet(iter);
8090                     ajStrTokenAssignC(&handle, strval, " ");
8091 
8092                     while(ajStrTokenNextParse(handle, &word))
8093                     {
8094                         if(ajStrMatchC(word, "!"))
8095                             break;
8096 
8097                         if(ajStrGetLen(*qrystr))
8098                             ajStrAppendK(qrystr, ' ');
8099 
8100                         ajStrAppendS(qrystr, word);
8101                     }
8102                 }
8103 
8104                 ajStrTokenDel(&handle);
8105                 ajStrDel(&word);
8106                 ajListIterDel(&iter);
8107                 break;
8108 
8109             default:
8110                 if(!ajStrGetLen((const AjPStr) svrval))
8111                     return ajFalse;
8112 
8113                 ajStrAssignS(qrystr, (const AjPStr) svrval);
8114                 break;
8115         }
8116     }
8117     else
8118     {
8119         if(!strlen(attr->Defval))
8120             return ajFalse;
8121 
8122         ajStrAssignC(qrystr, attr->Defval);
8123     }
8124 
8125     namVarResolve(qrystr);
8126 
8127     return ajTrue;
8128 }
8129 
8130 
8131 
8132 
8133 /* @funcstatic namSvrSetAttrBoolC *********************************************
8134 **
8135 ** Sets a named boolean attribute value from an attribute list.
8136 **
8137 ** @param [r] svrtable [const AjPTable] Attribute definitions table
8138 ** @param [r] attrib [const char*] Attribute name.
8139 ** @param [w] qrybool [AjBool*] Returned attribute value.
8140 ** @return [AjBool] ajTrue on success.
8141 **
8142 ** @release 6.4.0
8143 ** @@
8144 ******************************************************************************/
8145 
namSvrSetAttrBoolC(const AjPTable svrtable,const char * attrib,AjBool * qrybool)8146 static AjBool namSvrSetAttrBoolC(const AjPTable svrtable, const char* attrib,
8147                                  AjBool* qrybool)
8148 {
8149     AjBool ret = ajTrue;
8150     AjPStr tmpstr = NULL;
8151     const AjPStr svrval = NULL;
8152     const char* txtval = NULL;
8153     const NamPAttr attrval = NULL;
8154 
8155     svrval = ajTableFetchC(svrtable, attrib);
8156 
8157     if(svrval)
8158         txtval = ajStrGetPtr(svrval);
8159     else
8160     {
8161         attrval = ajTableFetchC(namSvrAttrTable, attrib);
8162 
8163         if(!attrval)
8164             ajFatal("unknown attribute '%s' requested",  attrib);
8165 
8166         txtval = attrval->Defval;
8167     }
8168 
8169     if(ajStrGetLen(svrval))
8170     {
8171 	ajStrAssignS(&tmpstr, svrval);
8172 	ret = ajTrue;
8173     }
8174     else
8175     {
8176 	ajStrAssignC(&tmpstr, txtval);
8177 	ret = ajFalse;
8178     }
8179 
8180     /* ajDebug("namSvrSetAttr('%S')\n", *qrystr); */
8181 
8182     namVarResolve(&tmpstr);
8183     ajStrToBool(tmpstr, qrybool);
8184     ajStrDel(&tmpstr);
8185 
8186     return ret;
8187 }
8188 
8189 
8190 
8191 
8192 /* @func ajNamDbTest **********************************************************
8193 **
8194 ** Looks for a database name in the known definitions.
8195 **
8196 ** @param [r] dbname [const AjPStr] Database name.
8197 ** @return [AjBool] ajTrue on success.
8198 **
8199 ** @release 1.0.0
8200 ** @@
8201 ******************************************************************************/
8202 
ajNamDbTest(const AjPStr dbname)8203 AjBool ajNamDbTest(const AjPStr dbname)
8204 {
8205     const NamPEntry data;
8206 
8207     data = ajTableFetchS(namDbMasterTable, dbname);
8208 
8209     if(!data)
8210 	return ajFalse;
8211 
8212     return ajTrue;
8213 }
8214 
8215 
8216 
8217 
8218 /* @func ajNamDbGetType *******************************************************
8219 **
8220 ** Gets the enumerated type for a database definition.
8221 **
8222 ** @param [r] dbname [const AjPStr] Database name.
8223 ** @param [w] itype [ajuint*] Database enumerated type
8224 ** @return [AjBool] ajTrue if success.
8225 **
8226 ** @release 6.4.0
8227 ** @@
8228 ******************************************************************************/
8229 
ajNamDbGetType(const AjPStr dbname,ajuint * itype)8230 AjBool ajNamDbGetType(const AjPStr dbname, ajuint *itype)
8231 {
8232     AjBool ret = ajFalse;
8233     const NamPEntry data;
8234     const AjPTable dbtable;
8235     const AjPStr dbval = NULL;
8236     AjPStrTok handle = NULL;
8237     AjPStr token = NULL;
8238     const NamPType namtype;
8239 
8240     data = ajTableFetchS(namDbMasterTable, dbname);
8241 
8242     if(!data)
8243 	ajFatal("%S is not a known database", dbname);
8244 
8245     dbtable = (const AjPTable) data->data;
8246 
8247     dbval = ajTableFetchC(dbtable, "type");
8248     ajStrTokenAssignC(&handle, dbval, " ,;");
8249 
8250     while(ajStrTokenNextParse(handle, &token))
8251     {
8252         if(!ajStrSuffixCaseC(token,"features"))
8253         {
8254             if(ajStrPrefixCaseC(token, "n"))
8255         	ajStrAssignC(&token, "Nucleotide");
8256             else if(ajStrPrefixCaseC(token, "p"))
8257         	ajStrAssignC(&token, "Protein");
8258         }
8259 
8260         namtype = ajTableFetchS(namDbTypeTable, token);
8261         ajDebug("testing type '%S' namtype: '%s' \n",
8262 		token, namtype->Name);
8263 
8264         *itype =  namtype->DataType;
8265         ret = ajTrue;
8266         break;
8267     }
8268 
8269     ajStrTokenDel(&handle);
8270     ajStrDel(&token);
8271 
8272     return ret;
8273 }
8274 
8275 
8276 
8277 
8278 /* @func ajNamDbGetUrl ********************************************************
8279 **
8280 ** Gets the URL definition for a database definition.
8281 **
8282 ** @param [r] dbname [const AjPStr] Database name.
8283 ** @param [w] url [AjPStr*] URL returned.
8284 ** @return [AjBool] ajTrue if success.
8285 **
8286 ** @release 1.0.0
8287 ** @@
8288 ******************************************************************************/
8289 
ajNamDbGetUrl(const AjPStr dbname,AjPStr * url)8290 AjBool ajNamDbGetUrl(const AjPStr dbname, AjPStr* url)
8291 {
8292 
8293     const NamPEntry data;
8294     const AjPTable dbtable;
8295     const AjPStr dbval = NULL;
8296 
8297     data = ajTableFetchS(namDbMasterTable, dbname);
8298 
8299     if(!data)
8300 	ajFatal("%S is not a known database", dbname);
8301 
8302     dbtable = (const AjPTable) data->data;
8303 
8304     dbval = ajTableFetchC(dbtable, "url");
8305 
8306     if(ajStrGetLen(dbval))
8307     {
8308 	ajStrAssignS(url, dbval);
8309 
8310 	return ajTrue;
8311     }
8312 
8313     if(ajStrGetLen(*url))
8314         return ajTrue;
8315 
8316     return ajFalse;
8317 }
8318 
8319 
8320 
8321 
8322 /* @func ajNamDbGetDbalias ****************************************************
8323 **
8324 ** Gets an alias name for a database.
8325 **
8326 ** @param [r] dbname [const AjPStr] Database name.
8327 ** @param [w] dbalias [AjPStr*] Alias returned.
8328 ** @return [AjBool] ajTrue if success.
8329 **
8330 ** @release 1.0.0
8331 ** @@
8332 ******************************************************************************/
8333 
ajNamDbGetDbalias(const AjPStr dbname,AjPStr * dbalias)8334 AjBool ajNamDbGetDbalias(const AjPStr dbname, AjPStr* dbalias)
8335 {
8336 
8337     const NamPEntry data;
8338     const AjPTable dbtable;
8339     const AjPStr dbval = NULL;
8340 
8341     data = ajTableFetchS(namDbMasterTable, dbname);
8342 
8343     if(!data)
8344 	ajFatal("%S is not a known database", dbname);
8345 
8346     dbtable = (const AjPTable) data->data;
8347 
8348     dbval = ajTableFetchC(dbtable, "dbalias");
8349 
8350     if(ajStrGetLen(dbval))
8351 	ajStrAssignS(dbalias, dbval);
8352     else
8353     {
8354         ajStrAssignS(dbalias, dbname);
8355         ajStrFmtLower(dbalias);
8356     }
8357 
8358     return ajTrue;
8359 }
8360 
8361 
8362 
8363 
8364 /* @func ajNamDbGetDbaliasTest ***********************************************
8365 **
8366 ** Gets an alias name for a database,
8367 ** no fatal error if the database name is not found
8368 **
8369 ** @param [r] dbname [const AjPStr] Database name.
8370 ** @param [w] dbalias [AjPStr*] Alias returned.
8371 ** @return [AjBool] ajTrue if success.
8372 **
8373 ** @release 1.0.0
8374 ** @@
8375 ******************************************************************************/
8376 
ajNamDbGetDbaliasTest(const AjPStr dbname,AjPStr * dbalias)8377 AjBool ajNamDbGetDbaliasTest(const AjPStr dbname, AjPStr* dbalias)
8378 {
8379 
8380     const NamPEntry data;
8381     const AjPTable dbtable;
8382     const AjPStr dbval = NULL;
8383 
8384     data = ajTableFetchS(namDbMasterTable, dbname);
8385 
8386     if(!data)
8387         return ajFalse;
8388 
8389     dbtable = (const AjPTable) data->data;
8390 
8391     dbval = ajTableFetchC(dbtable, "dbalias");
8392 
8393     if(ajStrGetLen(dbval))
8394 	ajStrAssignS(dbalias, dbval);
8395     else
8396     {
8397         ajStrAssignS(dbalias, dbname);
8398         ajStrFmtLower(dbalias);
8399     }
8400 
8401     return ajTrue;
8402 }
8403 
8404 
8405 
8406 
8407 /* @func ajNamDbGetIndexdir ***************************************************
8408 **
8409 ** Gets the index directory for a database.
8410 **
8411 ** @param [r] dbname [const AjPStr] Database name.
8412 ** @param [w] indexdir [AjPStr*] Directory path returned.
8413 ** @return [AjBool] ajTrue if success.
8414 **
8415 ** @release 6.4.0
8416 ** @@
8417 ******************************************************************************/
8418 
ajNamDbGetIndexdir(const AjPStr dbname,AjPStr * indexdir)8419 AjBool ajNamDbGetIndexdir(const AjPStr dbname, AjPStr* indexdir)
8420 {
8421 
8422    const  NamPEntry data;
8423     const AjPTable dbtable;
8424     const AjPStr dbval = NULL;
8425 
8426     data = ajTableFetchS(namDbMasterTable, dbname);
8427 
8428     if(!data)
8429 	ajFatal("%S is not a known database", dbname);
8430 
8431     dbtable = (const AjPTable) data->data;
8432 
8433     dbval = ajTableFetchC(dbtable, "indexdirectory");
8434 
8435     if(ajStrGetLen(dbval))
8436     {
8437 	ajStrAssignS(indexdir, dbval);
8438         return ajTrue;
8439     }
8440 
8441     dbval = ajTableFetchC(dbtable, "directory");
8442 
8443     if(ajStrGetLen(dbval))
8444     {
8445 	ajStrAssignS(indexdir, dbval);
8446         return ajTrue;
8447     }
8448 
8449     return ajFalse;
8450 }
8451 
8452 
8453 
8454 
8455 /* @func ajNamQuerySetDbalias *************************************************
8456 **
8457 ** Sets an alias name for a database query.
8458 **
8459 ** @param [u] qry [AjPQuery] Database query.
8460 ** @return [AjBool] ajTrue if success.
8461 **
8462 ** @release 6.4.0
8463 ** @@
8464 ******************************************************************************/
8465 
ajNamQuerySetDbalias(AjPQuery qry)8466 AjBool ajNamQuerySetDbalias(AjPQuery qry)
8467 {
8468     const NamPEntry data;
8469     const NamPEntry sdata;
8470     const AjPTable dbtable;
8471     const AjPTable sdbtable;
8472     const AjPStr dbval = NULL;
8473 
8474     if(ajStrGetLen(qry->SvrName))
8475     {
8476 	if(!ajStrGetLen(qry->DbType))
8477             ajNamSvrData(qry, 0);
8478 
8479         ajNamSvrQuery(qry);
8480         sdata = ajTableFetchS(namSvrDatabaseTable, qry->SvrName);
8481         sdbtable = (const AjPTable) sdata->data;
8482         data = ajTableFetchS(sdbtable, qry->DbName);
8483 
8484         if(!data)
8485             ajFatal("%S is not a known database for server %S",
8486                     qry->DbName, qry->SvrName);
8487     }
8488     else
8489     {
8490         data = ajTableFetchS(namDbMasterTable, qry->DbName);
8491 
8492         if(!data)
8493             ajFatal("%S is not a known database", qry->DbName);
8494     }
8495 
8496     dbtable = (const AjPTable) data->data;
8497 
8498     dbval = ajTableFetchC(dbtable, "dbalias");
8499 
8500     if(ajStrGetLen(dbval))
8501 	ajStrAssignS(&qry->DbAlias, dbval);
8502     else
8503     {
8504         ajStrAssignS(&qry->DbAlias, qry->DbName);
8505         ajStrFmtLower(&qry->DbAlias);
8506     }
8507 
8508     return ajTrue;
8509 }
8510 
8511 
8512 
8513 
8514 /* @func ajNamDbData **********************************************************
8515 **
8516 ** Given a query with database name and search fields,
8517 ** fill in the common fields. The query fields are set later.
8518 **
8519 ** This part of the database definition is required (specifically
8520 ** the "fields" definition) for setting the query details.
8521 **
8522 ** See also ajNamDbQuery, which calls this function if the common
8523 ** query data is not yet set.
8524 **
8525 ** @param [u] qry [AjPQuery] Query structure with at least
8526 **                                    dbname filled in
8527 ** @param [r] argc [ajuint] Number of additional attribute name/value pairs
8528 ** @param [v] [...] Variable length argument list
8529 ** @return [AjBool] ajTrue if success.
8530 **
8531 ** @release 2.4.0
8532 ** @@
8533 ******************************************************************************/
8534 
ajNamDbData(AjPQuery qry,ajuint argc,...)8535 AjBool ajNamDbData(AjPQuery qry, ajuint argc, ...)
8536 {
8537     const NamPEntry data;
8538     const AjPTable dbtable;
8539     AjPStrTok handle = NULL;
8540     AjPStr liststr = NULL;
8541     AjPStr token = NULL;
8542     ajuint i;
8543     const char* varAttrName;
8544     AjPStr* varAttrValue;
8545     va_list ap;
8546     const NamPType namtype;
8547     AjBool ok = ajTrue;
8548 
8549     if(qry->SetDatabase)
8550         return ajTrue;
8551 
8552     qry->SetDatabase = ajTrue;
8553 
8554     data = ajTableFetchS(namDbMasterTable, qry->DbName);
8555 
8556     if(!data)
8557     {
8558 	ajDebug("ajNamDbData: database %S unknown\n", qry->DbName);
8559         return ajFalse;
8560     }
8561 
8562     dbtable = (const AjPTable) data->data;
8563 
8564     /* general defaults */
8565 
8566     if(namDbSetAttrStrC(dbtable, "type", &liststr))
8567     {
8568         ajStrTokenAssignC(&handle, liststr, " ,;");
8569         ajStrAssignC(&qry->DbType, "");
8570 
8571         while(ajStrTokenNextParse(handle, &token))
8572         {
8573             if(ajStrMatchCaseC(token, "n"))
8574                 ajStrAssignC(&token, "Nucleotide");
8575             else if(ajStrMatchCaseC(token, "p"))
8576                 ajStrAssignC(&token, "Protein");
8577             else if(ajStrMatchCaseC(token, "prot"))
8578                 ajStrAssignC(&token, "Protein");
8579 
8580             namtype = ajTableFetchS(namDbTypeTable, token);
8581 
8582             if(!namtype)
8583             {
8584                 ajErr("Database %S type '%S' unknown", qry->DbName, token);
8585                 continue;
8586             }
8587 
8588             if(qry->DataType == AJDATATYPE_UNKNOWN) /* take first available */
8589                 qry->DataType = namtype->DataType;
8590 
8591             if(namtype->DataType == qry->DataType)
8592             {
8593                 ajStrAssignS(&qry->DbType, token);
8594                 break;
8595             }
8596         }
8597 
8598         if(!ajStrGetLen(qry->DbType))
8599         {
8600             ajErr("Database %S type(s) '%S' do not match query type '%s'",
8601                   qry->DbName, liststr, ajQueryGetDatatype(qry));
8602             return ajFalse;
8603         }
8604     }
8605 
8606     if(ajStrGetLen(qry->Formatstr))
8607     {
8608         if(!namInformatTest(qry->Formatstr, qry->DbType))
8609         {
8610             ajErr("Query format '%S' does not support datatype '%S'",
8611                   qry->Formatstr, qry->DbType);
8612             return ajFalse;
8613         }
8614     }
8615     else
8616     {
8617         if(namDbSetAttrStrC(dbtable, "format", &liststr))
8618         {
8619             ok = ajFalse;
8620             ajStrTokenAssignC(&handle, liststr, " ,;");
8621 
8622             while(ajStrTokenNextParse(handle, &token))
8623             {
8624                 if(namInformatTest(token, qry->DbType))
8625                 {
8626                     ok = ajTrue;
8627                     ajStrAssignS(&qry->Formatstr, token);
8628                 }
8629             }
8630 
8631             if(!ok)
8632             {
8633                 ajErr("Database %S format(s) '%S' do not support "
8634                       "datatype '%S'",
8635                       qry->DbName, liststr, qry->DbType);
8636                 return ajFalse;
8637             }
8638         }
8639     }
8640 
8641     ajStrDel(&liststr);
8642     ajStrDel(&token);
8643     ajStrTokenDel(&handle);
8644 
8645     namDbSetAttrStrC(dbtable, "method", &qry->Method);
8646     namDbSetAttrStrC(dbtable, "app", &qry->Application);
8647     namDbSetAttrStrC(dbtable, "directory", &qry->IndexDir);
8648     namDbSetAttrStrC(dbtable, "indexdirectory", &qry->IndexDir);
8649     namDbSetAttrStrC(dbtable, "indexdirectory", &qry->Directory);
8650     namDbSetAttrStrC(dbtable, "directory", &qry->Directory);
8651     namDbSetAttrStrC(dbtable, "namespace", &qry->Namespace);
8652     namDbSetAttrStrC(dbtable, "organisms", &qry->Organisms);
8653     namDbSetAttrStrC(dbtable, "exclude", &qry->Exclude);
8654     namDbSetAttrStrC(dbtable, "filename", &qry->Filename);
8655 
8656     if(!namDbSetAttrStrC(dbtable, "field", &qry->DbFields))
8657         namDbSetAttrStrC(dbtable, "fields", &qry->DbFields);
8658 
8659     namDbSetAttrStrC(dbtable, "url", &qry->DbUrl);
8660     namDbSetAttrStrC(dbtable, "proxy", &qry->DbProxy);
8661     namDbSetAttrStrC(dbtable, "httpversion", &qry->DbHttpVer);
8662     namDbSetAttrStrC(dbtable, "serverversion", &qry->ServerVer);
8663     namDbSetAttrBoolC(dbtable, "caseidmatch", &qry->CaseId);
8664     namDbSetAttrBoolC(dbtable, "hasaccession", &qry->HasAcc);
8665 
8666     namDbSetAttrStrC(dbtable, "identifier", &qry->DbIdentifier);
8667     namDbSetAttrStrC(dbtable, "accession", &qry->DbAccession);
8668     namDbSetAttrStrC(dbtable, "filters", &qry->DbFilter);
8669     namDbSetAttrStrC(dbtable, "return", &qry->DbReturn);
8670 
8671 #ifdef WIN32
8672     ajStrExchangeKK(&qry->Directory, '/', '\\');
8673     if(ajStrPrefixC(qry->Directory, ".\\"))
8674         ajStrCutStart(&qry->Directory, 2);
8675     ajStrExchangeKK(&qry->IndexDir, '/', '\\');
8676     if(ajStrPrefixC(qry->IndexDir, ".\\"))
8677         ajStrCutStart(&qry->IndexDir, 2);
8678 #endif
8679 
8680 
8681     if(argc)
8682     {
8683         va_start(ap, argc);
8684 
8685         for(i=0; i < argc; i++)
8686         {
8687             varAttrName = va_arg(ap, const char*);
8688             varAttrValue = va_arg(ap, AjPStr*);
8689             namDbSetAttrStrC(dbtable, varAttrName, varAttrValue);
8690         }
8691 
8692         va_end(ap);
8693     }
8694 
8695     return ajTrue;
8696 }
8697 
8698 
8699 
8700 
8701 /* @func ajNamDbQuery *********************************************************
8702 **
8703 ** Given a query with database name and search fields,
8704 ** fill in the access method and some common fields according
8705 ** to the query level.
8706 **
8707 ** @param [u] qry [AjPQuery] Query structure with at least
8708 **                                    dbname filled in
8709 ** @return [AjBool] ajTrue if success.
8710 **
8711 ** @release 1.0.0
8712 ** @@
8713 ******************************************************************************/
8714 
ajNamDbQuery(AjPQuery qry)8715 AjBool ajNamDbQuery(AjPQuery qry)
8716 {
8717 
8718     const NamPEntry data;
8719     const NamPEntry sdata;
8720 
8721     const AjPTable sdbtable;
8722 
8723     const AjPTable dbtable;
8724     const char* qlinks;
8725 
8726     ajDebug("ajNamDbQuery SetQuery:%B QueryType:%d\n",
8727             qry->SetQuery, qry->QueryType);
8728 
8729     if(qry->SetQuery)
8730         return ajTrue;
8731 
8732     qry->SetQuery = ajTrue;
8733 
8734     if(qry->InDrcat)
8735         return ajTrue;
8736 
8737     if(ajStrGetLen(qry->SvrName))
8738     {
8739         if(ajStrGetLen(qry->DbType))
8740             ajNamSvrData(qry, 0);
8741 
8742         ajNamSvrQuery(qry);
8743         sdata = ajTableFetchS(namSvrDatabaseTable, qry->SvrName);
8744         sdbtable = (const AjPTable) sdata->data;
8745         data = ajTableFetchS(sdbtable, qry->DbName);
8746     }
8747     else
8748         data = ajTableFetchS(namDbMasterTable, qry->DbName);
8749 
8750     if(!data)
8751         ajFatal("database %S unknown", qry->DbName);
8752 
8753     dbtable = (const AjPTable) data->data;
8754 
8755     if(!ajStrGetLen(qry->DbType))
8756     {
8757 	if(!ajNamDbData(qry, 0))
8758             return ajFalse;
8759     }
8760 
8761     if((qry->QueryType == AJQUERY_ALL) ||
8762        ((qry->QueryType == AJQUERY_UNKNOWN) && !ajQueryIsSet(qry)))
8763     {
8764         /* must have a method for all entries */
8765 	namDbSetAttrStrC(dbtable, "methodall", &qry->Method);
8766 	namDbSetAttrStrC(dbtable, "formatall", &qry->Formatstr);
8767 	namDbSetAttrStrC(dbtable, "appall", &qry->Application);
8768 	qry->QueryType = AJQUERY_ALL;
8769     }
8770     else		      /* must be able to query the database */
8771     {
8772 	namDbSetAttrStrC(dbtable, "methodquery", &qry->Method);
8773 	namDbSetAttrStrC(dbtable, "formatquery", &qry->Formatstr);
8774 	namDbSetAttrStrC(dbtable, "appquery", &qry->Application);
8775 
8776 	if((qry->QueryType != AJQUERY_QUERY) &&
8777            !ajQuerySetWild(qry)) /* ID - single entry may be available */
8778 	{
8779 	    namDbSetAttrStrC(dbtable, "methodentry", &qry->Method);
8780 	    namDbSetAttrStrC(dbtable, "formatentry", &qry->Formatstr);
8781 	    namDbSetAttrStrC(dbtable, "appentry", &qry->Application);
8782 	    qry->QueryType = AJQUERY_ENTRY;
8783 	}
8784 	else
8785 	    qry->QueryType = AJQUERY_QUERY;
8786     }
8787 
8788     namDbSetAttrStrC(dbtable, "return", &qry->DbReturn);
8789 
8790 
8791     if(!ajStrGetLen(qry->Formatstr))
8792     {
8793 	ajErr("No format defined for database '%S'", qry->DbName);
8794 
8795 	return ajFalse;
8796     }
8797 
8798     if(!ajStrGetLen(qry->Method))
8799     {
8800 	ajErr("No access method for database '%S'", qry->DbName);
8801 
8802 	return ajFalse;
8803     }
8804 
8805     qlinks = namMethod2Qlinks(qry->Method, qry->DataType);
8806 
8807     if(!qlinks)
8808     {
8809         ajErr("Unknown access method '%S' for database '%S'",
8810               qry->Method, qry->DbName);
8811         return ajFalse;
8812     }
8813 
8814     ajStrAssignC(&qry->Qlinks, qlinks);
8815 
8816     return ajTrue;
8817 }
8818 
8819 
8820 
8821 
8822 /* @func ajNamFileQuery *******************************************************
8823 **
8824 ** Given a query with no database name and search fields, check
8825 ** datatype specific fields according to the query level.
8826 **
8827 ** @param [u] qry [AjPQuery] Query structure with no database name
8828 ** @return [AjBool] ajTrue if success.
8829 **
8830 ** @release 6.4.0
8831 ** @@
8832 ******************************************************************************/
8833 
ajNamFileQuery(AjPQuery qry)8834 AjBool ajNamFileQuery(AjPQuery qry)
8835 {
8836     const char* fields = NULL;
8837     const char* qlinks = NULL;
8838 
8839     if(qry->SetQuery)
8840         return ajTrue;
8841 
8842     qry->SetQuery = ajTrue;
8843 
8844     if(ajStrGetLen(qry->SvrName))
8845 	ajFatal("ajNamFileQuery called with server '%S'", qry->SvrName);
8846     else if(ajStrGetLen(qry->DbName))
8847 	ajFatal("ajNamFileQuery called with database '%S'", qry->DbName);
8848 
8849     switch(qry->QueryType)
8850     {
8851         case AJQUERY_ALL:
8852             break;
8853 
8854         case AJQUERY_QUERY:
8855             break;
8856 
8857         case AJQUERY_ENTRY:
8858             break;
8859 
8860         case AJQUERY_UNKNOWN:
8861         default:
8862             break;
8863     }
8864 
8865     /*
8866     if(!ajStrGetLen(qry->Formatstr))
8867     {
8868 	ajErr("No format defined for file access query");
8869 
8870 	return ajFalse;
8871     }
8872     */
8873 
8874     qlinks = namDatatype2Qlinks(qry->DataType);
8875 
8876     if(qlinks)
8877         ajStrAssignC(&qry->Qlinks, qlinks);
8878     else
8879     {
8880         ajWarn("no query links defined for type; '%s'",
8881                namDbTypes[qry->DataType].Name);
8882         ajStrAssignC(&qry->Qlinks, "|");
8883     }
8884 
8885     fields = namDatatype2Fields(qry->DataType);
8886 
8887     if(fields)
8888         ajStrAssignC(&qry->DbFields, fields);
8889     else
8890     {
8891         ajWarn("no fields defined for type; '%s'",
8892                namDbTypes[qry->DataType].Name);
8893         ajStrAssignC(&qry->DbFields, "");
8894     }
8895 
8896     return ajTrue;
8897 }
8898 
8899 
8900 
8901 
8902 /* @funcstatic namDbSetAttrStrC ***********************************************
8903 **
8904 ** Sets a named string attribute value from an attribute list.
8905 **
8906 ** @param [r] dbtable [const AjPTable] Attribute definitions table.
8907 ** @param [r] attrib [const char*] Attribute name.
8908 ** @param [w] qrystr [AjPStr*] Returned attribute value.
8909 ** @return [AjBool] ajTrue on success.
8910 **
8911 ** @release 6.4.0
8912 ** @@
8913 ******************************************************************************/
8914 
namDbSetAttrStrC(const AjPTable dbtable,const char * attrib,AjPStr * qrystr)8915 static AjBool namDbSetAttrStrC(const AjPTable dbtable, const char* attrib,
8916                                AjPStr* qrystr)
8917 {
8918     const void* dbval = NULL;
8919     const AjPStr strval = NULL;
8920     const NamPAttr attr = NULL;
8921     const AjPList fdlist = NULL;
8922     AjIList iter = NULL;
8923     AjPStrTok handle = NULL;
8924     AjPStr word = NULL;
8925     char delimchar = ' ';
8926 
8927     attr = ajTableFetchC(namDbAttrTable, attrib);
8928 
8929     if(!attr)
8930         ajFatal("unknown attribute '%s' requested",  attrib);
8931 
8932     dbval = ajTableFetchC(dbtable, attrib);
8933 
8934     if(dbval)
8935     {
8936         switch(attr->Type)
8937         {
8938             case ATTR_LIST:
8939                 ajStrAssignC(qrystr, "");
8940                 fdlist = (const AjPList) dbval;
8941                 iter = ajListIterNewread(fdlist);
8942 
8943                 while(!ajListIterDone(iter))
8944                 {
8945                     strval = ajListIterGet(iter);
8946                     ajStrTokenAssignC(&handle, strval, " ");
8947 
8948                     while(ajStrTokenNextParse(handle, &word))
8949                     {
8950                         if(ajStrMatchC(word, "!"))
8951                             break;
8952 
8953                         if(ajStrGetLen(*qrystr))
8954                         {
8955                             ajStrAppendK(qrystr, delimchar);
8956                             delimchar = ' ';
8957                         }
8958 
8959                         ajStrAppendS(qrystr, word);
8960                     }
8961 
8962                     delimchar = ';';
8963                 }
8964 
8965                 ajStrTokenDel(&handle);
8966                 ajStrDel(&word);
8967                 ajListIterDel(&iter);
8968                 break;
8969 
8970             default:
8971                 if(!ajStrGetLen((const AjPStr) dbval))
8972                     return ajFalse;
8973                 ajStrAssignS(qrystr, (const AjPStr) dbval);
8974 
8975                 break;
8976         }
8977     }
8978     else
8979     {
8980         if(!strlen(attr->Defval))
8981             return ajFalse;
8982 
8983         ajStrAssignC(qrystr, attr->Defval);
8984     }
8985 
8986     namVarResolve(qrystr);
8987 
8988     return ajTrue;
8989 }
8990 
8991 
8992 
8993 
8994 /* @funcstatic namDbSetAttrBoolC **********************************************
8995 **
8996 ** Sets a named boolean attribute value from an attribute list.
8997 **
8998 ** @param [r] dbtable [const AjPTable] Attribute definitions table
8999 ** @param [r] attrib [const char*] Attribute name.
9000 ** @param [w] qrybool [AjBool*] Returned attribute value.
9001 ** @return [AjBool] ajTrue on success.
9002 **
9003 ** @release 6.4.0
9004 ** @@
9005 ******************************************************************************/
9006 
namDbSetAttrBoolC(const AjPTable dbtable,const char * attrib,AjBool * qrybool)9007 static AjBool namDbSetAttrBoolC(const AjPTable dbtable, const char* attrib,
9008                                 AjBool* qrybool)
9009 {
9010     AjBool ret = ajTrue;
9011     AjPStr tmpstr = NULL;
9012     const AjPStr dbval = NULL;
9013     const char* txtval = NULL;
9014     const NamPAttr attr = NULL;
9015 
9016     dbval = ajTableFetchC(dbtable, attrib);
9017 
9018     if(dbval)
9019         txtval = ajStrGetPtr(dbval);
9020     else
9021     {
9022         attr = ajTableFetchC(namDbAttrTable, attrib);
9023 
9024         if(!attr)
9025             ajFatal("unknown attribute '%s' requested",  attrib);
9026 
9027         txtval = attr->Defval;
9028     }
9029 
9030     if(!ajStrGetLen(dbval))
9031     {
9032 	ajStrAssignC(&tmpstr, txtval);
9033 	ret = ajFalse;
9034     }
9035     else
9036     {
9037 	ajStrAssignS(&tmpstr, dbval);
9038 	ret = ajTrue;
9039     }
9040 
9041     /* ajDebug("namDbSetAttr('%S')\n", *qrystr); */
9042 
9043     namVarResolve(&tmpstr);
9044     ajStrToBool(tmpstr, qrybool);
9045     ajStrDel(&tmpstr);
9046 
9047     return ret;
9048 }
9049 
9050 
9051 
9052 
9053 /* @funcstatic namVarResolve **************************************************
9054 **
9055 ** Resolves any variable or function references in a string.
9056 **
9057 ** @param [u] var [AjPStr*] String value
9058 ** @return [AjBool] Always ajTrue so far
9059 **
9060 ** @release 1.0.0
9061 ** @@
9062 ******************************************************************************/
9063 
namVarResolve(AjPStr * var)9064 static AjBool namVarResolve(AjPStr* var)
9065 {
9066 
9067     AjPStr varname = NULL;
9068     AjPStr newvar  = NULL;
9069     AjPStr restvar = NULL;
9070 
9071     if(!namVarExp)
9072 	namVarExp = ajRegCompC("^\\$([a-zA-Z0-9_.]+)");
9073 
9074     while(ajRegExec(namVarExp, *var))
9075     {
9076 	ajRegSubI(namVarExp, 1, &varname); /* variable name */
9077 
9078 	ajNamGetValueS(varname, &newvar);
9079 
9080 	ajDebug("namVarResolve '%S' = '%S'\n", varname, newvar);
9081 
9082 	if(ajRegPost(namVarExp, &restvar)) /* any more? */
9083 	    ajStrAppendS(&newvar, restvar);
9084 
9085 	ajStrAssignS(var, newvar);
9086     }
9087 
9088     ajStrDel(&varname);
9089     ajStrDel(&newvar);
9090     ajStrDel(&restvar);
9091 
9092     return ajFalse;
9093 }
9094 
9095 
9096 
9097 
9098 /* @funcstatic namUser ********************************************************
9099 **
9100 ** Formatted write as an error message.
9101 **
9102 ** @param [r] fmt [const char*] Format string
9103 ** @param [v] [...] Format arguments.
9104 ** @return [void]
9105 **
9106 ** @release 1.0.0
9107 ** @@
9108 ******************************************************************************/
9109 
namUser(const char * fmt,...)9110 static void namUser(const char* fmt, ...)
9111 {
9112     va_list args;
9113 
9114     if(!namDoDebug)
9115 	return;
9116 
9117     va_start(args, fmt);
9118     ajFmtVError(fmt, args);
9119     va_end(args);
9120 
9121     return;
9122 }
9123 
9124 
9125 
9126 
9127 /* @funcstatic namError *******************************************************
9128 **
9129 ** Formatted write as an error message.
9130 **
9131 ** @param [r] fmt [const char*] Format string
9132 ** @param [v] [...] Format arguments.
9133 ** @return [void]
9134 **
9135 ** @release 2.7.0
9136 ** @@
9137 ******************************************************************************/
9138 
namError(const char * fmt,...)9139 static void namError(const char* fmt, ...)
9140 {
9141     va_list args;
9142     AjPStr errstr = NULL;
9143 
9144     namErrorCount++;
9145 
9146     va_start(args, fmt);
9147     ajFmtVPrintS(&errstr, fmt, args);
9148     va_end(args);
9149 
9150     ajErr("File %S line %d: %S", namFileName, namLine, errstr);
9151     ajStrDel(&errstr);
9152 
9153     return;
9154 }
9155 
9156 
9157 
9158 
9159 /* @func ajNamValueInstalldir *************************************************
9160 **
9161 ** Returns the install directory root for all file searches
9162 ** (package level)
9163 **
9164 ** @return [const AjPStr] Install directory root
9165 **
9166 ** @release 6.0.0
9167 ** @@
9168 ******************************************************************************/
9169 
ajNamValueInstalldir(void)9170 const AjPStr ajNamValueInstalldir(void)
9171 {
9172     return namFixedInstallStr;
9173 }
9174 
9175 
9176 
9177 
9178 /* @func ajNamValuePackage ****************************************************
9179 **
9180 ** Returns the package name for the library
9181 **
9182 ** @return [const AjPStr] Package name
9183 **
9184 ** @release 6.0.0
9185 ** @@
9186 ******************************************************************************/
9187 
ajNamValuePackage(void)9188 const AjPStr ajNamValuePackage(void)
9189 {
9190     return namFixedPackageStr;
9191 }
9192 
9193 
9194 
9195 
9196 /* @func ajNamValueSystem *****************************************************
9197 **
9198 ** Returns the system information for the library
9199 **
9200 ** @return [const AjPStr] Version number
9201 **
9202 ** @release 6.2.0
9203 ** @@
9204 ******************************************************************************/
9205 
ajNamValueSystem(void)9206 const AjPStr ajNamValueSystem(void)
9207 {
9208     return namFixedSystemStr;
9209 }
9210 
9211 
9212 
9213 
9214 /* @func ajNamValueVersion ****************************************************
9215 **
9216 ** Returns the version number for the library
9217 **
9218 ** @return [const AjPStr] Version number
9219 **
9220 ** @release 6.0.0
9221 ** @@
9222 ******************************************************************************/
9223 
ajNamValueVersion(void)9224 const AjPStr ajNamValueVersion(void)
9225 {
9226     return namFixedVersionStr;
9227 }
9228 
9229 
9230 
9231 
9232 /* @func ajNamValueRootdir ****************************************************
9233 **
9234 ** Returns the directory for all file searches
9235 ** (package level)
9236 **
9237 ** @return [const AjPStr] Package level root directory
9238 **
9239 ** @release 6.0.0
9240 ** @@
9241 ******************************************************************************/
9242 
ajNamValueRootdir(void)9243 const AjPStr ajNamValueRootdir(void)
9244 {
9245     return namFixedRootStr;
9246 }
9247 
9248 
9249 
9250 
9251 /* @func ajNamValueBasedir ****************************************************
9252 **
9253 ** Returns the base directory for all for all file searches
9254 ** (above package level).
9255 **
9256 ** @return [const AjPStr] Base directory
9257 **
9258 ** @release 6.0.0
9259 ******************************************************************************/
9260 
ajNamValueBasedir(void)9261 const AjPStr ajNamValueBasedir(void)
9262 {
9263     return namFixedBaseStr;
9264 }
9265 
9266 
9267 
9268 
9269 /* @func ajNamResolve *********************************************************
9270 **
9271 ** Resolves a variable name if the input string starts with a dollar sign.
9272 **
9273 ** @param [w] name [AjPStr*] String
9274 ** @return [AjBool] ajTrue on success.
9275 **
9276 ** @release 1.0.0
9277 ** @@
9278 ******************************************************************************/
9279 
ajNamResolve(AjPStr * name)9280 AjBool ajNamResolve(AjPStr* name)
9281 {
9282 
9283     AjPStr varname  = NULL;
9284     AjPStr varvalue = NULL;
9285     AjPStr restname = NULL;
9286     AjBool ret;
9287 
9288     if(!namNameExp)
9289 	namNameExp = ajRegCompC("^\\$([A-Za-z0-9_]+)");
9290 
9291     namUser("ajNamResolve of '%S'\n", *name);
9292     ret = ajRegExec(namNameExp, *name);
9293 
9294     if(ret)
9295     {
9296 	ajRegSubI(namNameExp, 1, &varname);
9297 	namUser("variable '%S' found\n", varname);
9298 	ajRegPost(namNameExp, &restname);
9299 	ret = ajNamGetValueS(varname, &varvalue);
9300 
9301 	if(ret)
9302 	{
9303 	    ajStrAssignS(name, varvalue);
9304 	    ajStrAppendS(name, restname);
9305 	    namUser("converted to '%S'\n", *name);
9306 	}
9307 	else
9308 	{
9309 	    namUser("Variable unknown '$%S'\n", varname);
9310 	    ajWarn("Variable unknown in '%S'", *name);
9311 	    ajStrAssignS(name, restname);
9312 	}
9313 
9314 	ajStrDel(&varname);
9315 	ajStrDel(&varvalue);
9316 	ajStrDel(&restname);
9317     }
9318 
9319     return ret;
9320 }
9321 
9322 
9323 
9324 
9325 /* @funcstatic namValid *******************************************************
9326 **
9327 ** Validation of a master table entry
9328 **
9329 ** @param [r] entry [const NamPEntry] Internal table entry
9330 ** @param [r] entrytype [ajint] Internal table entry type
9331 ** @return [AjBool] ajTrue on success
9332 **
9333 ** @release 2.7.0
9334 ** @@
9335 ******************************************************************************/
9336 
namValid(const NamPEntry entry,ajint entrytype)9337 static AjBool namValid(const NamPEntry entry, ajint entrytype)
9338 {
9339     if(entrytype == TYPE_ENV)
9340 	return namValidVariable(entry);
9341     else if(entrytype == TYPE_SVR)
9342 	return namValidServer(entry);
9343     else if(entrytype == TYPE_DB)
9344 	return namValidDatabase(entry);
9345     else if(entrytype == TYPE_RESOURCE)
9346 	return namValidResource(entry);
9347     else if(entrytype == TYPE_ALIAS)
9348 	return namValidAlias(entry);
9349 
9350     /* fatal: cannot test - should not happen */
9351     namError("Unknown definition type number %d",
9352 	      entrytype);
9353 
9354     return ajFalse;
9355 }
9356 
9357 
9358 
9359 
9360 /* @funcstatic namValidAlias **************************************************
9361 **
9362 ** Validation of a master table alias entry
9363 **
9364 ** @param [r] entry [const NamPEntry] Internal table entry
9365 ** @return [AjBool] ajTrue on success
9366 **
9367 ** @release 6.4.0
9368 ** @@
9369 ******************************************************************************/
9370 
namValidAlias(const NamPEntry entry)9371 static AjBool namValidAlias(const NamPEntry entry)
9372 {
9373     AjPTable attrtable;
9374 
9375     attrtable = (AjPTable) entry->data;
9376 
9377     if(attrtable)
9378     {			 /* strange - should be nothing for aliases */
9379 	namError("Alias '%S' has a list of attributes",
9380 		  entry->name);
9381 
9382 	return ajFalse;
9383     }
9384 
9385     return ajTrue;
9386 }
9387 
9388 
9389 
9390 
9391 /* @funcstatic namValidServer *************************************************
9392 **
9393 ** Validation of a master table server entry
9394 **
9395 ** @param [r] entry [const NamPEntry] Internal table entry
9396 ** @return [AjBool] ajTrue on success
9397 **
9398 ** @release 6.4.0
9399 ** @@
9400 ******************************************************************************/
9401 
namValidServer(const NamPEntry entry)9402 static AjBool namValidServer(const NamPEntry entry)
9403 {
9404     ajint iattr = 0;
9405     ajint j;
9406     ajint k;
9407     AjBool ok;
9408     AjBool oktype;
9409     AjPTable attrtable;
9410     AjBool hasmethod = ajFalse;
9411     AjBool hastype   = ajFalse;
9412     AjPStr name = NULL;
9413     AjPStrTok handle = NULL;
9414     AjPStr token = NULL;
9415     const AjPStr value = NULL;
9416     const AjPStr dbtype = NULL;
9417 
9418     attrtable = (AjPTable) entry->data;
9419 
9420     if(!attrtable)
9421     {			 /* fatal - should be set for all servers */
9422 	namError("Server '%S' has no list of valid attributes",
9423 		  entry->name);
9424 	return ajFalse;
9425     }
9426 
9427     dbtype = ajTableFetchC(attrtable, "type");
9428 
9429     for(j=0; namSvrAttrs[j].Name; j++)
9430     {
9431         if(namSvrAttrs[j].Type != ATTR_STR)
9432             continue;
9433 
9434         ajStrAssignC(&name, namSvrAttrs[j].Name);
9435         value = ajTableFetchS(attrtable, name);
9436 
9437 	if(value)
9438 	{
9439 	    iattr++;
9440 
9441 	    if(ajStrPrefixC(name, "format"))
9442             {
9443                 if(!namInformatTest(value, dbtype))
9444                         namError("Database '%S' %S: '%S' unknown",
9445                                  entry->name, name, value);
9446             }
9447 
9448             if(ajStrPrefixC(name, "method"))
9449             {
9450         	handle = NULL;
9451         	token = ajStrNew();
9452         	hasmethod=ajTrue;
9453 
9454         	ajStrTokenAssignC(&handle, dbtype, " ,;");
9455 
9456         	while(ajStrTokenNextParse(handle, &token))
9457         	    if(!namAccessTest(value, token))
9458         		namError("Server '%S' %S: '%S' unknown",
9459         		         entry->name, name, value);
9460 
9461         	ajStrTokenDel(&handle);
9462         	ajStrDel(&token);
9463             }
9464 
9465 	    if(ajStrPrefixC(name, "type"))
9466 	    {
9467 		hastype=ajTrue;
9468 		oktype = ajFalse;
9469 
9470 		for(k=0; namDbTypes[k].Name; k++)
9471 		    if(ajStrFindAnyC(value, namDbTypes[k].Name) != -1)
9472 			oktype = ajTrue;
9473 
9474 		if(!oktype)
9475 		    namError("Server '%S' %S: '%S' unknown",
9476 			      entry->name, name, value);
9477 	    }
9478 	}
9479     }
9480 
9481     ok = ajTrue;
9482 
9483     if(!iattr)
9484     {
9485 	namError("Server '%S' has no attributes", entry->name);
9486 	ok = ajFalse;
9487     }
9488 
9489     if(!hastype)
9490     {
9491 	namError("Database '%S' has no type definition", entry->name);
9492 	ok = ajFalse;
9493     }
9494 
9495     if(!hasmethod)
9496     {
9497 	namError("Database '%S' has no access method definition",
9498 		  entry->name);
9499 	ok = ajFalse;
9500     }
9501 
9502     ajStrDel(&name);
9503 
9504     return ok;
9505 }
9506 
9507 
9508 
9509 
9510 /* @funcstatic namValidDatabase ***********************************************
9511 **
9512 ** Validation of a master table database entry
9513 **
9514 ** @param [r] entry [const NamPEntry] Internal table entry
9515 ** @return [AjBool] ajTrue on success
9516 **
9517 ** @release 2.7.0
9518 ** @@
9519 ******************************************************************************/
9520 
namValidDatabase(const NamPEntry entry)9521 static AjBool namValidDatabase(const NamPEntry entry)
9522 {
9523     ajint iattr = 0;
9524     ajint j;
9525     ajint k;
9526     AjBool ok;
9527     AjBool oktype;
9528     AjPTable attrtable;
9529     AjBool hasformat = ajFalse;
9530     AjBool hasmethod = ajFalse;
9531     AjBool hastype   = ajFalse;
9532     AjPStr name = NULL;
9533     AjPStr token = NULL;
9534     AjPStr typetoken = NULL;
9535     AjPStrTok handle = NULL;
9536     AjPStrTok typehandle = NULL;
9537     const AjPStr value = NULL;
9538     const AjPStr dbtype = NULL;
9539 
9540     attrtable = (AjPTable) entry->data;
9541 
9542     if(!attrtable)
9543     {			 /* fatal - should be set for all databases */
9544 	namError("Database '%S' has no list of valid attributes",
9545 		  entry->name);
9546 	return ajFalse;
9547     }
9548 
9549     dbtype = ajTableFetchC(attrtable, "type");
9550 
9551     for(j=0; namDbAttrs[j].Name; j++)
9552     {
9553         if(namDbAttrs[j].Type != ATTR_STR)
9554             continue;
9555 
9556         ajStrAssignC(&name, namDbAttrs[j].Name);
9557         value = ajTableFetchS(attrtable, name);
9558 
9559 	if(value)
9560 	{
9561 	    iattr++;
9562 
9563 	    if(ajStrPrefixC(name, "format"))
9564 	    {
9565 		hasformat=ajTrue;
9566 
9567                 ajStrTokenAssignC(&typehandle, dbtype, " ,;");
9568 
9569                 while(ajStrTokenNextParse(typehandle, &typetoken))
9570                 {
9571                     ok = ajFalse;
9572                     ajStrTokenAssignC(&handle, value, " ,;");
9573                     while(ajStrTokenNextParse(handle, &token))
9574                     {
9575                         if(namInformatTest(token, typetoken))
9576                             ok = ajTrue;
9577                     }
9578 
9579                     if(!ok) /* test: dbunknowns.rc */
9580                         namError("Database '%S' %S: '%S' unknown for type '%S'",
9581                                  entry->name, name, value, typetoken);
9582                 }
9583 
9584             }
9585 
9586             if(ajStrPrefixC(name, "method"))
9587 	    {
9588 		hasmethod=ajTrue;
9589 
9590                 ajStrTokenAssignC(&typehandle, dbtype, " ,;");
9591 
9592                 while(ajStrTokenNextParse(typehandle, &typetoken))
9593                 {
9594                     ok = ajFalse;
9595                     ajStrTokenAssignC(&handle, value, " ,;");
9596                     while(ajStrTokenNextParse(handle, &token))
9597                     {
9598                         if(namAccessTest(value, typetoken))
9599                             ok = ajTrue;
9600                     }
9601 
9602                     if(!ok)  /* test: dbunknowns.rc */
9603                         namError("Database '%S' %S: '%S' unknown for type '%S'",
9604                                  entry->name, name, value, typetoken);
9605                 }
9606             }
9607 
9608 	    if(ajStrPrefixC(name, "type"))
9609 	    {
9610 		hastype=ajTrue;
9611 		oktype = ajFalse;
9612 
9613                 ajStrTokenAssignC(&typehandle, value, " ,;");
9614                 while(ajStrTokenNextParse(typehandle, &typetoken))
9615                 {
9616                     for(k=0; namDbTypes[k].Name; k++)
9617                         if(ajStrMatchCaseC(typetoken, namDbTypes[k].Name))
9618                             oktype = ajTrue;
9619                 }
9620 
9621 		if(!oktype)		/* test: dbunknowns.rc */
9622 		    namError("Database '%S' %S: '%S' unknown",
9623 			      entry->name, name, value);
9624 	    }
9625 	}
9626     }
9627 
9628     ok = ajTrue;
9629 
9630     if(!iattr)
9631     {					/* test: dbempty.rc */
9632 	namError("Database '%S' has no attributes", entry->name);
9633 	ok = ajFalse;
9634     }
9635 
9636     if(!hasformat)		/* test: dbempty.rc */
9637     {
9638 	namError("Database '%S' has no format definition", entry->name);
9639 	ok = ajFalse;
9640     }
9641 
9642     if(!hastype)			/* test: dbempty.rc */
9643     {
9644 	namError("Database '%S' has no type definition", entry->name);
9645 	ok = ajFalse;
9646     }
9647 
9648     if(!hasmethod)		/* test: dbempty.rc */
9649     {
9650 	namError("Database '%S' has no access method definition",
9651 		  entry->name);
9652 	ok = ajFalse;
9653     }
9654 
9655     ajStrDel(&name);
9656     ajStrTokenDel(&handle);
9657     ajStrTokenDel(&typehandle);
9658     ajStrDel(&token);
9659     ajStrDel(&typetoken);
9660 
9661     return ok;
9662 }
9663 
9664 
9665 
9666 
9667 /* @funcstatic namValidResource ***********************************************
9668 **
9669 ** Validation of a master table resource entry
9670 **
9671 ** @param [r] entry [const NamPEntry] Internal table entry
9672 ** @return [AjBool] ajTrue on success
9673 **
9674 ** @release 2.7.0
9675 ** @@
9676 ******************************************************************************/
9677 
namValidResource(const NamPEntry entry)9678 static AjBool namValidResource(const NamPEntry entry)
9679 {
9680     ajint iattr = 0;
9681     ajint j;
9682     AjPTable rstable;
9683     AjBool ok;
9684 
9685     rstable = (AjPTable) entry->data;
9686 
9687     if(!rstable)
9688     {			 /* fatal - should be set for all databases */
9689 	namError("Resource '%S' has no list of valid attributes",
9690 		  entry->name);
9691 	return ajFalse;
9692     }
9693 
9694     for(j=0; namRsAttrs[j].Name; j++)
9695 	if(ajTableFetchC(rstable,  namRsAttrs[j].Name))
9696 	    iattr++;
9697 
9698     ok = ajTrue;
9699 
9700     if(!iattr)
9701     {					/* test: dbempty.rc */
9702 	namError("Resource '%S' has no attributes", entry->name);
9703 	ok =  ajFalse;
9704     }
9705 
9706     return ok;
9707 }
9708 
9709 
9710 
9711 
9712 /* @funcstatic namValidVariable ***********************************************
9713 **
9714 ** Validation of a master table variable entry
9715 **
9716 ** @param [r] entry [const NamPEntry] Internal table entry
9717 ** @return [AjBool] ajTrue on success
9718 **
9719 ** @release 2.7.0
9720 ** @@
9721 ******************************************************************************/
9722 
namValidVariable(const NamPEntry entry)9723 static AjBool namValidVariable(const NamPEntry entry)
9724 {
9725     AjPTable attrtable;
9726 
9727     attrtable = (AjPTable) entry->data;
9728 
9729     if(attrtable)
9730     {			 /* strange - should be nothing for variables */
9731 	namError("Variable '%S' has a list of attributes",
9732 		  entry->name);
9733 
9734 	return ajFalse;
9735     }
9736 
9737     return ajTrue;
9738 }
9739 
9740 
9741 
9742 
9743 /* @func ajNamSetControl ******************************************************
9744 **
9745 ** Sets special internal variables to reflect their presence.
9746 **
9747 ** Currently these are "namdebug, namvalid"
9748 **
9749 ** @param [r] optionName [const char*] option name
9750 ** @return [AjBool] ajTrue if option was recognised
9751 **
9752 ** @release 2.7.0
9753 ** @@
9754 ******************************************************************************/
9755 
ajNamSetControl(const char * optionName)9756 AjBool ajNamSetControl(const char* optionName)
9757 {
9758 
9759     if(!ajCharCmpCase(optionName, "namdebug"))
9760     {
9761 	namDoDebug = ajTrue;
9762 
9763 	return ajTrue;
9764     }
9765 
9766     if(!ajCharCmpCase(optionName, "namvalid"))
9767     {
9768 	namDoValid = ajTrue;
9769 
9770 	return ajTrue;
9771     }
9772 
9773     ajDie("Unknown ajNamSetControl control option '%s'", optionName);
9774 
9775     return ajFalse;
9776 }
9777 
9778 
9779 
9780 
9781 /* @func ajNamRsAttrValueC ****************************************************
9782 **
9783 ** Return the value for a resource attribute
9784 **
9785 ** @param [r] name [const char *] resource name
9786 ** @param [r] attribute [const char *] resource attribute
9787 ** @param [w] value [AjPStr *] resource value
9788 
9789 **
9790 ** @return [AjBool] true if found
9791 **
9792 ** @release 3.0.0
9793 ** @@
9794 ******************************************************************************/
9795 
ajNamRsAttrValueC(const char * name,const char * attribute,AjPStr * value)9796 AjBool ajNamRsAttrValueC(const char *name, const char *attribute,
9797 			 AjPStr *value)
9798 {
9799     ajint j;
9800     const NamPEntry fnew = NULL;
9801     const AjPTable rstable;
9802     const AjPStr rsvalue;
9803 
9804     ajDebug("ajNamRsAttrValueC '%s' '%s'\n", name, attribute);
9805 
9806     fnew = ajTableFetchC(namResMasterTable, name);
9807 
9808     if(!fnew)
9809 	return ajFalse;
9810 
9811     rstable = (const AjPTable) fnew->data;
9812     j = namRsAttrC(attribute);
9813 
9814     if(j < 0)
9815     {
9816         if(namRsAttrFieldC(rstable, attribute))
9817             return ajFalse;
9818 
9819 	ajFatal("unknown attribute '%s' requested for resource '%s'",
9820                 attribute, name);
9821     }
9822 
9823     rsvalue = ajTableFetchC(rstable, attribute);
9824 
9825     if(ajStrGetLen(rsvalue))
9826     {
9827 	ajStrAssignS(value,rsvalue);
9828 
9829 	return ajTrue;
9830     }
9831 
9832     return ajFalse;
9833 }
9834 
9835 
9836 
9837 
9838 /* @func ajNamRsAttrValueS ****************************************************
9839 **
9840 ** Return the value for a resource attribute
9841 **
9842 ** @param [r] name [const AjPStr] resource name
9843 ** @param [r] attribute [const AjPStr] resource attribute
9844 ** @param [w] value [AjPStr *] resource value
9845 
9846 **
9847 ** @return [AjBool] true if found
9848 **
9849 ** @release 6.4.0
9850 ** @@
9851 ******************************************************************************/
9852 
ajNamRsAttrValueS(const AjPStr name,const AjPStr attribute,AjPStr * value)9853 AjBool ajNamRsAttrValueS(const AjPStr name, const AjPStr attribute,
9854 			 AjPStr *value)
9855 {
9856     ajint j;
9857     const NamPEntry fnew = NULL;
9858     const AjPTable rstable;
9859     const AjPStr rsvalue;
9860 
9861     ajDebug("ajNamRsAttrValueS '%S' '%S'\n", name, attribute);
9862 
9863     fnew = ajTableFetchS(namResMasterTable, name);
9864 
9865     if(!fnew)
9866 	ajFatal("unknown resource '%S'",
9867                 name);
9868 
9869     j = namRsAttrS(attribute);
9870 
9871     rstable = (const AjPTable) fnew->data;
9872     rsvalue = ajTableFetchS(rstable, attribute);
9873 
9874     ajDebug("resource '%S' found file:%S attribute '%S' j:%d value: '%S'\n",
9875             name, fnew->file, attribute, j, rsvalue);
9876 
9877     if(ajStrGetLen(rsvalue))
9878     {
9879 	ajStrAssignS(value,rsvalue);
9880 
9881 	return ajTrue;
9882     }
9883 
9884     if(j < 0)
9885     {
9886         if(namRsAttrFieldS(rstable, attribute))
9887             return ajFalse;
9888 
9889 	ajFatal("unknown attribute '%S' requested for resource '%S'",
9890                 attribute, name);
9891     }
9892 
9893     return ajFalse;
9894 }
9895 
9896 
9897 
9898 
9899 /* @func ajNamRsListValue *****************************************************
9900 **
9901 ** Return the value for a resource attribute of type 'list'
9902 **
9903 ** @param [r] name [const AjPStr] resource name
9904 ** @param [w] value [AjPStr *] resource value
9905 **
9906 ** @return [AjBool] true if found
9907 **
9908 ** @release 3.0.0
9909 ** @@
9910 ******************************************************************************/
9911 
ajNamRsListValue(const AjPStr name,AjPStr * value)9912 AjBool ajNamRsListValue(const AjPStr name, AjPStr *value)
9913 {
9914     const NamPEntry fnew = NULL;
9915     const AjPTable rstable = NULL;
9916     const AjPStr rsvalue = NULL;
9917 
9918     fnew = ajTableFetchS(namResMasterTable, name);
9919 
9920     rstable = (const AjPTable) fnew->data;
9921     rsvalue = ajTableFetchC(rstable, "type");
9922 
9923     if(!ajStrMatchCaseC(rsvalue, "list"))
9924 	return ajFalse;
9925 
9926     rsvalue = ajTableFetchC(rstable, "value");
9927 
9928     if(ajStrGetLen(rsvalue))
9929     {
9930 	ajStrAssignS(value,rsvalue);
9931 
9932 	return ajTrue;
9933     }
9934 
9935     return ajFalse;
9936 }
9937 
9938 
9939 
9940 
9941 #ifdef AJ_COMPILE_DEPRECATED_BOOK
9942 #endif
9943 
9944 
9945 
9946 
9947 #ifdef AJ_COMPILE_DEPRECATED
9948 /* @obsolete ajNamGetenv
9949 ** @rename ajNamGetenvS
9950 */
ajNamGetenv(const AjPStr name,AjPStr * value)9951 __deprecated AjBool ajNamGetenv(const AjPStr name,
9952 		    AjPStr* value)
9953 {
9954     return ajNamGetenvS(name, value);
9955 }
9956 
9957 
9958 
9959 
9960 /* @obsolete ajNamGetValue
9961 ** @rename ajNamGetValusS
9962 */
9963 
ajNamGetValue(const AjPStr name,AjPStr * value)9964 __deprecated AjBool ajNamGetValue(const AjPStr name, AjPStr* value)
9965 {
9966     return ajNamGetValueC(ajStrGetPtr(name), value);
9967 }
9968 
9969 
9970 
9971 
9972 /* @obsolete ajNamRootInstall
9973 ** @remove Use ajNamValueinstalldir
9974 */
ajNamRootInstall(AjPStr * root)9975 __deprecated AjBool ajNamRootInstall(AjPStr* root)
9976 {
9977     ajStrAssignS(root, namFixedInstallStr);
9978 
9979     if(!ajStrGetLen(*root))
9980         return ajFalse;
9981 
9982     return ajTrue;
9983 }
9984 
9985 
9986 
9987 
9988 /* @obsolete ajNamRootPack
9989 ** @remove Use ajNamValuePackage
9990 */
ajNamRootPack(AjPStr * root)9991 __deprecated AjBool ajNamRootPack(AjPStr* root)
9992 {
9993     ajStrAssignS(root, namFixedPackageStr);
9994 
9995     if(!ajStrGetLen(*root))
9996         return ajFalse;
9997 
9998     return ajTrue;
9999 }
10000 
10001 
10002 
10003 
10004 /* @obsolete ajNamRootVersion
10005 ** @remove Use ajNamValueVersion
10006 */
ajNamRootVersion(AjPStr * version)10007 __deprecated AjBool ajNamRootVersion(AjPStr* version)
10008 {
10009     ajStrAssignS(version, namFixedVersionStr);
10010 
10011     return ajTrue;
10012 }
10013 
10014 
10015 
10016 
10017 /* @obsolete ajNamRoot
10018 ** @remove Use ajNamValueRootdir
10019 */
ajNamRoot(AjPStr * root)10020 __deprecated AjBool ajNamRoot(AjPStr* root)
10021 {
10022     ajStrAssignS(root, namFixedRootStr);
10023 
10024     return ajTrue;
10025 }
10026 
10027 
10028 
10029 
10030 /* @obsolete ajNamRootBase
10031 ** @remove Use ajNamValueBasedir
10032 */
ajNamRootBase(AjPStr * rootbase)10033 __deprecated AjBool ajNamRootBase(AjPStr* rootbase)
10034 {
10035     ajStrAssignS(rootbase, namFixedBaseStr);
10036 
10037     return ajTrue;
10038 }
10039 
10040 
10041 
10042 
10043 /* @obsolete ajNamRsAttrValue
10044 ** @rename ajNamRsAttrValueS
10045 */
ajNamRsAttrValue(const AjPStr name,const AjPStr attribute,AjPStr * value)10046 __deprecated AjBool ajNamRsAttrValue(const AjPStr name, const AjPStr attribute,
10047 			 AjPStr *value)
10048 {
10049     return ajNamRsAttrValueS(name, attribute, value);
10050 }
10051 #endif
10052