1 /*
2 Copyright (c) 1991-1999 Thomas T. Wetmore IV
3
4 Permission is hereby granted, free of charge, to any person
5 obtaining a copy of this software and associated documentation
6 files (the "Software"), to deal in the Software without
7 restriction, including without limitation the rights to use, copy,
8 modify, merge, publish, distribute, sublicense, and/or sell copies
9 of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be
13 included in all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19 BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20 ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 SOFTWARE.
23 */
24 /* modified 05 Jan 2000 by Paul B. McBride (pmcbride@tiac.net) */
25 /*=============================================================
26 * misc.c -- Various useful, miscellaneous routines
27 * Copyright(c) 1992-94 by T.T. Wetmore IV; all rights reserved
28 * 2.3.4 - 24 Jun 93 2.3.5 - 02 Sep 93
29 * 3.0.0 - 08 May 94 3.0.2 - 12 Dec 94
30 * 3.0.3 - 06 Aug 95
31 *===========================================================*/
32
33 #include "llstdlib.h"
34 #include "table.h"
35 #include "translat.h"
36 #include "gedcom.h"
37 #include "zstr.h"
38
39 /*========================================
40 * addat -- Add @'s to both ends of string
41 * returns static buffer
42 *======================================*/
43 STRING
addat(STRING str)44 addat (STRING str)
45 {
46 STRING p;
47 static char buffer[3][20];
48 static INT dex = 0;
49 if (++dex > 2) dex = 0;
50 p = buffer[dex];
51 sprintf(p, "@%s@", str);
52 return p;
53 }
54 /*===========================================
55 * rmvat_char -- Remove bracketing characters
56 * from around a string
57 * returns static buffer
58 *==========================================*/
59 static STRING
rmvat_char(CNSTRING str,char c,char d)60 rmvat_char (CNSTRING str, char c, char d)
61 {
62 STRING p;
63 int len;
64 /* WARNING: GEDCOM 5.5 specifies that the resulting string (XREF) can be
65 * 1 to 22 characters. Allow a little extra. */
66 static char buffer[32][32]; /* was [10][20] pbm 11-jun-96*/
67 static INT dex = 0;
68 /* Watch out for bad pointers */
69 if((str == NULL) || (*str == '\0')) return(NULL);
70 if (str[0] != c) return NULL;
71 if (++dex > 31) dex = 0; /* was 9 pbm 11-jun-96*/
72 p = buffer[dex];
73 len = strlen(str+1);
74 if (str[len] != d) return NULL;
75 if(len > 31) len = 31; /* 31 characters is maximum */
76 else if(len > 0) len--;
77 strncpy(p, &str[1], len);
78 p[len] = 0; /* overwrite trailing "@" with null */
79 return p;
80 }
81 /*=============================================
82 * rmvat -- Remove @'s from both ends of string
83 * returns static buffer
84 *===========================================*/
85 STRING
rmvat(CNSTRING str)86 rmvat (CNSTRING str)
87 {
88 return rmvat_char(str, '@', '@');
89 }
90 /*=============================================
91 * rmvbrackets -- Remove <>'s from around a string
92 * returns static buffer
93 *===========================================*/
94 STRING
rmvbrackets(CNSTRING str)95 rmvbrackets (CNSTRING str)
96 {
97 return rmvat_char(str, '<', '>');
98 }
99 /*=============================================
100 * node_to_keynum -- key # of a 0 level node
101 * returns 0 for failure
102 *===========================================*/
103 INT
node_to_keynum(char ntype,NODE nod)104 node_to_keynum(char ntype, NODE nod)
105 {
106 if (!nod) return 0;
107 return xrefval(ntype, nxref(nod));
108 }
109 /*=============================================
110 * xrefval -- numeric value after removing @'s at both ends
111 *===========================================*/
112 INT
xrefval(char ntype,STRING str)113 xrefval (char ntype, STRING str)
114 {
115 INT val, i, len;
116 if ((str == NULL) || (*str == '\0')) return 0;
117 len = strlen(str);
118 if (str[0] != '@' || str[len-1] != '@') return 0;
119 if (str[1] != ntype) return 0;
120 val=0;
121 for (i=2; i<len-1; i++) {
122 if (chartype((uchar)str[i]) != DIGIT) return 0;
123 if (i>31) return 0;
124 val = val*10 + (str[i]-'0');
125 }
126 return val;
127 }
128 /*==============================================
129 * find_tag -- Search node list for specific tag
130 *============================================*/
131 NODE
find_tag(NODE node,CNSTRING str)132 find_tag (NODE node, CNSTRING str)
133 {
134 while (node) {
135 ASSERT(ntag(node));
136 if (eqstr(str, ntag(node))) return node;
137 node = nsibling(node);
138 }
139 return NULL;
140 }
141 /*=================================================
142 * val_to_sex -- Convert SEX value to internal form
143 *===============================================*/
144 INT
val_to_sex(NODE node)145 val_to_sex (NODE node)
146 {
147 if (!node || !nval(node)) return SEX_UNKNOWN;
148 if (eqstr("M", nval(node))) return SEX_MALE;
149 if (eqstr("F", nval(node))) return SEX_FEMALE;
150 return SEX_UNKNOWN;
151 }
152 /*====================================================
153 * full_value -- Return value of node, with CONC & CONT lines
154 * (sep is used before CONT lines, eg, "\n")
155 * heap-allocated string is returned
156 *==================================================*/
157 STRING
full_value(NODE node,STRING sep)158 full_value (NODE node, STRING sep)
159 {
160 NODE child;
161 ZSTR zstr = 0;
162 STRING str = 0;
163 if (!node) return NULL;
164 if (nval(node))
165 zstr = zs_news(nval(node));
166 else
167 zstr = zs_new();
168 for (child = nchild(node); child ; child = nsibling(child)) {
169 if (nchild(child) || !ntag(child)) break;
170 if (eqstr("CONC", ntag(child))) {
171 if (nval(child)) {
172 zs_apps(zstr, nval(child));
173 }
174 } else if (eqstr("CONT", ntag(child))) {
175 if (sep) {
176 zs_apps(zstr, sep);
177 }
178 if (nval(child)) {
179 zs_apps(zstr, nval(child));
180 }
181 } else {
182 break;
183 }
184 }
185 str = strdup(zs_str(zstr));
186 zs_free(&zstr);
187 return str;
188 }
189