2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
6 * These libraries and programs are free software; you can
7 * redistribute them and/or modify them under the terms of the GNU
8 * Lesser General Public License as published by the Free Software
9 * Foundation; either version 2 of the License, or (at your option)
12 * These libraries and programs are distributed in the hope that
13 * they will be useful, but WITHOUT ANY WARRANTY; without even the
14 * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15 * PURPOSE. See the GNU Lesser General Public License for more
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with these librararies and programs; if not, write
20 * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21 * Floor, Boston, MA 02110-1301 USA
23 /* $XConsortium: traninit.c /main/1 1996/07/23 19:43:52 rws $ */
25 * Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
26 * All rights reserved.
30 * Open Software Foundation, Inc.
32 * Permission is hereby granted to use, copy, modify and freely distribute
33 * the software in this file and its documentation for any purpose without
34 * fee, provided that the above copyright notice appears in all copies and
35 * that both the copyright notice and this permission notice appear in
36 * supporting documentation. Further, provided that the name of Open
37 * Software Foundation, Inc. ("OSF") not be used in advertising or
38 * publicity pertaining to distribution of the software without prior
39 * written permission from OSF. OSF makes no representations about the
40 * suitability of this software for any purpose. It is provided "as is"
41 * without express or implied warranty.
44 * Copyright (c) 1996 X Consortium
45 * Copyright (c) 1995, 1996 Dalrymple Consulting
47 * Permission is hereby granted, free of charge, to any person obtaining a copy
48 * of this software and associated documentation files (the "Software"), to deal
49 * in the Software without restriction, including without limitation the rights
50 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
51 * copies of the Software, and to permit persons to whom the Software is
52 * furnished to do so, subject to the following conditions:
54 * The above copyright notice and this permission notice shall be included in
55 * all copies or substantial portions of the Software.
57 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
58 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
59 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
60 * X CONSORTIUM OR DALRYMPLE CONSULTING BE LIABLE FOR ANY CLAIM, DAMAGES OR
61 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
62 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
63 * OTHER DEALINGS IN THE SOFTWARE.
65 * Except as contained in this notice, the names of the X Consortium and
66 * Dalrymple Consulting shall not be used in advertising or otherwise to
67 * promote the sale, use or other dealings in this Software without prior
68 * written authorization.
70 /* ________________________________________________________________________
72 * Program to manipulate SGML instances.
74 * This module contains the initialization routines for translation module.
75 * They mostly deal with reading data files (translation specs, SDATA
76 * mappings, character mappings).
79 * ReadTransSpec(transfile) read/store translation spec from file
80 * ReadSDATA(sdatafile) read/store SDATA mappings from file
81 * ReadMapping(mapfile) read/store char mappings from file
82 * ________________________________________________________________________
90 #include <sys/types.h>
93 #include <tptregexp.h>
95 #include "translate.h"
101 /* forward references */
102 void RememberTransSpec(Trans_t *, int);
104 /* ______________________________________________________________________ */
105 /* Read the translation specs from the input file, storing in memory.
107 * Name of translation spec file.
116 char buf[LINESIZE], *cp, *fn, *cp2;
120 if ((fp=OpenFile(transfile)) == NULL) {
121 fprintf(stderr, "Can not open translation spec file '%s'.\n%s\n",
122 transfile, strerror(errno));
126 memset(&T, 0, sizeof T); /* initialize/clear structure */
127 while (fgets(buf, LINESIZE, fp)) /* read line from .ts file */
130 /* skip comment and blank lines */
131 if (buf[0] == '#' || buf[0] == NL) continue;
133 /* '-' indicates end of a spec. When we hit one, remember what we've
134 * accumulated so far, and null-out the accumulating structure. */
137 RememberTransSpec(&T, lineno);
138 memset(&T, 0, sizeof T);
144 /* See if next line is continued from this one -- ie. it starts with
145 * whitespace. If so, append to current line. (This is similar to
146 * how e-mail headers work...) */
148 c = getc(fp); /* 1st char of next line */
149 if (IsWhite(c)) { /* space or tab? */
150 /* keep getting characters until it's a non-whitespace */
152 while (IsWhite(c)) c = getc(fp);
153 ungetc(c, fp); /* put back non-whitespace */
156 fn = buf + i; /* point to end of string in buffer */
157 fgets(fn, LINESIZE-i, fp); /* read and append to buf */
162 ungetc(c, fp); /* put back non-whitespace */
166 /* Isolate field value */
167 if ((cp=strchr(buf, ':'))) {
168 cp++; /* point past colon */
169 while (*cp && IsWhite(*cp)) cp++; /* point to content */
173 "Trans spec error, missing colon (skipping line):\n %s\n", fn);
176 fn = buf; /* fn is name of the field, cp the value. */
178 /* Check field names in order that they're likely to occur. */
179 if (!strncmp("GI:", fn, 3)) {
180 /* if we are folding the case of GIs, make all upper (unless
181 it's an internal pseudo-GI name, which starts with '_') */
182 if (fold_case && cp[0] != '_' && cp[0] != '#') {
183 for (cp2=cp; *cp2; cp2++)
184 if (islower(*cp2)) *cp2 = toupper(*cp2);
186 T.gi = AddElemName(cp);
188 else if (!strncmp("StartText:", fn, 10)) T.starttext = strdup(cp);
189 else if (!strncmp("EndText:", fn, 8)) T.endtext = strdup(cp);
190 else if (!strncmp("Relation:", fn, 9)) {
191 if (!T.relations) T.relations = NewMap(IMS_relations);
192 SetMapping(T.relations, cp);
194 else if (!strncmp("Replace:", fn, 8)) T.replace = strdup(cp);
195 else if (!strncmp("AttValue:", fn, 9)) {
197 Malloc(1, T.attpair, AttPair_t);
200 Realloc((T.nattpairs+1), T.attpair, AttPair_t);
201 /* we'll split name/value pairs later */
202 T.attpair[T.nattpairs].name = strdup(cp);
205 /* If there's only one item in context, it's the parent. Treat
206 * it specially, since it's easier to just check parent gi.
208 else if (!strncmp("Context:", fn, 8)) T.context = strdup(cp);
209 else if (!strncmp("Message:", fn, 8)) T.message = strdup(cp);
210 else if (!strncmp("SpecID:", fn, 7)) T.my_id = atoi(cp);
211 else if (!strncmp("Action:", fn, 7)) T.use_id = atoi(cp);
212 else if (!strncmp("Content:", fn, 8)) T.content = strdup(cp);
213 else if (!strncmp("PAttSet:", fn, 8)) T.pattrset = strdup(cp);
214 else if (!strncmp("Verbatim:", fn, 9)) T.verbatim = TRUE;
215 else if (!strncmp("Ignore:", fn, 7)) {
216 if (!strcmp(cp, "all")) T.ignore = IGN_ALL;
217 else if (!strcmp(cp, "data")) T.ignore = IGN_DATA;
218 else if (!strcmp(cp, "children")) T.ignore = IGN_CHILDREN;
220 fprintf(stderr, "Bad 'Ignore:' arg in transpec (line %d): %s\n",
223 else if (!strncmp("VarValue:", fn, 9)) {
226 tok = Split(cp, &i, S_STRDUP);
228 T.var_value = tok[1];
230 else if (!strncmp("VarREValue:", fn, 11)) {
233 tok = Split(cp, &i, S_STRDUP);
234 T.var_RE_name = tok[0];
235 ExpandVariables(tok[1], buf, 0);
236 if (!(T.var_RE_value=tpt_regcomp(buf))) {
237 fprintf(stderr, "Regex error in VarREValue Content: %s\n",
241 else if (!strncmp("Set:", fn, 4)) {
242 if (!T.set_var) T.set_var = NewMap(IMS_setvar);
243 SetMapping(T.set_var, cp);
245 else if (!strncmp("Increment:", fn, 10)) {
246 if (!T.incr_var) T.incr_var = NewMap(IMS_incvar);
247 SetMapping(T.incr_var, cp);
249 else if (!strncmp("NthChild:", fn, 9)) T.nth_child = atoi(cp);
250 else if (!strncmp("Var:", fn, 4)) SetMapping(Variables, cp);
251 else if (!strncmp("Quit:", fn, 5)) T.quit = strdup(cp);
253 fprintf(stderr, "Unknown translation spec (skipping it): %s\n", fn);
258 /* ______________________________________________________________________ */
259 /* Store translation spec 't' in memory.
261 * Pointer to translation spec to remember.
262 * Line number where translation spec ends.
272 static Trans_t *last_t;
275 /* If context testing, check some details and set things up for later. */
277 /* See if the context specified is a regular expression.
278 * If so, compile the reg expr. It is assumed to be a regex if
279 * it contains a character other than what's allowed for GIs in the
280 * OSF sgml declaration (alphas, nums, '-', and '.').
282 for (do_regex=0,cp=t->context; *cp; cp++) {
283 if (!isalnum(*cp) && *cp != '-' && *cp != '.' && *cp != ' ') {
290 t->depth = MAX_DEPTH;
291 if (!(t->context_re=tpt_regcomp(t->context))) {
292 fprintf(stderr, "Regex error in Context: %s\n", t->context);
296 /* If there's only one item in context, it's the parent. Treat
297 * it specially, since it's faster to just check parent gi.
300 if (!strchr(cp, ' ')) {
301 t->parent = t->context;
305 /* Figure out depth of context string */
309 while (*cp && !IsWhite(*cp)) cp++; /* find end of gi */
310 while (*cp && IsWhite(*cp)) cp++; /* skip space */
316 /* Compile regular expressions for each attribute */
317 for (i=0; i<t->nattpairs; i++) {
318 /* Initially, name points to "name value". Split them... */
319 cp = t->attpair[i].name;
320 while (*cp && !IsWhite(*cp)) cp++; /* point past end of name */
321 if (*cp) { /* value found */
322 *cp++ = EOS; /* terminate name */
323 while (*cp && IsWhite(*cp)) cp++; /* point to value */
324 ExpandVariables(cp, buf, 0); /* expand any variables */
325 t->attpair[i].val = strdup(buf);
327 else { /* value not found */
328 t->attpair[i].val = ".";
330 if (!(t->attpair[i].rex=tpt_regcomp(t->attpair[i].val))) {
331 fprintf(stderr, "Regex error in AttValue: %s %s\n",
332 t->attpair[i].name, t->attpair[i].val);
336 /* Compile regular expression for content */
339 ExpandVariables(t->content, buf, 0);
340 if (!(t->content_re=tpt_regcomp(buf)))
341 fprintf(stderr, "Regex error in Content: %s\n",
345 /* If multiple GIs, break up into a vector, then remember it. We either
346 * sture the individual, or the list - not both. */
347 if (t->gi && strchr(t->gi, ' ')) {
348 t->gilist = Split(t->gi, 0, S_ALVEC);
352 /* Now, store structure in linked list. */
354 Malloc(1, TrSpecs, Trans_t);
358 Malloc(1, last_t->next, Trans_t);
359 last_t = last_t->next;
365 /* ______________________________________________________________________ */
366 /* Read mapping file, filling in structure slots (just name-value pairs).
368 * Name of character mapping file.
377 char buf[LINESIZE], *name, *val;
379 int n_alloc=0; /* number of slots allocated so far */
381 if ((fp=OpenFile(filename)) == NULL) {
382 fprintf(stderr, "Can not open character mapping file '%s'.\n%s\n",
383 filename, strerror(errno));
387 /* We allocate slots in blocks of N, so we don't have to call
388 * malloc so many times. */
390 Calloc(n_alloc, CharMap, Mapping_t);
393 while (fgets(buf, LINESIZE, fp))
396 /* skip comment and blank lines */
397 if (buf[0] == '#' || buf[0] == NL) continue;
400 /* Need more slots for mapping structures? */
401 if (nCharMap >= n_alloc) {
403 Realloc(n_alloc, CharMap, Mapping_t);
406 while (*val && !IsWhite(*val)) val++; /* point past end of name */
408 *val++ = EOS; /* terminate name */
409 while (*val && IsWhite(*val)) val++; /* point to value */
412 CharMap[nCharMap].name = strdup(name);
413 if (val) CharMap[nCharMap].sval = strdup(val);
414 if (CharMap[nCharMap].name[0] == '\\') CharMap[nCharMap].name++;
421 /* ______________________________________________________________________ */
422 /* Read SDATA mapping file, remembering the mappings in memory.
423 * Input file format is 2 columns, name and value, separated by one or
424 * more tabs (not spaces).
425 * This can be called multuple times, reading several files.
427 * Name of SDATA entity mapping file.
436 char buf[LINESIZE], *name, *val;
439 if ((fp=OpenFile(filename)) == NULL) {
440 fprintf(stderr, "Can not open SDATA file '%s': %s", filename,
445 if (!SDATAmap) SDATAmap = NewMap(IMS_sdata);
447 while (fgets(buf, LINESIZE, fp))
450 /* skip comment and blank lines */
451 if (buf[0] == '#' || buf[0] == NL) continue;
455 while (*val && *val != TAB) val++; /* point past end of name */
457 *val++ = EOS; /* terminate name */
458 while (*val && *val == TAB) val++; /* point to value */
461 SetMappingNV(SDATAmap, name, val);
466 /* ______________________________________________________________________ */