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