doc2sdl: use POSIX regex functions.
This commit is contained in:
15
cde/programs/dtdocbook/doc2sdl/instant/Makefile.am
Normal file
15
cde/programs/dtdocbook/doc2sdl/instant/Makefile.am
Normal file
@@ -0,0 +1,15 @@
|
||||
MAINTAINERCLEANFILES = Makefile.in
|
||||
|
||||
include ../doc2sdl.am
|
||||
|
||||
doc2sdllibexec_PROGRAMS = instant
|
||||
|
||||
instant_CFLAGS = $(DT_INCDIR)
|
||||
|
||||
instant_LDADD = $(DTCLIENTLIBS) $(XTOOLLIB)
|
||||
|
||||
instant_CFLAGS += @TCL_INCLUDE_SPEC@
|
||||
instant_LDADD += @TCL_LIB_SPEC@
|
||||
|
||||
instant_SOURCES = main.c util.c info.c translate.c traninit.c tranvar.c \
|
||||
tables.c browse.c
|
||||
151
cde/programs/dtdocbook/doc2sdl/instant/README
Normal file
151
cde/programs/dtdocbook/doc2sdl/instant/README
Normal file
@@ -0,0 +1,151 @@
|
||||
/* $XConsortium: README /main/2 1996/07/15 14:09:31 drk $ */
|
||||
#
|
||||
# Copyright (c) 1994
|
||||
# Open Software Foundation, Inc.
|
||||
#
|
||||
# Permission is hereby granted to use, copy, modify and freely distribute
|
||||
# the software in this file and its documentation for any purpose without
|
||||
# fee, provided that the above copyright notice appears in all copies and
|
||||
# that both the copyright notice and this permission notice appear in
|
||||
# supporting documentation. Further, provided that the name of Open
|
||||
# Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without prior
|
||||
# written permission from OSF. OSF makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
|
||||
instant - a formatting application for OSF SGML instances
|
||||
____________________________________________________________________________
|
||||
|
||||
Requirements
|
||||
|
||||
ANSI C compiler (gcc is one)
|
||||
|
||||
sgmls 1.1 -- sgml parser from James Clark. Based on Goldfarb's ARC parser.
|
||||
|
||||
Vanilla unix make
|
||||
|
||||
POSIX C libraries
|
||||
|
||||
|
||||
Files for instant program
|
||||
|
||||
Module Function
|
||||
------ --------
|
||||
browse.c interactive browser
|
||||
general.h general definitions
|
||||
info.c print information about the instances
|
||||
main.c main entry, arg parsing, instance reading
|
||||
tables.c table-specific formatting routines (TeX and tbl)
|
||||
traninit.c translator initialization (read spec, etc.)
|
||||
translate.c main translator
|
||||
translate.h structure definitions for translation code
|
||||
tranvar.c routines for handling "special variables"
|
||||
util.c general utilities
|
||||
|
||||
|
||||
Also required
|
||||
|
||||
1. Translation spec (transpec) files. (../transpecs/*.ts)
|
||||
2. SDATA mapping files for mapping sdata entities. (../transpecs/*.sdata)
|
||||
3. Character mapping files for mapping characters. (../transpecs/*.cmap)
|
||||
|
||||
|
||||
Platforms tried on
|
||||
|
||||
OSF1 1.3 (i486)
|
||||
Ultrix 4.2 (mips)
|
||||
HP-UX 9.01 (hp 9000/700)
|
||||
AIX 3.2 (rs6000)
|
||||
SunOS [missing strerror()]
|
||||
|
||||
____________________________________________________________________________
|
||||
|
||||
General outline of program
|
||||
------- ------- -- -------
|
||||
|
||||
To summarize in a sentence, instant reads the output of sgmls, builds a tree
|
||||
of the instnace in memory, then traverses the tree in in-order, processing
|
||||
the nodes according to a translation spec.
|
||||
|
||||
Element tree storage
|
||||
------- ---- -------
|
||||
|
||||
The first thing instant must do is read the ESIS (output of sgmls) from the
|
||||
specified file or stdin, forming a tree in memory. (Nothing makes sense
|
||||
without an instance...) Each element of the instance is a node in the tree,
|
||||
stored as a structure called Element_t. Elements contain content (what
|
||||
else?), which is a mixture of data (#PCDATA, #CDATA, #RCDATA - all the same
|
||||
in the ESIS), child elements, and PIs. Each 'chunk' of content is referred
|
||||
to by a Content_t structure. A Content_t contains an enum that can point to
|
||||
a string (data or PI), another Element_t. For example, if a <p> element
|
||||
contains some characters, an <emphasis> element, some more characters,
|
||||
a <function> element, then some more characters, it has 5 Content_t children
|
||||
as an array.
|
||||
|
||||
Element_t's have pointers to their parents, and a next element in a linked
|
||||
list (they're stored as a linked list, for cases when you'd want to quickly
|
||||
travers all the nodes, in no particular order).
|
||||
For convenience, Element_t's have an array of pointers to it's child
|
||||
Element_t's. These are just pointers to the same thing contained in the
|
||||
Content_t array, without the intervening data or PIs. This makes it easier
|
||||
for the program to traverse the elements of the tree (it does not have to
|
||||
be concerned with skipping data, etc.). There is an analagous array of
|
||||
pointers for the data content, an array of (char *)'s. This makes it easier
|
||||
to consider the immediate character content of an element.
|
||||
|
||||
Attributes are kept as an array of name-value mappings (using the typedef
|
||||
Mapping_t). ID attributes are also stored in a separate list of ID value -
|
||||
element pointer pairs so that it is quick to find an element by ID.
|
||||
|
||||
Other information kept about each element (in the Element_t struct) includes
|
||||
the line number in the EISI where the element occurs, the input filename.
|
||||
(These depend on sgmls being run with the "-l" option.) Also stored is
|
||||
an element's order in its parent's collection of children and an element's
|
||||
depth in the tree.
|
||||
|
||||
Translation specs
|
||||
----------- -----
|
||||
|
||||
A translation spec is read into a linked list in memory. As the instance
|
||||
tree is traversed, the transpecs are searched in order for a match. As a
|
||||
rule, one should position the less specific transpecs later in the file.
|
||||
Also, specs for seldom-used element are best placed later in the file, since
|
||||
it takes cpu cycles to skip over them for each of the more-used elements.
|
||||
|
||||
During translation of a particular element, the list of Content_t structures
|
||||
are processed in order. If a content 'chunk' is data, it is printed to
|
||||
the output stream. If it is an element, the translation routine is called
|
||||
for that elemen, recursively. Hence, in-order traversal.
|
||||
|
||||
Miscellaneous information displays
|
||||
------------- ----------- --------
|
||||
|
||||
There are several informational display options available. They include:
|
||||
- a list of element usage (-u) -- lists each element in the instance,
|
||||
it's attributes, number of children, parent, data content 'nodes'.
|
||||
- statistics about elements (-S) -- lists elements, number of times
|
||||
each is used, percent of elements that this is, total char content
|
||||
in that element, average number of characters in they element.
|
||||
- show context of each element (-x) -- lists each element and its
|
||||
context, looking up the tree (this is the same context that
|
||||
would match the Context field of a transpec).
|
||||
- show the hierarchy of the instance (-h) -- show an ascii 'tree' of
|
||||
the instance, where elements deeper in the tree are indented more.
|
||||
Numbers after the element name in parentheses are the number of
|
||||
element content nodes and the number of data content nodes.
|
||||
|
||||
Interactive browser
|
||||
----------- -------
|
||||
|
||||
Originally, the interactive browser was intended as a debugging aid for
|
||||
the code developer. It was a way to examine a particular node of the
|
||||
instance tree or process a subtree without being distracted by the rest
|
||||
of the instance. Many of the commands test functionality of the query
|
||||
and search code (such as testing whether a certain element has a given
|
||||
relationship to the current position in the tree).
|
||||
|
||||
|
||||
____________________________________________________________________________
|
||||
|
||||
47
cde/programs/dtdocbook/doc2sdl/instant/TODO
Normal file
47
cde/programs/dtdocbook/doc2sdl/instant/TODO
Normal file
@@ -0,0 +1,47 @@
|
||||
#
|
||||
# Copyright (c) 1994
|
||||
# Open Software Foundation, Inc.
|
||||
#
|
||||
# Permission is hereby granted to use, copy, modify and freely distribute
|
||||
# the software in this file and its documentation for any purpose without
|
||||
# fee, provided that the above copyright notice appears in all copies and
|
||||
# that both the copyright notice and this permission notice appear in
|
||||
# supporting documentation. Further, provided that the name of Open
|
||||
# Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without prior
|
||||
# written permission from OSF. OSF makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
|
||||
Stuff to do:
|
||||
|
||||
Add param to _nchild - gi. ??
|
||||
|
||||
Tables
|
||||
|
||||
Consider having _osftable do the entire table, just calling it
|
||||
for each call and row.
|
||||
|
||||
More work on tables, in general. (try more test more cases, etc.)
|
||||
|
||||
Document _osftable special variable better.
|
||||
|
||||
Use message catalogs.
|
||||
|
||||
Investigate translating StartText/EndText escapes (\n, etc.) as they are
|
||||
read, not when processing.
|
||||
|
||||
Keep a list of SpecID's. Right now we search all specs in FindSpecByID().
|
||||
|
||||
a test suite
|
||||
|
||||
PI mapping - document how it works
|
||||
|
||||
faster trans spec lookup (hash buckets?)
|
||||
|
||||
Info option:
|
||||
in summary, total and avg char data in for each elem type
|
||||
|
||||
when malloc'ing structs of a linked list, do N structures at a shot?
|
||||
|
||||
466
cde/programs/dtdocbook/doc2sdl/instant/browse.c
Normal file
466
cde/programs/dtdocbook/doc2sdl/instant/browse.c
Normal file
@@ -0,0 +1,466 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Module for interactive browsing.
|
||||
*
|
||||
* Entry points for this module:
|
||||
* Browse() interactive browser
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid =
|
||||
"$XConsortium: browse.c /main/3 1996/06/19 17:13:03 drk $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "general.h"
|
||||
|
||||
static void PrElemPlusID(Element_t *);
|
||||
static void ls_node(Element_t *, int, char **);
|
||||
static void do_query(Element_t *, char *, char *);
|
||||
static void do_find(Element_t *, char **);
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
static char *br_help_msg[] = {
|
||||
" ls List info about current element in tree",
|
||||
" (context, children, attributes, etc.)",
|
||||
" cd N ... Change to Nth elememt child, where N is shown by 'ls'.",
|
||||
" N may also be '/' (top) or '..' (up).",
|
||||
" cd id I Change to elememt whose ID is I",
|
||||
" data N Show data of Nth data node",
|
||||
" where Show current position in the tree",
|
||||
" id I Show path to element with id I",
|
||||
" (using '?' for I will lists all IDs and their paths)",
|
||||
" find S Find elements matching spec S. Recognized syntaxes:",
|
||||
" find attr <name> <value>",
|
||||
" find cont <string>",
|
||||
" find parent <gi-name>",
|
||||
" find child <gi-name>",
|
||||
" find gi <gi-name>",
|
||||
" q rel gi Query: report if elem 'gi' has relation to current elem",
|
||||
" ('rel' is one of 'child parent ancestor descendant",
|
||||
" sibling sibling+ sibling+1 sibling- sibling-1 cousin')",
|
||||
"",
|
||||
" tran file [outfile]",
|
||||
" With trans spec in 'file' translate into 'outfile' (stdout)",
|
||||
" sdata file Read SDATA map file (for translations).",
|
||||
" cmap file Read character map file (for translations).",
|
||||
" stat Print statistics (how often elements occur, etc.)",
|
||||
" sum Print elem usage summary (# of children, depth, etc.)",
|
||||
" tree Print document hierarchy as a tree",
|
||||
" cont Print context of each element",
|
||||
NULL
|
||||
};
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
void
|
||||
Browse(void)
|
||||
{
|
||||
char buf[256], *cmd, **av, **sv, *cmapfile, *sdatafile;
|
||||
char *Prompt;
|
||||
Element_t *ce; /* current element */
|
||||
Element_t *e;
|
||||
int i, n, ac;
|
||||
|
||||
if (slave) Prompt = "=>\n";
|
||||
else Prompt = "=> ";
|
||||
|
||||
ce = DocTree;
|
||||
while (fputs(Prompt, stdout)) {
|
||||
if (!fgets(buf, 256, stdin)) break;
|
||||
stripNL(buf);
|
||||
if (buf[0] == EOS) {
|
||||
fputs(Prompt, stdout);
|
||||
continue;
|
||||
}
|
||||
ac = 20;
|
||||
av = Split(buf, &ac, S_ALVEC);
|
||||
if (ac > 0) cmd = av[0];
|
||||
if (!cmd || !(*cmd)) continue;
|
||||
|
||||
if (!strcmp(cmd, "ls")) ls_node(ce, ac, av);
|
||||
|
||||
else if (!strcmp(cmd, "cd")) {
|
||||
if (av[1]) {
|
||||
if (ac == 3 && !strcmp(av[1], "id")) {
|
||||
if ((e = FindElemByID(av[2]))) ce = e;
|
||||
else printf("Element with ID '%s' not found.\n", av[2]);
|
||||
continue;
|
||||
}
|
||||
for (i=1; i<ac; i++) {
|
||||
if (!strcmp(av[i], "..")) {
|
||||
if (ce->parent) ce = ce->parent;
|
||||
continue;
|
||||
}
|
||||
if (!strcmp(av[i], "/")) {
|
||||
if (ce->parent) ce = DocTree;
|
||||
continue;
|
||||
}
|
||||
if (!isdigit(*av[i])) {
|
||||
printf("Expecting digit, '..', or '/', got '%s'.\n",
|
||||
av[i]);
|
||||
break;
|
||||
}
|
||||
n = atoi(av[i]);
|
||||
if (n < ce->necont) ce = ce->econt[n];
|
||||
else {
|
||||
printf("Must be in range 0 - %d.\n", ce->necont);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "data")) {
|
||||
if (av[1] && isdigit(*av[1])) {
|
||||
n = atoi(av[1]);
|
||||
if (n < ce->ndcont) {
|
||||
printf("%s", ce->dcont[n]);
|
||||
fputs("\n", stdout);
|
||||
}
|
||||
else if (ce->ndcont == 0)
|
||||
printf("No data at this node.\n");
|
||||
else printf("Must be in range 0 - %d.\n", ce->ndcont);
|
||||
}
|
||||
}
|
||||
|
||||
/* show where we are in the tree */
|
||||
else if (!strcmp(cmd, "where")) PrintLocation(ce, stdout);
|
||||
|
||||
/* show where we are in the tree */
|
||||
else if (!strcmp(cmd, "pwd")) PrElemPlusID(ce);
|
||||
|
||||
/* perform query with yes/no answer */
|
||||
else if (!strcmp(cmd, "q") && av[1] && av[2])
|
||||
do_query(ce, av[1], av[2]);
|
||||
|
||||
/* perform query printing paths to matching elements */
|
||||
else if (!strcmp(cmd, "find") && av[1] && av[2])
|
||||
do_find(ce, av);
|
||||
|
||||
/* list locations where specified ID(s) occur */
|
||||
else if (!strcmp(cmd, "id")) {
|
||||
if (ac <= 1) continue;
|
||||
if (*av[1] == '?') PrintIDList();
|
||||
else {
|
||||
/* short: "id i1 i2 ...", long: "id -l i1 i2 ..." */
|
||||
if (!strcmp(av[1], "-l")) n = 2;
|
||||
else n = 1;
|
||||
for (i=n; i<ac; i++) {
|
||||
if ((e = FindElemByID(av[i]))) {
|
||||
if (n == 2) { /* long (multiline) format */
|
||||
if (n != i) putchar('\n');
|
||||
PrintLocation(e, stdout);
|
||||
}
|
||||
else PrElemPlusID(e);
|
||||
}
|
||||
else printf("Element with ID '%s' not found.\n", av[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* show and set variables */
|
||||
else if (!strcmp(cmd, "show") && av[1]) {
|
||||
printf("%s\n", FindMappingVal(Variables, av[1]));
|
||||
}
|
||||
else if (!strcmp(cmd, "set") && av[1] && av[2]) {
|
||||
SetMappingNV(Variables, av[1], av[2]);
|
||||
}
|
||||
|
||||
/* print summary of tag usage */
|
||||
else if (!strcmp(cmd, "sum")) {
|
||||
if (ac > 1) PrintElemSummary(ce);
|
||||
else PrintElemSummary(DocTree);
|
||||
}
|
||||
/* print element tree */
|
||||
else if (!strcmp(cmd, "tree")) {
|
||||
if (ac > 1) PrintElemTree(ce);
|
||||
else PrintElemTree(DocTree);
|
||||
}
|
||||
/* print statistics */
|
||||
else if (!strcmp(cmd, "stat")) {
|
||||
if (ac > 1) PrintStats(ce);
|
||||
else PrintStats(DocTree);
|
||||
}
|
||||
/* print context of each element of tree */
|
||||
else if (!strcmp(cmd, "cont")) {
|
||||
if (ac > 1) PrintContext(ce);
|
||||
else PrintContext(DocTree);
|
||||
}
|
||||
/* print translation, given transpec */
|
||||
else if (!strcmp(cmd, "tran")) {
|
||||
FILE *fp;
|
||||
if (ac > 2){
|
||||
if (!(fp = fopen(av[2], "w"))) {
|
||||
perror("Can not open output file");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else fp = stdout;
|
||||
DoTranslate(ce, av[1], fp);
|
||||
if (ac > 2) fclose(fp);
|
||||
}
|
||||
else if (!strcmp(cmd, "sdata")){
|
||||
sdatafile = strdup(av[1]);
|
||||
ReadSDATA(sdatafile);
|
||||
}
|
||||
else if (!strcmp(cmd, "cmap")){
|
||||
cmapfile = strdup(av[1]);
|
||||
ReadCharMap(cmapfile);
|
||||
}
|
||||
|
||||
else if (!strcmp(cmd, "help") || *cmd == '?') {
|
||||
sv = br_help_msg;
|
||||
while (*sv) puts(*sv++);
|
||||
}
|
||||
|
||||
/* quit (control-D also works) */
|
||||
else if (!strcmp(cmd, "quit")) break;
|
||||
|
||||
else
|
||||
fprintf(stderr, "Unknown command '%s' - ignored.\n", cmd);
|
||||
}
|
||||
putc(NL, stdout);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Do the "ls" command.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* Arg count from command line (this command, not the shell command).
|
||||
* Arg vector.
|
||||
*/
|
||||
|
||||
static void
|
||||
ls_node(
|
||||
Element_t *e,
|
||||
int ac,
|
||||
char **av
|
||||
)
|
||||
{
|
||||
int i;
|
||||
char buf[LINESIZE];
|
||||
|
||||
if (ac > 1 && !strcmp(av[1], "-n")) {
|
||||
for(i=0; i<e->ncont; i++) {
|
||||
if (IsContElem(e,i)) printf("%s\n", ContElem(e,i)->gi);
|
||||
else if (IsContData(e,i)) printf("#data %s\n", ContData(e,i));
|
||||
else if (IsContPI(e,i)) printf("#pi %s\n", ContData(e,i));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
printf("Element: %s\tLineNumber: %d\n", e->gi, e->lineno);
|
||||
if (e->parent)
|
||||
printf("Context: %s\n", FindContext(e, 20, buf));
|
||||
|
||||
if (e->natts) {
|
||||
printf("%d attributes:\n", e->natts);
|
||||
for (i=0; i<e->natts; i++)
|
||||
printf("\t%2d: %s = '%s'\n", i, e->atts[i].name, e->atts[i].sval);
|
||||
}
|
||||
if (e->entity) {
|
||||
printf("Entity & notation information:\n");
|
||||
if (e->entity->ename)
|
||||
printf("Entity name: %s\n", e->entity->ename);
|
||||
if (e->entity->nname)
|
||||
printf("Notation name: %s\n", e->entity->nname);
|
||||
if (e->entity->sysid)
|
||||
printf("Sys id: %s\n", e->entity->sysid);
|
||||
if (e->entity->pubid)
|
||||
printf("Pub id: %s\n", e->entity->pubid);
|
||||
if (e->entity->fname)
|
||||
printf("Filename: %s\n", e->entity->fname);
|
||||
}
|
||||
|
||||
if (e->my_eorder >= 0)
|
||||
printf("My order among my siblings: %d\n", e->my_eorder);
|
||||
|
||||
if (e->necont) {
|
||||
printf("%d child element nodes:\n", e->necont);
|
||||
for(i=0; i<e->necont; i++) printf("\t%2d: %s\n", i, e->econt[i]->gi);
|
||||
}
|
||||
|
||||
if (e->ndcont) {
|
||||
printf("%d child data nodes:\n", e->ndcont);
|
||||
for(i=0; i<e->ndcont; i++) {
|
||||
if (strlen(e->dcont[i]) < 40)
|
||||
printf("\t%2d: %s\n", i, e->dcont[i]);
|
||||
else
|
||||
printf("\t%2d: %-40.40s...\n", i, e->dcont[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Perform query. Syntax: find relationship gi. Tells whether gi has
|
||||
* given relationship to current element. Result (message) sent to stdout.
|
||||
* Args:
|
||||
* Pointer to element under consideration.
|
||||
* Pointer to name of relationship. (see FindRelByName() for names)
|
||||
* Pointer to GI to look for.
|
||||
*/
|
||||
|
||||
static void
|
||||
do_query(
|
||||
Element_t *e,
|
||||
char *rel,
|
||||
char *gi
|
||||
)
|
||||
{
|
||||
char *cp;
|
||||
Relation_t r;
|
||||
Element_t *ep;
|
||||
|
||||
for (cp=gi; *cp; cp++) if (islower(*cp)) *cp = toupper(*cp);
|
||||
|
||||
if ((r = FindRelByName(rel)) == REL_Unknown) {
|
||||
return;
|
||||
}
|
||||
ep = QRelation(e, gi, r);
|
||||
printf("%s, '%s' is%s %s of '%s'.\n", (ep ? "Yes" : "No"), gi,
|
||||
(ep ? "" : " not"), rel, e->gi);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Print path to the element and its ID (if it has one) on a single line.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
*/
|
||||
static void
|
||||
PrElemPlusID(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
char buf[LINESIZE];
|
||||
|
||||
if (e->id) printf("%s -- ID=%s\n", FindElementPath(e, buf), e->id);
|
||||
else printf("%s\n", FindElementPath(e, buf));
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Print path to the element and its ID (if it has one) on a single line.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
*/
|
||||
|
||||
static void
|
||||
match_gi(
|
||||
Element_t *e,
|
||||
char **av
|
||||
)
|
||||
{
|
||||
if (!strcmp(av[1], e->gi)) PrElemPlusID(e);
|
||||
}
|
||||
|
||||
/* Shorthand for defining simple finctions, which are just interfaces to
|
||||
* calling QRelation(). DescendTree() only passes ptr to element. */
|
||||
#define MATCH(Fun,Rel) \
|
||||
static void Fun(Element_t *e, char **av) \
|
||||
{ if (QRelation(e, av[1], Rel)) PrElemPlusID(e); }
|
||||
|
||||
MATCH(match_parent, REL_Parent)
|
||||
MATCH(match_child, REL_Child)
|
||||
MATCH(match_anc, REL_Ancestor)
|
||||
MATCH(match_desc, REL_Descendant)
|
||||
MATCH(match_sib, REL_Sibling)
|
||||
|
||||
static void
|
||||
match_attr(
|
||||
Element_t *e,
|
||||
char **av
|
||||
)
|
||||
{
|
||||
char *atval;
|
||||
|
||||
if ((atval = FindAttValByName(e, av[1])) && !strcmp(av[2], atval))
|
||||
PrElemPlusID(e);
|
||||
}
|
||||
|
||||
static void
|
||||
match_cont(
|
||||
Element_t *e,
|
||||
char **av
|
||||
)
|
||||
{
|
||||
int i;
|
||||
for (i=0; i<e->ncont; i++) {
|
||||
if (IsContData(e,i) && strstr(ContData(e,i), av[1])) {
|
||||
PrElemPlusID(e);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Find an element, given the criteria on its command line.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
*/
|
||||
static void
|
||||
do_find(
|
||||
Element_t *e,
|
||||
char **av
|
||||
)
|
||||
{
|
||||
av++;
|
||||
if (!strcmp(av[0], ".")) av++;
|
||||
else e = DocTree;
|
||||
if (!strcmp(av[0], "gi")) DescendTree(e, match_gi, 0, 0, av);
|
||||
else if (!strcmp(av[0], "attr")) DescendTree(e, match_attr, 0, 0, av);
|
||||
else if (!strcmp(av[0], "parent")) DescendTree(e, match_parent, 0, 0, av);
|
||||
else if (!strcmp(av[0], "child")) DescendTree(e, match_child, 0, 0, av);
|
||||
else if (!strcmp(av[0], "cont")) DescendTree(e, match_cont, 0, 0, av);
|
||||
else if (!strcmp(av[0], "sib")) DescendTree(e, match_sib, 0, 0, av);
|
||||
else if (!strcmp(av[0], "desc")) DescendTree(e, match_desc, 0, 0, av);
|
||||
else if (!strcmp(av[0], "anc")) DescendTree(e, match_anc, 0, 0, av);
|
||||
else fprintf(stderr, "Unknown find command: %s.\n", av[0]);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
331
cde/programs/dtdocbook/doc2sdl/instant/general.h
Normal file
331
cde/programs/dtdocbook/doc2sdl/instant/general.h
Normal file
@@ -0,0 +1,331 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Common definitions for "instant" program.
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifdef STORAGE
|
||||
#ifndef lint
|
||||
static char *gen_h_RCSid =
|
||||
"$XConsortium: general.h /main/11 1996/08/08 14:41:50 cde-hp $";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* get Tcl header so the variables make sense */
|
||||
#include <tcl.h>
|
||||
|
||||
/* Compatibility with pre 8.6 versions */
|
||||
#if (TCL_MAJOR_VERSION < 8) || (TCL_MAJOR_VERSION == 8) && (TCL_MINOR_VERSION < 6)
|
||||
# define Tcl_GetErrorLine(x) ((x)->errorLine)
|
||||
#endif
|
||||
|
||||
/* instant variable delimiter (can't use '$', collides with Tcl) */
|
||||
#define VDELIM '@'
|
||||
|
||||
/* string/numeric/character definitions */
|
||||
|
||||
#define EOS '\0'
|
||||
#define NL '\n'
|
||||
#define TAB '\t'
|
||||
#define CR '\r'
|
||||
#define ANCHOR '^'
|
||||
|
||||
/* bigmask/flags for the Split() function */
|
||||
#define S_STRDUP 0x01
|
||||
#define S_ALVEC 0x02
|
||||
|
||||
/* Command codes (1st char of esis lines) from sgmls. See its manpage. */
|
||||
#define CMD_DATA '-'
|
||||
#define CMD_OPEN '('
|
||||
#define CMD_CLOSE ')'
|
||||
#define CMD_ATT 'A'
|
||||
#define CMD_D_ATT 'D'
|
||||
#define CMD_NOTATION 'N'
|
||||
#define CMD_EXT_ENT 'E'
|
||||
#define CMD_INT_ENT 'I'
|
||||
#define CMD_SYSID 's'
|
||||
#define CMD_PUBID 'p'
|
||||
#define CMD_FILENAME 'f'
|
||||
#define CMD_LINE 'L'
|
||||
#define CMD_PI '?'
|
||||
#define CMD_SUBDOC 'S'
|
||||
#define CMD_SUBDOC_S '{'
|
||||
#define CMD_SUBDOC_E '}'
|
||||
#define CMD_EXT_REF '&'
|
||||
#define CMD_APPINFO '#'
|
||||
#define CMD_CONFORM 'C'
|
||||
|
||||
/* Some sizes */
|
||||
#define MAX_DEPTH 40
|
||||
#define LINESIZE 60000
|
||||
|
||||
/* Name of library env variable, and default value. */
|
||||
#ifndef TPT_LIB
|
||||
#define TPT_LIB "TPT_LIB"
|
||||
#endif
|
||||
#ifndef DEF_TPT_LIB
|
||||
#define DEF_TPT_LIB "/project/tools/libdata/tpt"
|
||||
#endif
|
||||
|
||||
/* for buffered output (buffer gets passed to interpreter) */
|
||||
typedef struct _OutputBuffer {
|
||||
char *base; /* pointer to start of buffer */
|
||||
char *current; /* pointer to current location in buffer */
|
||||
int size; /* total size of buffer */
|
||||
} OutputBuffer_t;
|
||||
|
||||
#define OBUF_INCR 4096 /* enlarge buffer by this when full */
|
||||
#ifndef MIN
|
||||
#define MIN(i,j) (((i) < (j)) ? (i) : (j))
|
||||
#endif
|
||||
|
||||
/* Relationships - for querying */
|
||||
typedef enum {
|
||||
REL_None, REL_Parent, REL_Child, REL_Ancestor, REL_Descendant,
|
||||
REL_Sibling, REL_Preceding, REL_ImmPreceding, REL_Following,
|
||||
REL_ImmFollowing, REL_Cousin, REL_Is1stContent, REL_HasOnlyContent,
|
||||
REL_Unknown
|
||||
} Relation_t;
|
||||
|
||||
/* Initial map sizes (IMS) */
|
||||
#define IMS_relations 3
|
||||
#define IMS_setvar 3
|
||||
#define IMS_incvar 3
|
||||
#define IMS_sdata 50
|
||||
#define IMS_sdatacache 30
|
||||
#define IMS_variables 20
|
||||
#define IMS_attnames 50
|
||||
#define IMS_elemnames 50
|
||||
|
||||
/* ----- structure definitions ----- */
|
||||
|
||||
/* We use this for variables, attributes, etc., so the caller only needs an
|
||||
* opaque handle to the thing below, not worrying about array management. */
|
||||
typedef struct {
|
||||
char *name; /* name of the thing */
|
||||
char *sval; /* string value */
|
||||
} Mapping_t;
|
||||
|
||||
typedef struct {
|
||||
int n_alloc; /* number of elements allocated */
|
||||
int n_used; /* number of elements used */
|
||||
int slot_incr; /* increment for allocating slots */
|
||||
int flags; /* info about this set of mappings */
|
||||
Mapping_t *maps; /* array of mappings */
|
||||
} Map_t;
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
/* Information about an entity reference. Not all fields will be used
|
||||
* at once. */
|
||||
typedef struct _ent {
|
||||
char *type; /* entity type */
|
||||
char *ename; /* entity name */
|
||||
char *nname; /* notation name */
|
||||
char *sysid; /* sys id */
|
||||
char *pubid; /* pub id */
|
||||
char *fname; /* filename */
|
||||
struct _ent *next; /* next in linked list */
|
||||
} Entity_t;
|
||||
|
||||
/* Content (child nodes) of an element (node in the tree) -- both data
|
||||
* and other elements. */
|
||||
typedef struct {
|
||||
char type; /* element, data, or pi? */
|
||||
union {
|
||||
struct _elem *elem; /* direct children of this elem */
|
||||
char *data; /* character data of this elem */
|
||||
} ch;
|
||||
} Content_t;
|
||||
|
||||
/* An element (node in the tree) */
|
||||
typedef struct _elem {
|
||||
char *gi; /* element GI */
|
||||
Content_t *cont; /* content - element & data children */
|
||||
int ncont; /* # of content/children */
|
||||
struct _elem **econt; /* element children */
|
||||
int necont; /* # of element children */
|
||||
char **dcont; /* character data children */
|
||||
int ndcont; /* # of data children */
|
||||
Mapping_t *atts; /* array of attributes */
|
||||
int natts; /* # of attributes */
|
||||
Entity_t *entity; /* ext entity & notation info */
|
||||
char *id; /* for linking */
|
||||
int index; /* an internal bookkeeping mechanism */
|
||||
int depth; /* how deep in tree */
|
||||
int lineno; /* line number */
|
||||
char *infile; /* input filename */
|
||||
int my_eorder; /* order of this elem of its parent */
|
||||
struct _elem *parent; /* this elem's direct parent */
|
||||
struct _elem *next; /* kept in linked list */
|
||||
void *trans; /* pointer to translation spec */
|
||||
/* I'm not crazy about this, but it works */
|
||||
int gen_trans[2]; /* refs to generated trans specs */
|
||||
int processed; /* was this node processed? */
|
||||
} Element_t;
|
||||
|
||||
/* For mapping of element IDs to elements themselves. */
|
||||
typedef struct id_s {
|
||||
char *id; /* ID of the element */
|
||||
Element_t *elem; /* pointer to it */
|
||||
struct id_s *next;
|
||||
} ID_t;
|
||||
|
||||
/* ----- global variable declarations ----- */
|
||||
|
||||
#ifdef STORAGE
|
||||
# define def
|
||||
#else
|
||||
# define def extern
|
||||
#endif
|
||||
|
||||
def Element_t *DocTree; /* root of document tree */
|
||||
def char **UsedElem; /* a unique list of used elem names */
|
||||
def int nUsedElem; /* number of used elem names */
|
||||
def char **UsedAtt; /* a unique list of used attrib names */
|
||||
def int nUsedAtt; /* number of used attrib names */
|
||||
def ID_t *IDList; /* list of IDs used in the doc */
|
||||
def Map_t *Variables; /* general, global variables */
|
||||
def Map_t *SDATAmap; /* SDATA mappings */
|
||||
def Map_t *PImap; /* Processing Instruction mappings */
|
||||
def Entity_t *Entities; /* list of entities */
|
||||
|
||||
def FILE *outfp; /* where output is written */
|
||||
def char *tpt_lib; /* TPT library directory */
|
||||
def int verbose; /* flag - verbose output? */
|
||||
def int warnings; /* flag - show warnings? */
|
||||
def int interactive; /* flag - interactive browsing? */
|
||||
def int slave; /* are we slave to another process? */
|
||||
def int fold_case; /* flag - fold case of GIs? */
|
||||
def Tcl_Interp *interpreter; /* interp for start_ and end_code */
|
||||
def Element_t *tclE; /* active element in Tcl call */
|
||||
|
||||
|
||||
/* ----- some macros for convenience and ease of code reading ----- */
|
||||
|
||||
/* #define stripNL(s) { char *_cp; if ((_cp=strchr(s, NL))) *_cp = EOS; } */
|
||||
#define stripNL(s) { char *_cp = s; while (*_cp) _cp++; \
|
||||
if ((_cp > s) && (*--_cp == NL)) *_cp = EOS; }
|
||||
|
||||
#define I18N_TRIGGER 0xFF
|
||||
|
||||
/* Similar to calloc(), malloc(), and realloc(), but check for success.
|
||||
* Args to all:
|
||||
* (1) number of 'elements' to allocate
|
||||
* (2) variable to point at allocated space
|
||||
* (3) type of 'element'
|
||||
* Eg: Calloc(5, e, Element_t) replaces
|
||||
* if (!(e = (Element_t *)calloc(5, sizeof(Element_t))) {
|
||||
* ... handle error ... ;
|
||||
* }
|
||||
*/
|
||||
#define Calloc(N,V,T) \
|
||||
{ if (!((V) = (T *)calloc((size_t)N, sizeof(T)))) { \
|
||||
perror("Calloc failed -- out of memory. Bailing out."); exit(1); \
|
||||
} }
|
||||
#define Malloc(N,V,T) \
|
||||
{ if (!((V) = (T *)malloc((size_t)N*sizeof(T)))) { \
|
||||
perror("Malloc failed -- out of memory. Bailing out."); exit(1); \
|
||||
} }
|
||||
#define Realloc(N,V,T) \
|
||||
{ if (!((V) = (T *)realloc(V,(size_t)N*sizeof(T)))) { \
|
||||
perror("Realloc failed -- out of memory. Bailing out."); exit(1); \
|
||||
} }
|
||||
|
||||
/* similar to strcmp(), but check first chars first, for efficiency */
|
||||
#define StrEq(s1,s2) (s1[0] == s2[0] && !strcmp(s1,s2))
|
||||
|
||||
/* similar to isspace(), but check for blank or tab - without overhead
|
||||
* of procedure call */
|
||||
#define IsWhite(c) (c == ' ' || c == TAB)
|
||||
|
||||
#define ContType(e,i) (e->cont[i].type)
|
||||
#define ContData(e,i) (e->cont[i].ch.data)
|
||||
#define ContElem(e,i) (e->cont[i].ch.elem)
|
||||
#define IsContData(e,i) (e->cont[i].type == CMD_DATA)
|
||||
#define IsContElem(e,i) (e->cont[i].type == CMD_OPEN)
|
||||
#define IsContPI(e,i) (e->cont[i].type == CMD_PI)
|
||||
|
||||
/* ----- function prototypes ----- */
|
||||
|
||||
/* things defined in util.c */
|
||||
Element_t *QRelation(Element_t *, char *, Relation_t);
|
||||
Relation_t FindRelByName(char *);
|
||||
char *FindAttValByName(Element_t *, char *);
|
||||
char *FindContext(Element_t *, int, char *);
|
||||
char *AddElemName(char *);
|
||||
char *AddAttName(char *);
|
||||
void OutputString(char *, FILE *, int);
|
||||
int Putc(int, FILE *);
|
||||
int FPuts(const char *, FILE *);
|
||||
int FFlush(FILE *);
|
||||
FILE *OpenFile(char *);
|
||||
char *FindElementPath(Element_t *, char *);
|
||||
char *NearestOlderElem(Element_t *, char *);
|
||||
void PrintLocation(Element_t *, FILE *);
|
||||
char **Split(char *, int *, int);
|
||||
void DescendTree(Element_t *, void(*)(), void(*)(), void(*)(), void *);
|
||||
Map_t *NewMap(int);
|
||||
Mapping_t *FindMapping(Map_t *, char *);
|
||||
char *FindMappingVal(Map_t *, char *);
|
||||
void SetMapping(Map_t *, char *);
|
||||
void SetMappingNV(Map_t *, char *, char *);
|
||||
void AddID(Element_t *, char *);
|
||||
Element_t *FindElemByID(char *);
|
||||
|
||||
/* things defined in translate.c */
|
||||
void DoTranslate(Element_t*, char *, FILE *);
|
||||
|
||||
/* things defined in traninit.c */
|
||||
void ReadTransSpec(char *);
|
||||
void ReadSDATA(char *);
|
||||
void ReadCharMap(char *);
|
||||
|
||||
/* things defined in info.c */
|
||||
void PrintContext(Element_t *e);
|
||||
void PrintElemSummary(Element_t *);
|
||||
void PrintElemTree(Element_t *);
|
||||
void PrintStats(Element_t *);
|
||||
void PrintIDList();
|
||||
|
||||
95
cde/programs/dtdocbook/doc2sdl/instant/hyper.c
Normal file
95
cde/programs/dtdocbook/doc2sdl/instant/hyper.c
Normal file
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Hypermedia-related facilities.
|
||||
*
|
||||
* Entry points for this module:
|
||||
* AddID(elem, idval) add elem-id pair to list of known ids
|
||||
* FindElemByID(idval) find elem by id
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid =
|
||||
"$XConsortium: hyper.c /main/3 1996/06/19 17:13:07 drk $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "general.h"
|
||||
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
void
|
||||
AddID(Element *e, char *idval)
|
||||
{
|
||||
static ID *id_last;
|
||||
if (!IDList) {
|
||||
Calloc(1, id_last, ID);
|
||||
IDList = id_last;
|
||||
}
|
||||
else {
|
||||
Calloc(1, id_last->next, ID);
|
||||
id_last = id_last->next;
|
||||
}
|
||||
id_last->elem = e;
|
||||
id_last->id = idval;
|
||||
}
|
||||
|
||||
Element *
|
||||
FindElemByID(char *idval)
|
||||
{
|
||||
ID *id;
|
||||
for (id=IDList; id; id=id->next)
|
||||
if (!strcmp(id->id, idval)) return id->elem;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
295
cde/programs/dtdocbook/doc2sdl/instant/info.c
Normal file
295
cde/programs/dtdocbook/doc2sdl/instant/info.c
Normal file
@@ -0,0 +1,295 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Functions for printing information about an instance in the 'instant'
|
||||
* program. Most of these are fairly short and simple.
|
||||
*
|
||||
* Entry points for this module:
|
||||
* PrintElemSummary(elem) print summary info of each element
|
||||
* PrintContext(elem) print context of each element
|
||||
* PrintElemTree(elem) print tree of document
|
||||
* PrintStats(elem) print statistics about doc tree
|
||||
* PrintIDList(elem) print list of IDs and element context
|
||||
* Most Print*() functions start at subtree pointed to by 'elem'.
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid =
|
||||
"$XConsortium: info.c /main/3 1996/06/19 17:13:13 drk $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "general.h"
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Print a summary of each tag use in the instance. Things like depth in
|
||||
* the tree, number of children, parent, attributes.
|
||||
*/
|
||||
|
||||
/* Do the actual printing. Print the info about the node. If null,
|
||||
* print a header for the columns.
|
||||
* Arguments:
|
||||
* Pointer to element structure of the node to print.
|
||||
*/
|
||||
static void
|
||||
print_summ(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
int i, n, dsize;
|
||||
char *hfmt="%-18.18s %4s %5s %4s %4s %s\n";
|
||||
char *fmt ="%-18.18s %4d %5d %4d %4d %s\n";
|
||||
|
||||
if (e == NULL) {
|
||||
fprintf(outfp, hfmt, "Element", "Att", "Data", "Chd", "Dep", "Parent");
|
||||
return;
|
||||
}
|
||||
for (i=0,n=0; i<e->ncont; i++) if (IsContElem(e,i)) n++;
|
||||
for (i=0,dsize=0; i<e->ncont; i++)
|
||||
if (IsContElem(e,i)) dsize += strlen(e->cont[i].ch.data);
|
||||
fprintf(outfp, fmt, e->gi, e->natts, dsize, n, e->depth,
|
||||
e->parent ? e->parent->gi : "-");
|
||||
|
||||
for (i=0; i<e->natts; i++) {
|
||||
fprintf(outfp, "%45d: %s = %s\n", i, e->atts[i].name,
|
||||
e->atts[i].sval ? e->atts[i].sval : "empty");
|
||||
}
|
||||
}
|
||||
|
||||
/* Descend the tree, calling processing routine.
|
||||
* Arguments:
|
||||
* Pointer to element structure at top of tree to traverse.
|
||||
*/
|
||||
void
|
||||
PrintElemSummary(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
print_summ(0);
|
||||
DescendTree(e, print_summ, 0, 0, 0);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Print the context of each tag in the instance (i.e. the tag with its
|
||||
* ancestors).
|
||||
*/
|
||||
|
||||
/* Do the actual printing. Print the context of the node.
|
||||
* Arguments:
|
||||
* Pointer to element structure of the node to print.
|
||||
*/
|
||||
static void
|
||||
print_context(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
char buf[LINESIZE];
|
||||
|
||||
fprintf(outfp, "%-22s %s\n", e->gi, FindContext(e, 10, buf));
|
||||
}
|
||||
|
||||
/* Descend the tree, calling processing routine.
|
||||
* Arguments:
|
||||
* Pointer to element structure at top of tree to traverse.
|
||||
*/
|
||||
void
|
||||
PrintContext(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
fprintf(outfp, "%-22s %s\n", "Element", "Context");
|
||||
fprintf(outfp, "%-22s %s\n", "---------------", "-----------");
|
||||
DescendTree(e, print_context, 0, 0, 0);
|
||||
|
||||
putc(NL, outfp);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Print tree of the instance. GI's are printed indented by their depth
|
||||
* in the tree.
|
||||
*/
|
||||
|
||||
/* Do the actual printing. Print the element name, indented the right amount.
|
||||
* Arguments:
|
||||
* Pointer to element structure of the node to print.
|
||||
*/
|
||||
static void
|
||||
print_indent(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
int i, ne, nd;
|
||||
for(i=0; i<e->depth; i++) fputs(". ", outfp);
|
||||
for(i=0,ne=0; i<e->ncont; i++) if (IsContElem(e,i)) ne++;
|
||||
for(i=0,nd=0; i<e->ncont; i++) if IsContData(e,i) nd++;
|
||||
fprintf(outfp, "%s (%d,%d)\n", e->gi, ne, nd);
|
||||
}
|
||||
|
||||
/* Descend the tree, calling processing routine.
|
||||
* Arguments:
|
||||
* Pointer to element structure at top of tree to traverse.
|
||||
*/
|
||||
void
|
||||
PrintElemTree(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
DescendTree(e, print_indent, 0, 0, 0);
|
||||
putc(NL, outfp);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Print some statistics about the instance.
|
||||
*/
|
||||
|
||||
/* Accumulate the totals for the statistics.
|
||||
* Arguments:
|
||||
* Pointer to element structure of the node to print.
|
||||
* Pointer to the total number of elements.
|
||||
* Pointer to the total amount of content data.
|
||||
* Pointer to the maximum depth of tree.
|
||||
*/
|
||||
static void
|
||||
acc_tots(
|
||||
Element_t *e,
|
||||
int *tot_el,
|
||||
int *tot_data,
|
||||
int *max_depth
|
||||
)
|
||||
{
|
||||
int i;
|
||||
for(i=0; i<e->necont; i++)
|
||||
acc_tots(e->econt[i], tot_el, tot_data, max_depth);
|
||||
for (i=0; i<e->necont; i++) (*tot_el)++;
|
||||
for (i=0; i<e->ndcont; i++) (*tot_data) += strlen(e->dcont[i]);
|
||||
if (e->depth > (*max_depth)) *max_depth = e->depth;
|
||||
}
|
||||
|
||||
/* Descend the tree (recursively), collecting the statistics.
|
||||
* Arguments:
|
||||
* Pointer to element structure of the node to print.
|
||||
* Pointer to the total number of elements.
|
||||
* Pointer to the total amount of content data.
|
||||
* Pointer to the maximum depth of tree.
|
||||
*/
|
||||
static void
|
||||
elem_usage(
|
||||
Element_t *e,
|
||||
char *name,
|
||||
int *n_used,
|
||||
int *nchars
|
||||
)
|
||||
{
|
||||
int i;
|
||||
if (!strcmp(name, e->gi)) {
|
||||
(*n_used)++;
|
||||
for (i=0; i<e->ncont; i++)
|
||||
if (IsContData(e,i)) (*nchars) += strlen(ContData(e,i));
|
||||
}
|
||||
for(i=0; i<e->necont; i++)
|
||||
elem_usage(e->econt[i], name, n_used, nchars);
|
||||
}
|
||||
|
||||
/* Descend the tree, calling processing routine.
|
||||
* Arguments:
|
||||
* Pointer to element structure at top of tree to traverse.
|
||||
*/
|
||||
void
|
||||
PrintStats(
|
||||
Element_t *top
|
||||
)
|
||||
{
|
||||
int i, n;
|
||||
int dif_el=0, tot_el=0, tot_data=0, nchars, max_depth=0;
|
||||
float pct;
|
||||
|
||||
fprintf(outfp, "%-22s %s %s\n", "Element name", "Occurrences", "Character Content");
|
||||
fprintf(outfp, "%-22s %s %s\n", "---------------", "-----------", "-----------------");
|
||||
|
||||
acc_tots(top, &tot_el, &tot_data, &max_depth);
|
||||
|
||||
for (i=0; i<nUsedElem; i++) {
|
||||
n = 0;
|
||||
nchars = 0;
|
||||
elem_usage(top, UsedElem[i], &n, &nchars);
|
||||
if (n > 0) {
|
||||
pct = 100.0 * (float)n / (float)tot_el;
|
||||
fprintf(outfp, "%-22s %4d %4.1f%% %6d %4d\n", UsedElem[i],
|
||||
n, pct, nchars, (nchars/n));
|
||||
dif_el++;
|
||||
}
|
||||
}
|
||||
|
||||
fprintf(outfp, "\nTotal of %d elements used, %d different ones.\n",
|
||||
tot_el, dif_el);
|
||||
fprintf(outfp, "Total character data: %d.\n", tot_data);
|
||||
fprintf(outfp, "Maximum element depth: %d.\n", max_depth);
|
||||
putc(NL, outfp);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Print list of: ID, GI, input file, line number, separated by colons.
|
||||
* This is better for other programs to manipulate (like for keeping a
|
||||
* database of IDs in documents) than humans to read.
|
||||
*/
|
||||
|
||||
void
|
||||
PrintIDList(void)
|
||||
{
|
||||
ID_t *id;
|
||||
Element_t *ep;
|
||||
|
||||
for (id=IDList; id; id=id->next) {
|
||||
ep = id->elem;
|
||||
fprintf(outfp, "%s:%s:%s:%d\n", id->id, ep->gi,
|
||||
ep->infile?ep->infile:"-", ep->lineno);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
952
cde/programs/dtdocbook/doc2sdl/instant/main.c
Normal file
952
cde/programs/dtdocbook/doc2sdl/instant/main.c
Normal file
@@ -0,0 +1,952 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Program to read an SGML document instance, creating any of several things:
|
||||
*
|
||||
* "translated" output for formatting applications (given a trans. spec)
|
||||
* validation report (given a appropriate trans spec)
|
||||
* tree of the document's structure
|
||||
* statistics about the element usage
|
||||
* summary of the elements used
|
||||
* context of each element used
|
||||
* IDs of each element
|
||||
*
|
||||
* A C structure is created for each element, which includes:
|
||||
* name, attributes, parent, children, content
|
||||
* The tree is descended, and the desired actions performed.
|
||||
*
|
||||
* Takes input from James Clark's "sgmls" program (v. 1.1).
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid =
|
||||
"$XConsortium: main.c /main/14 1996/11/27 11:47:17 cde-hp $";
|
||||
static char *CopyRt =
|
||||
"Copyright 1993 Open Software Foundation, Inc., Cambridge, Mass. All rights reserved.";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <memory.h>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/file.h>
|
||||
#include <dirent.h>
|
||||
#include <time.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <locale.h>
|
||||
#include <langinfo.h>
|
||||
#include "LocaleXlate.h"
|
||||
#include "XlationSvc.h"
|
||||
|
||||
|
||||
#define STORAGE
|
||||
#include "general.h"
|
||||
|
||||
/* for backwards compatibility */
|
||||
#ifndef _MAXNAMLEN
|
||||
#ifndef MAXNAMLEN
|
||||
#define _MAXNAMLEN NAME_MAX
|
||||
#else
|
||||
#define _MAXNAMLEN MAXNAMLEN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static int do_context, do_tree, do_summ, do_stats, do_validate, do_idlist;
|
||||
static char *this_prog;
|
||||
static char *in_file, *out_file;
|
||||
static char *tranfile;
|
||||
static char **cmapfile, **sdatafile;
|
||||
static char *start_id;
|
||||
static char *last_file;
|
||||
static int last_lineno;
|
||||
|
||||
/* forward references */
|
||||
static void HandleArgs(int, char *[]);
|
||||
static void Initialize1();
|
||||
static void Initialize2();
|
||||
static void ReadInstance(char *);
|
||||
static void DoHelpMessage();
|
||||
extern void Browse();
|
||||
static int TclPrintLocation(ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int argc,
|
||||
const char *argv[]);
|
||||
static int DefaultOutputString(ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int argc,
|
||||
const char *argv[]);
|
||||
char *GetOutFileBaseName();
|
||||
|
||||
char *
|
||||
GetCLocale(void)
|
||||
{
|
||||
_DtXlateDb myDb = NULL;
|
||||
char myPlatform[_DtPLATFORM_MAX_LEN+1];
|
||||
static char locale[] = "C.ISO-8859-1";
|
||||
char *newLocale;
|
||||
int execVer;
|
||||
int compVer;
|
||||
int ret;
|
||||
|
||||
if ((_DtLcxOpenAllDbs(&myDb) != 0)) {
|
||||
fprintf(stderr,
|
||||
"Warning: could not open databases.\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
ret = _DtXlateGetXlateEnv(myDb,myPlatform,&execVer,&compVer);
|
||||
if (ret != 0) {
|
||||
fprintf(stderr,
|
||||
"Fatal: could not open locale translation database. %d\n", ret);
|
||||
|
||||
exit(1);
|
||||
}
|
||||
|
||||
if (_DtLcxXlateStdToOp(myDb,
|
||||
myPlatform,
|
||||
execVer,
|
||||
DtLCX_OPER_SETLOCALE,
|
||||
locale,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&newLocale)) {
|
||||
fprintf(stderr,
|
||||
"Warning: could not translate C.ISO-8859-1 to local locale\n");
|
||||
}
|
||||
|
||||
_DtLcxCloseDb(&myDb);
|
||||
|
||||
return newLocale;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Program entry point. Look at args, read instance, dispatch to the
|
||||
* correct routines to do the work, and finish.
|
||||
*/
|
||||
int
|
||||
main(
|
||||
int ac,
|
||||
char *av[]
|
||||
)
|
||||
{
|
||||
char **thisopt;
|
||||
Initialize1(av[0]);
|
||||
HandleArgs(ac, av);
|
||||
Initialize2();
|
||||
|
||||
/* use the current locale for all text but use American English ... */
|
||||
setlocale(LC_ALL, "");
|
||||
|
||||
/* ... in expressions (e.g., leave "." as the radix operator) */
|
||||
setlocale(LC_NUMERIC, GetCLocale());
|
||||
|
||||
/* Create a Tcl interpreter. */
|
||||
interpreter = Tcl_CreateInterp();
|
||||
|
||||
/* Add our output string routine as the default output string routine. */
|
||||
Tcl_CreateCommand(interpreter,
|
||||
"OutputString",
|
||||
DefaultOutputString,
|
||||
0,
|
||||
0);
|
||||
|
||||
/* Add a hook so the interpreter can print the location in the
|
||||
* source file for user errors */
|
||||
Tcl_CreateCommand(interpreter,
|
||||
"PrintLocation",
|
||||
TclPrintLocation,
|
||||
0,
|
||||
0);
|
||||
|
||||
ReadInstance(in_file);
|
||||
|
||||
if (interactive) {
|
||||
Browse(); /* this will handle interactive commands */
|
||||
}
|
||||
else {
|
||||
/* Perform tasks based on command line flags... */
|
||||
if (tranfile) {
|
||||
Element_t *e;
|
||||
/* If user wants to start at a particular ID, point to that
|
||||
* element. Else, point to the top of the tree. */
|
||||
if (start_id) {
|
||||
if (!(e=FindElemByID(start_id))) {
|
||||
fprintf(stderr, "Error: Can not find element with ID %s\n",
|
||||
start_id);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else e = DocTree;
|
||||
if (sdatafile)
|
||||
{
|
||||
thisopt = sdatafile;
|
||||
while (*thisopt)
|
||||
{
|
||||
ReadSDATA(*thisopt);
|
||||
free(*thisopt++);
|
||||
}
|
||||
free(sdatafile);
|
||||
}
|
||||
if (cmapfile)
|
||||
{
|
||||
thisopt = cmapfile;
|
||||
while (*thisopt)
|
||||
{
|
||||
ReadCharMap(*thisopt);
|
||||
free(*thisopt++);
|
||||
}
|
||||
free(cmapfile);
|
||||
}
|
||||
DoTranslate(e, tranfile, outfp);
|
||||
}
|
||||
if (do_summ) PrintElemSummary(DocTree);
|
||||
if (do_tree) PrintElemTree(DocTree);
|
||||
if (do_stats) PrintStats(DocTree);
|
||||
if (do_context) PrintContext(DocTree);
|
||||
if (do_idlist) PrintIDList();
|
||||
}
|
||||
if (out_file && outfp) fclose(outfp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int DefaultOutputString(ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int argc,
|
||||
const char *argv[])
|
||||
{
|
||||
char *string = NULL, *pString = NULL;
|
||||
const char *pArgv = NULL;
|
||||
int retCode = 0, stringLength = 0;
|
||||
|
||||
if (argc < 2) {
|
||||
Tcl_SetResult(interpreter, "Missing string to output", TCL_VOLATILE);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
if (argc > 2) {
|
||||
Tcl_SetResult(interpreter, "Too many arguments", TCL_VOLATILE);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
/* leave room for worst case expansion plus quotes plus null */
|
||||
pArgv = argv[1];
|
||||
stringLength = (4 * strlen(pArgv)) + 3;
|
||||
|
||||
string = Tcl_Alloc(stringLength);
|
||||
memset(string, 0, stringLength);
|
||||
pString = string;
|
||||
|
||||
|
||||
/* wrap the string in quotes and copy argv[1] over escaping
|
||||
* any characters that will throw Tcl for a loop */
|
||||
*pString++ = '"';
|
||||
while (*pArgv) {
|
||||
switch (*pArgv) {
|
||||
case '{':
|
||||
case '}':
|
||||
case '"':
|
||||
case '\'':
|
||||
case '[':
|
||||
case ']':
|
||||
case '$':
|
||||
case '\\':
|
||||
*pString++ = '\\';
|
||||
}
|
||||
*pString++ = *pArgv++;
|
||||
}
|
||||
*pString++ = '"';
|
||||
*pString++ = 0;
|
||||
|
||||
/* put the string to the output */
|
||||
retCode = Tcl_VarEval(interpreter, "puts -nonewline ", string,
|
||||
(char *)NULL);
|
||||
#if 0
|
||||
/* JET*/
|
||||
if (retCode != TCL_OK)
|
||||
{
|
||||
fprintf(stderr, "JET: retCode = %d, LEN = %d STRING = '%s'\n",
|
||||
retCode, strlen(string), string);
|
||||
fprintf(stderr, "\tstring[1] = 0x%02x\n", string[1]);
|
||||
}
|
||||
#endif
|
||||
Tcl_Free(string);
|
||||
|
||||
/* and ripple up any error code we got from the "puts" */
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static int TclPrintLocation(ClientData clientData,
|
||||
Tcl_Interp *interp,
|
||||
int argc,
|
||||
const char *argv[])
|
||||
{
|
||||
if (argc > 1) {
|
||||
Tcl_SetResult(interpreter, "Too many arguments", TCL_VOLATILE);
|
||||
return TCL_ERROR;
|
||||
}
|
||||
|
||||
PrintLocation(tclE, stderr);
|
||||
|
||||
return TCL_OK;
|
||||
}
|
||||
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Initialization stuff done before dealing with args.
|
||||
* Arguments:
|
||||
* Name of program (string).
|
||||
*/
|
||||
|
||||
static void
|
||||
Initialize1(
|
||||
char *myname
|
||||
)
|
||||
{
|
||||
time_t tnow;
|
||||
struct tm *nowtm;
|
||||
char *cp, buf[100];
|
||||
#if HPUX
|
||||
extern int gethostname(char *, int); /* not in a system .h file... */
|
||||
#endif
|
||||
|
||||
/* where we try to find data/library files */
|
||||
if (!(tpt_lib=getenv(TPT_LIB))) tpt_lib = DEF_TPT_LIB;
|
||||
|
||||
/* set some global variables */
|
||||
warnings = 1;
|
||||
fold_case = 1;
|
||||
this_prog = myname;
|
||||
|
||||
/* setup global variable mapping */
|
||||
Variables = NewMap(IMS_variables);
|
||||
|
||||
/* set some pre-defined variables */
|
||||
SetMappingNV(Variables, "user", (cp=getenv("USER")) ? cp : "UnknownUser" );
|
||||
time(&tnow);
|
||||
nowtm = localtime(&tnow);
|
||||
strftime(buf, 100, "%a %d %b %Y, %R", nowtm);
|
||||
SetMappingNV(Variables, "date", buf);
|
||||
#if HPUX
|
||||
if (gethostname(buf, 100) < 0) strcpy(buf, "unknown-host");
|
||||
#else
|
||||
strcpy(buf, "unknown-host");
|
||||
#endif
|
||||
SetMappingNV(Variables, "host", buf);
|
||||
SetMappingNV(Variables, "transpec", tranfile ? tranfile : "??");
|
||||
}
|
||||
|
||||
/* Initialization stuff done after dealing with args. */
|
||||
|
||||
static void
|
||||
Initialize2(void)
|
||||
{
|
||||
SetMappingNV(Variables, "transpec", tranfile ? tranfile : "??");
|
||||
|
||||
/* If the user wants to send output to a file, reopen stdout as
|
||||
* the file. The interpreter will write its output by default to
|
||||
* stdout so the reopen makes sure the output goes to the desired
|
||||
* named file. */
|
||||
if (do_validate)
|
||||
out_file = "/dev/null"; /* toss all but error output */
|
||||
|
||||
if (!out_file) {
|
||||
out_file = "out.sdl";
|
||||
}
|
||||
|
||||
if (!(outfp = freopen(out_file, "w", stdout))) {
|
||||
fprintf(stderr,
|
||||
"Could not re-open output '%s' file for writing.\n%s",
|
||||
out_file,
|
||||
strerror(errno));
|
||||
exit(1);
|
||||
}
|
||||
SetMappingNV(Variables, "basename", GetOutFileBaseName());
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Get the base name of the output file (for transpec "basename" command)
|
||||
* Arguments:
|
||||
*
|
||||
*/
|
||||
char *GetOutFileBaseName(void)
|
||||
{
|
||||
char *prefix, *suffix, *cp;
|
||||
static char nameBuf[_MAXNAMLEN+1] = "";
|
||||
|
||||
prefix = strchr(out_file, '/');
|
||||
if (!prefix)
|
||||
prefix = out_file;
|
||||
else
|
||||
prefix++;
|
||||
|
||||
suffix = strrchr(prefix, '.');
|
||||
if (!suffix)
|
||||
suffix = prefix + strlen(prefix);
|
||||
|
||||
if (!*(cp = nameBuf)) {
|
||||
while (prefix != suffix) {
|
||||
*cp++ = *prefix++;
|
||||
}
|
||||
*cp = 0;
|
||||
}
|
||||
return nameBuf;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Set a variable. If it is one of the "known" variables, set the
|
||||
* variable in the C code (this program).
|
||||
* Arguments:
|
||||
* Variable name/value string - separated by an '=' (eg, "myname=Sally").
|
||||
*/
|
||||
static void
|
||||
CmdLineSetVariable(
|
||||
char *var
|
||||
)
|
||||
{
|
||||
char *cp, buf[100], **tok;
|
||||
int n;
|
||||
|
||||
/* Turn '=' into a space, to isolate the name. Then set variable. */
|
||||
snprintf(buf, sizeof(buf), "%s", var);
|
||||
if ((cp=strchr(buf, '='))) {
|
||||
/* we have "var=value" */
|
||||
*cp = ' ';
|
||||
n = 2;
|
||||
tok = Split(buf, &n, 0);
|
||||
/* see if variable name matches one of our internal ones */
|
||||
if (!strcmp(tok[0], "verbose")) verbose = atoi(tok[1]);
|
||||
else if (!strcmp(tok[0], "warnings")) warnings = atoi(tok[1]);
|
||||
else if (!strcmp(tok[0], "foldcase")) fold_case = atoi(tok[1]);
|
||||
else SetMappingNV(Variables, tok[0], tok[1]);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Expected an '=' in variable assignment: %s. Ignored\n",
|
||||
var);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Bounce through arguments, setting variables and flags.
|
||||
* Arguments:
|
||||
* Argc and Argv, as passed to main().
|
||||
*/
|
||||
static void
|
||||
HandleArgs(
|
||||
int ac,
|
||||
char *av[]
|
||||
)
|
||||
{
|
||||
int c, errflag=0;
|
||||
extern char *optarg;
|
||||
extern int optind;
|
||||
char **thisopt;
|
||||
int count;
|
||||
|
||||
while ((c=getopt(ac, av, "t:vc:s:o:huSxIl:bHVWi:D:Z")) != EOF) {
|
||||
switch (c) {
|
||||
case 't': tranfile = optarg; break;
|
||||
case 'v': do_validate = 1; break;
|
||||
case 's':
|
||||
{
|
||||
if (thisopt = sdatafile)
|
||||
{
|
||||
count = 0;
|
||||
while (*thisopt++)
|
||||
count++;
|
||||
sdatafile = (char **)
|
||||
realloc(sdatafile, (count+2)*sizeof(char *));
|
||||
sdatafile[count+1] = 0;
|
||||
thisopt = sdatafile + count;
|
||||
}
|
||||
else
|
||||
{
|
||||
sdatafile = (char **) calloc(2, sizeof(char *));
|
||||
thisopt = sdatafile;
|
||||
}
|
||||
*thisopt = strdup(optarg);
|
||||
break;
|
||||
}
|
||||
case 'c':
|
||||
{
|
||||
if (thisopt = cmapfile)
|
||||
{
|
||||
count = 0;
|
||||
while (*thisopt++)
|
||||
count++;
|
||||
cmapfile = (char **)
|
||||
realloc(cmapfile, (count+2)*sizeof(char *));
|
||||
cmapfile[count+1] = 0;
|
||||
thisopt = cmapfile + count;
|
||||
}
|
||||
else
|
||||
{
|
||||
cmapfile = (char **) calloc(2, sizeof(char *));
|
||||
thisopt = cmapfile;
|
||||
}
|
||||
*thisopt = strdup(optarg);
|
||||
break;
|
||||
}
|
||||
case 'h': do_tree = 1; break;
|
||||
case 'u': do_summ = 1; break;
|
||||
case 'S': do_stats = 1; break;
|
||||
case 'x': do_context = 1; break;
|
||||
case 'I': do_idlist = 1; break;
|
||||
case 'l': tpt_lib = optarg; break;
|
||||
case 'i': start_id = optarg; break;
|
||||
case 'o': out_file = optarg; break;
|
||||
case 'b': interactive = 1; break;
|
||||
case 'W': warnings = 0; break;
|
||||
case 'V': verbose = 1; break;
|
||||
case 'Z': slave = 1; break;
|
||||
case 'H': DoHelpMessage(); exit(0); break;
|
||||
case 'D': CmdLineSetVariable(optarg); break;
|
||||
case '?': errflag = 1; break;
|
||||
}
|
||||
if (errflag) {
|
||||
fprintf(stderr, "Try '%s -H' for help.\n", this_prog);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* input (ESIS) file name */
|
||||
if (optind < ac) in_file = av[optind];
|
||||
|
||||
/* If doing interactive/browsing, we can't take ESIS from stdin. */
|
||||
if (interactive && !in_file) {
|
||||
fprintf(stderr,
|
||||
"You must specify ESIS file on cmd line for browser mode.\n");
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Simply print out a help/usage message.
|
||||
*/
|
||||
|
||||
static char *help_msg[] = {
|
||||
"",
|
||||
" -t file Print translated output using translation spec in <file>",
|
||||
" -s file <file> contains a list of character mappings",
|
||||
" -c file <file> contains a list of character mappings",
|
||||
" -v Validate using translation spec specified with -t",
|
||||
" -i id Consider only subtree starting at element with ID <id>",
|
||||
" -b Interactive browser",
|
||||
" -S Print statistics (how often elements occur, etc.)",
|
||||
" -u Print element usage summary (# of children, depth, etc.)",
|
||||
" -x Print context of each element",
|
||||
" -h Print document hierarchy as a tree",
|
||||
" -o file Write output to <file>. Default is standard output.",
|
||||
" -l dir Set library directory to <dir>. (or env. variable TPT_LIB)",
|
||||
" -I List all IDs used in the instance",
|
||||
" -W Do not print warning messages",
|
||||
" -H Print this help message",
|
||||
" -Dvar=val Set variable 'var' to value 'val'",
|
||||
" file Take input from named file. If not specified, assume stdin.",
|
||||
" File should be output from the 'sgmls' program (ESIS).",
|
||||
NULL
|
||||
};
|
||||
|
||||
static void
|
||||
DoHelpMessage(void)
|
||||
{
|
||||
char **s = help_msg;
|
||||
printf("usage: %s [option ...] [file]", this_prog);
|
||||
while (*s) puts(*s++);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Remember an external entity for future reference.
|
||||
* Arguments:
|
||||
* Pointer to entity structure to remember.
|
||||
*/
|
||||
|
||||
static void
|
||||
AddEntity(
|
||||
Entity_t *ent
|
||||
)
|
||||
{
|
||||
static Entity_t *last_ent;
|
||||
|
||||
if (!Entities) {
|
||||
Malloc(1, Entities, Entity_t);
|
||||
last_ent = Entities;
|
||||
}
|
||||
else {
|
||||
Malloc(1, last_ent->next, Entity_t);
|
||||
last_ent = last_ent->next;
|
||||
}
|
||||
*last_ent = *ent;
|
||||
|
||||
}
|
||||
|
||||
/* Find an entity, given its entity name.
|
||||
* Arguments:
|
||||
* Name of entity to retrieve.
|
||||
*/
|
||||
static Entity_t *
|
||||
FindEntity(
|
||||
char *ename
|
||||
)
|
||||
{
|
||||
Entity_t *n;
|
||||
for (n=Entities; n; n=n->next)
|
||||
if (StrEq(ename, n->ename)) return n;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Accumulate lines up to the open tag. Attributes, line number,
|
||||
* entity info, notation info, etc., all come before the open tag.
|
||||
*/
|
||||
static Element_t *
|
||||
AccumElemInfo(
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
char buf[LINESIZE+1];
|
||||
int c;
|
||||
int i, na;
|
||||
char *cp, *atval;
|
||||
Mapping_t a[100];
|
||||
Element_t *e;
|
||||
Entity_t ent, *ent2;
|
||||
char **tok;
|
||||
static int Index=0;
|
||||
static Element_t *last_e;
|
||||
|
||||
|
||||
Calloc(1, e, Element_t);
|
||||
memset(&ent, 0, sizeof ent); /* clean space for entity info */
|
||||
|
||||
/* Also, keep a linked list of elements, so we can easily scan through */
|
||||
if (last_e) last_e->next = e;
|
||||
last_e = e;
|
||||
|
||||
e->index = Index++; /* just a unique number for identification */
|
||||
|
||||
/* in case these are not set for this element in the ESIS */
|
||||
e->lineno = last_lineno;
|
||||
e->infile = last_file;
|
||||
|
||||
na = 0;
|
||||
while (1) {
|
||||
if ((c = getc(fp)) == EOF) break;
|
||||
fgets(buf, LINESIZE, fp);
|
||||
stripNL(buf);
|
||||
switch (c) {
|
||||
case EOF: /* End of input */
|
||||
fprintf(stderr, "Error: Unexpectedly reached end of ESIS.\n");
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case CMD_OPEN: /* (gi */
|
||||
e->gi = AddElemName(buf);
|
||||
if (na > 0) {
|
||||
Malloc(na, e->atts, Mapping_t);
|
||||
memcpy(e->atts, a, na*sizeof(Mapping_t));
|
||||
e->natts = na;
|
||||
na = 0;
|
||||
}
|
||||
/* Check if this elem has a notation attr. If yes, and there
|
||||
is no notation specified, recall the previous one. (feature
|
||||
of sgmls - it does not repeat notation stuff if we the same
|
||||
is used twice in a row) */
|
||||
if ((atval=FindAttValByName(e, "ENTITYREF")) && /* HACK */
|
||||
(ent2=FindEntity(atval))) {
|
||||
e->entity = ent2;
|
||||
}
|
||||
|
||||
return e;
|
||||
break;
|
||||
|
||||
case CMD_ATT: /* Aname val */
|
||||
i = 3;
|
||||
tok = Split(buf, &i, 0);
|
||||
if (!strcmp(tok[1], "IMPLIED")) break; /* skip IMPLIED atts. */
|
||||
if (!strcmp(tok[1], "CDATA") || !strcmp(tok[1], "TOKEN") ||
|
||||
!strcmp(tok[1], "ENTITY") ||!strcmp(tok[1], "NOTATION"))
|
||||
{
|
||||
a[na].name = AddAttName(tok[0]);
|
||||
a[na].sval = AddAttName(tok[2]);
|
||||
na++;
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Error: Bad attr line (%d): A%s %s...\n",
|
||||
e->lineno, tok[0], tok[1]);
|
||||
}
|
||||
break;
|
||||
|
||||
case CMD_LINE: /* Llineno */
|
||||
/* These lines come in 2 forms: "L123" and "L123 file.sgml".
|
||||
* Filename is given only at 1st occurrence. Remember it.
|
||||
*/
|
||||
if ((cp = strchr(buf, ' '))) {
|
||||
cp++;
|
||||
last_file = strdup(cp);
|
||||
}
|
||||
last_lineno = e->lineno = atoi(buf);
|
||||
e->infile = last_file;
|
||||
break;
|
||||
|
||||
case CMD_DATA: /* -data */
|
||||
fprintf(stderr, "Error: Data in AccumElemInfo, line %d:\n%c%s\n",
|
||||
e->lineno, c,buf);
|
||||
/*return e;*/
|
||||
exit(1);
|
||||
break;
|
||||
|
||||
case CMD_D_ATT: /* Dename name val */
|
||||
|
||||
case CMD_NOTATION: /* Nnname */
|
||||
break;
|
||||
|
||||
case CMD_EXT_ENT: /* Eename typ nname */
|
||||
i = 3;
|
||||
tok = Split(buf, &i, 0);
|
||||
ent.ename = strdup(tok[0]);
|
||||
ent.type = strdup(tok[1]);
|
||||
ent.nname = strdup(tok[2]);
|
||||
AddEntity(&ent);
|
||||
break;
|
||||
case CMD_INT_ENT: /* Iename typ text */
|
||||
fprintf(stderr, "Error: Got CMD_INT_ENT in AccumElemInfo: %s\n", buf);
|
||||
break;
|
||||
case CMD_SYSID: /* ssysid */
|
||||
ent.sysid = strdup(buf);
|
||||
break;
|
||||
case CMD_PUBID: /* ppubid */
|
||||
ent.pubid = strdup(buf);
|
||||
break;
|
||||
case CMD_FILENAME: /* ffilename */
|
||||
ent.fname = strdup(buf);
|
||||
break;
|
||||
|
||||
case CMD_CLOSE: /* )gi */
|
||||
case CMD_PI: /* ?pi */
|
||||
case CMD_SUBDOC: /* Sename */
|
||||
case CMD_SUBDOC_S: /* {ename */
|
||||
case CMD_SUBDOC_E: /* }ename */
|
||||
case CMD_EXT_REF: /* &name */
|
||||
case CMD_APPINFO: /* #text */
|
||||
case CMD_CONFORM: /* C */
|
||||
default:
|
||||
fprintf(stderr, "Error: Unexpected input in AccumElemInfo, %d:\n%c%s\n",
|
||||
e->lineno, c,buf);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Error: End of AccumElemInfo - should not be here: %s\n",
|
||||
e->gi);
|
||||
/* return e;*/
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* Read ESIS lines.
|
||||
* Limitation? Max 5000 children per node. (done for efficiency --
|
||||
* should do some malloc and bookkeeping games later).
|
||||
*/
|
||||
|
||||
static Element_t *
|
||||
ReadESIS(
|
||||
FILE *fp,
|
||||
int depth
|
||||
)
|
||||
{
|
||||
char *buf;
|
||||
int i, c, ncont;
|
||||
Element_t *e;
|
||||
Content_t cont[5000] = {0};
|
||||
|
||||
Malloc( LINESIZE+1, buf, char );
|
||||
|
||||
/* Read input stream - the output of "sgmls", called "ESIS". */
|
||||
e = AccumElemInfo(fp);
|
||||
e->depth = depth;
|
||||
|
||||
ncont = 0;
|
||||
while (1) {
|
||||
if ((c = getc(fp)) == EOF) break;
|
||||
switch (c) {
|
||||
case EOF: /* End of input */
|
||||
break;
|
||||
|
||||
case CMD_DATA: /* -data */
|
||||
fgets(buf, LINESIZE, fp);
|
||||
stripNL(buf);
|
||||
cont[ncont].ch.data = strdup(buf);
|
||||
cont[ncont].type = CMD_DATA;
|
||||
ncont++;
|
||||
break;
|
||||
|
||||
case CMD_PI: /* ?pi */
|
||||
fgets(buf, LINESIZE, fp);
|
||||
stripNL(buf);
|
||||
cont[ncont].type = CMD_PI;
|
||||
cont[ncont].ch.data = strdup(buf);
|
||||
ncont++;
|
||||
break;
|
||||
|
||||
case CMD_CLOSE: /* )gi */
|
||||
fgets(buf, LINESIZE, fp);
|
||||
stripNL(buf);
|
||||
if (ncont) {
|
||||
e->ncont = ncont;
|
||||
Malloc(ncont, e->cont, Content_t);
|
||||
for (i=0; i<ncont; i++) e->cont[i] = cont[i];
|
||||
}
|
||||
free(buf);
|
||||
return e;
|
||||
break;
|
||||
|
||||
case CMD_OPEN: /* (gi */
|
||||
/*fprintf(stderr, "+++++ OPEN +++\n");*/
|
||||
/* break;*/
|
||||
|
||||
case CMD_ATT: /* Aname val */
|
||||
case CMD_D_ATT: /* Dename name val */
|
||||
case CMD_NOTATION: /* Nnname */
|
||||
case CMD_EXT_ENT: /* Eename typ nname */
|
||||
case CMD_INT_ENT: /* Iename typ text */
|
||||
case CMD_SYSID: /* ssysid */
|
||||
case CMD_PUBID: /* ppubid */
|
||||
case CMD_FILENAME: /* ffilename */
|
||||
ungetc(c, fp);
|
||||
cont[ncont].ch.elem = ReadESIS(fp, depth+1);
|
||||
cont[ncont].type = CMD_OPEN;
|
||||
cont[ncont].ch.elem->parent = e;
|
||||
ncont++;
|
||||
break;
|
||||
|
||||
case CMD_LINE: /* Llineno */
|
||||
fgets(buf, LINESIZE, fp);
|
||||
break; /* ignore these here */
|
||||
|
||||
case CMD_SUBDOC: /* Sename */
|
||||
case CMD_SUBDOC_S: /* {ename */
|
||||
case CMD_SUBDOC_E: /* }ename */
|
||||
case CMD_EXT_REF: /* &name */
|
||||
case CMD_APPINFO: /* #text */
|
||||
case CMD_CONFORM: /* C */
|
||||
default:
|
||||
fgets(buf, LINESIZE, fp);
|
||||
fprintf(stderr, "Error: Unexpected input at %d: '%c%s'\n",
|
||||
e->lineno, c, buf);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Error: End of ReadESIS - should not be here: %s\n", e->gi);
|
||||
free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Read input stream, creating a tree in memory of the elements and data.
|
||||
* Arguments:
|
||||
* Filename where instance's ESIS is.
|
||||
*/
|
||||
static void
|
||||
ReadInstance(
|
||||
char *filename
|
||||
)
|
||||
{
|
||||
int i, n;
|
||||
FILE *fp;
|
||||
Element_t *e;
|
||||
char *idatt;
|
||||
|
||||
if (filename) { /* if we specified input file. else stdin */
|
||||
if ((fp=fopen(filename, "r")) == NULL) {
|
||||
perror(filename);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
else fp = stdin;
|
||||
last_file = filename;
|
||||
DocTree = ReadESIS(fp, 0);
|
||||
if (filename) fclose(fp);
|
||||
|
||||
/* Traverse tree, filling in econt and figuring out which child
|
||||
* (ie. what birth order) each element is. */
|
||||
DocTree->my_eorder = -1;
|
||||
for (e=DocTree; e; e=e->next) {
|
||||
|
||||
/* count element children */
|
||||
for (i=0,n=0; i<e->ncont; i++) if (IsContElem(e,i)) n++;
|
||||
if (n > 0) Calloc(n, e->econt, Element_t *);
|
||||
for (i=0; i<e->ncont; i++)
|
||||
if (IsContElem(e,i)) e->econt[e->necont++] = ContElem(e,i);
|
||||
|
||||
/* count data children */
|
||||
for (i=0,n=0; i<e->ncont; i++) if (IsContData(e,i)) n++;
|
||||
if (n > 0) Calloc(n, e->dcont, char *);
|
||||
for (i=0; i<e->ncont; i++)
|
||||
if (IsContData(e,i)) e->dcont[e->ndcont++] = ContData(e,i);
|
||||
|
||||
/* where in child order order */
|
||||
for (i=0; i<e->necont; i++)
|
||||
e->econt[i]->my_eorder = i;
|
||||
|
||||
/* Does this element have an ID? */
|
||||
for (i=0; i<e->natts; i++) {
|
||||
if ((idatt=FindAttValByName(e, "ID"))) {
|
||||
AddID(e, idatt);
|
||||
/* remember ID value for quick reference */
|
||||
e->id = idatt;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
43
cde/programs/dtdocbook/doc2sdl/instant/sgmls.notes
Normal file
43
cde/programs/dtdocbook/doc2sdl/instant/sgmls.notes
Normal file
@@ -0,0 +1,43 @@
|
||||
#
|
||||
# Copyright (c) 1994
|
||||
# Open Software Foundation, Inc.
|
||||
#
|
||||
# Permission is hereby granted to use, copy, modify and freely distribute
|
||||
# the software in this file and its documentation for any purpose without
|
||||
# fee, provided that the above copyright notice appears in all copies and
|
||||
# that both the copyright notice and this permission notice appear in
|
||||
# supporting documentation. Further, provided that the name of Open
|
||||
# Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
# publicity pertaining to distribution of the software without prior
|
||||
# written permission from OSF. OSF makes no representations about the
|
||||
# suitability of this software for any purpose. It is provided "as is"
|
||||
# without express or implied warranty.
|
||||
#
|
||||
|
||||
These are what sgmls feeds us (from the sgmls manpage):
|
||||
|
||||
Commands (the command is the 1st char):
|
||||
(gi start of element gi
|
||||
)gi end of element gi
|
||||
-data data
|
||||
&name ref to external data entity
|
||||
?pi processing instruction
|
||||
Aname val attr name and value
|
||||
Dename name val same as A, except external entity ename
|
||||
Nnname sysid pubid def notation nname, ass w/ sysid,pubid
|
||||
Eename typ nname filename def external data entity ename
|
||||
Iename text def internal data entity ename
|
||||
Sename filename... def subdoc entity
|
||||
{ename start of SGML subdocument entity
|
||||
}ename end of SGML subdocument entity
|
||||
Llineno [file] set current line number, filename
|
||||
|
||||
And attributes values can have the form:
|
||||
IMPLIED
|
||||
CDATA data
|
||||
TOKEN token
|
||||
NOTATION nname
|
||||
ENTITY name...
|
||||
ID id
|
||||
IDREF id...
|
||||
|
||||
975
cde/programs/dtdocbook/doc2sdl/instant/tables.c
Normal file
975
cde/programs/dtdocbook/doc2sdl/instant/tables.c
Normal file
@@ -0,0 +1,975 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Program to manipulate SGML instances.
|
||||
*
|
||||
* This module is for handling OSF table markup, printing TeX or tbl
|
||||
* (tbl) markup to the output stream. Also, table markup checking is
|
||||
* done here. Yes, this depends on the DTD, but it makes translation
|
||||
* specs much cleaner (and makes some things possible.
|
||||
*
|
||||
* Incomplete / not implemented / limitations / notes:
|
||||
* vertical alignment (valign attr)
|
||||
* vertical spanning
|
||||
* 'wrap hint' attribute
|
||||
* row separators are for the whole line, not per cell (the prog looks
|
||||
* at rowsep for the 1st cell and applies it to the whole row)
|
||||
* trusts that units if colwidths are acceptable to LaTeX and tbl
|
||||
* "s" is an acceptable shorthand for "span" in model attributes
|
||||
*
|
||||
* A note on use of OutputString(): Strings with backslashes (\) need lots
|
||||
* of backslashes. You have to escape them for the C compiler, and escape
|
||||
* them again for OutputString() itself.
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid =
|
||||
"$XConsortium: tables.c /main/3 1996/06/19 17:13:17 drk $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "general.h"
|
||||
#include "translate.h"
|
||||
|
||||
/* text width of page, in inches */
|
||||
#define TEXTWIDTH 6.0
|
||||
#define MAXCOLS 100
|
||||
#define SPAN_NOT 0
|
||||
#define SPAN_START 1
|
||||
#define SPAN_CONT 2
|
||||
|
||||
/* these cover the attributes on the table element */
|
||||
typedef struct {
|
||||
char *ncols;
|
||||
char *halign, **halign_v;
|
||||
char *model, **model_v;
|
||||
char *colwidth, **colwidth_v;
|
||||
char *colsep, **colsep_v;
|
||||
char *colweight, **colweight_v;
|
||||
char *frame;
|
||||
int n_halign, n_model, n_colwidth, n_colsep, n_colweight;
|
||||
int repeathead;
|
||||
int nc;
|
||||
} TableInfo;
|
||||
|
||||
|
||||
/* some flags, set when the table tag is processed, used later */
|
||||
static int rowsep, siderules;
|
||||
static int frametop, framebot, frameall;
|
||||
static char basemodel[128]; /* model for table (in formatting language) */
|
||||
static int spaninfo[MAXCOLS]; /* 100 columns, max */
|
||||
static TableInfo TheTab;
|
||||
|
||||
/* forward references */
|
||||
void SetTabAtts(Element_t *, TableInfo *, int);
|
||||
void FreeTabAtts(TableInfo *);
|
||||
void CheckTable(Element_t *);
|
||||
void TblTable(Element_t *, FILE *);
|
||||
void TblTableCellStart(Element_t *, FILE *);
|
||||
void TblTableCellEnd(Element_t *, FILE *);
|
||||
void TblTableRowStart(Element_t *, FILE *);
|
||||
void TblTableRowEnd(Element_t *, FILE *);
|
||||
void TblTableTop(Element_t *, FILE *);
|
||||
void TblTableBottom(Element_t *, FILE *);
|
||||
void TexTable(Element_t *, FILE *);
|
||||
void TexTableCellStart(Element_t *, FILE *);
|
||||
void TexTableCellEnd(Element_t *, FILE *);
|
||||
void TexTableRowStart(Element_t *, FILE *);
|
||||
void TexTableRowEnd(Element_t *, FILE *);
|
||||
void TexTableTop(Element_t *, FILE *);
|
||||
void TexTableBottom(Element_t *, FILE *);
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Hard-coded stuff for OSF DTD tables.
|
||||
* Here are the TABLE attributes (for handy reference):
|
||||
* ncols NUMBER num of cells/row should match
|
||||
* model CDATA column prototypes for this table
|
||||
* colwidth NUTOKENS absolute widths of cols
|
||||
* colweight NUMBERS column weights
|
||||
* halign CDATA horiz alignment for columns
|
||||
* valign CDATA vertical alignment for columns
|
||||
* colsep NUMBERS use col separators (lines)?
|
||||
* rowsep NUMBERS use row separators (lines)?
|
||||
* wrap NUMBERS wrap hints for columns
|
||||
* repeathead NUMBER carry title rows to other pages
|
||||
* frame (top|bottom|topbot|all|sides|none) frame style
|
||||
*
|
||||
* The 'wrap' attribute is never used.
|
||||
*
|
||||
* Usage in transpec: _osftable [tex|tbl|check] ['aspect']
|
||||
* where 'aspect' is:
|
||||
* rowstart stuff to do at start of a row (tests for spanning)
|
||||
* rowend stuff to do at end of a row (eg, rules, etc.)
|
||||
* cellstart stuff to do at start of a cell (eg, handle actual
|
||||
* spanning instructions, etc.)
|
||||
* cellend stuff to do at end of a cell (eg, cell separator)
|
||||
* top stuff to do at top of the table
|
||||
* (like whether or not it needs a starting horiz rule)
|
||||
* bottom stuff to do at bottom of the table
|
||||
* (like whether or not it needs an ending horiz rule)
|
||||
* (nothing) the 'cols' param to LaTeX's \begin{tabular}[pos]{cols}
|
||||
* or 'options' and 'formats' part in tbl
|
||||
*/
|
||||
|
||||
/* Procedure to
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
* Vector of args to _osftable
|
||||
* Count of args to _osftable
|
||||
*/
|
||||
void
|
||||
OSFtable(
|
||||
Element_t *e,
|
||||
FILE *fp,
|
||||
char **av,
|
||||
int ac
|
||||
)
|
||||
{
|
||||
/* Check params and dispatch to appropriate routine */
|
||||
|
||||
if (ac > 1 && !strcmp(av[1], "check")) CheckTable(e);
|
||||
|
||||
else if (!strcmp(av[1], "tbl")) {
|
||||
if (ac > 2) {
|
||||
if (!strcmp(av[2], "cellstart")) TblTableCellStart(e, fp);
|
||||
else if (!strcmp(av[2], "cellend")) TblTableCellEnd(e, fp);
|
||||
else if (!strcmp(av[2], "rowstart")) TblTableRowStart(e, fp);
|
||||
else if (!strcmp(av[2], "rowend")) TblTableRowEnd(e, fp);
|
||||
else if (!strcmp(av[2], "top")) TblTableTop(e, fp);
|
||||
else if (!strcmp(av[2], "bottom")) TblTableBottom(e, fp);
|
||||
else fprintf(stderr, "Unknown %s table instruction: %s\n",
|
||||
av[1], av[2]);
|
||||
}
|
||||
else TblTable(e, fp);
|
||||
}
|
||||
|
||||
else if (!strcmp(av[1], "tex")) {
|
||||
if (ac > 2) {
|
||||
if (!strcmp(av[2], "cellstart")) TexTableCellStart(e, fp);
|
||||
else if (!strcmp(av[2], "cellend")) TexTableCellEnd(e, fp);
|
||||
else if (!strcmp(av[2], "rowstart")) TexTableRowStart(e, fp);
|
||||
else if (!strcmp(av[2], "rowend")) TexTableRowEnd(e, fp);
|
||||
else if (!strcmp(av[2], "top")) TexTableTop(e, fp);
|
||||
else if (!strcmp(av[2], "bottom")) TexTableBottom(e, fp);
|
||||
else fprintf(stderr, "Unknown %s table instruction: %s\n",
|
||||
av[1], av[2]);
|
||||
}
|
||||
else TexTable(e, fp);
|
||||
}
|
||||
|
||||
else fprintf(stderr, "Unknown table type: %s\n", av[1]);
|
||||
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Set values of the our internal table structure based on the table's
|
||||
* attributes. (This is also called for rows, since tables and rows
|
||||
* share many of the same attributes.)
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* Pointer table info structure which will be filled in.
|
||||
* Flag saying whether or not to set global variables based on attrs.
|
||||
*/
|
||||
void
|
||||
SetTabAtts(
|
||||
Element_t *e,
|
||||
TableInfo *t,
|
||||
int set_globals
|
||||
)
|
||||
{
|
||||
char *at;
|
||||
|
||||
memset(t, 0, sizeof(TableInfo));
|
||||
|
||||
/* remember values of attributes */
|
||||
if ((at = FindAttValByName(e, "HALIGN"))) t->halign = at;
|
||||
if ((at = FindAttValByName(e, "MODEL"))) t->model = at;
|
||||
if ((at = FindAttValByName(e, "COLWIDTH"))) t->colwidth = at;
|
||||
if ((at = FindAttValByName(e, "COLSEP"))) t->colsep = at;
|
||||
if ((at = FindAttValByName(e, "COLWEIGHT"))) t->colweight = at;
|
||||
if ((at = FindAttValByName(e, "FRAME"))) t->frame = at;
|
||||
if ((at = FindAttValByName(e, "REPEATHEAD"))) t->repeathead = atoi(at);
|
||||
if ((at = FindAttValByName(e, "NCOLS"))) t->ncols = at;
|
||||
|
||||
/* Set some things for later when processing this table */
|
||||
if (set_globals) {
|
||||
|
||||
rowsep = 1;
|
||||
frametop = framebot = 1; /* default style */
|
||||
|
||||
/* For now we look at the first number of rowsep - it controls the
|
||||
* horiz rule for then entire row. (not easy to specify lines that
|
||||
* span only some columns in tex or tbl. */
|
||||
if ((at = FindAttValByName(e, "ROWSEP"))) rowsep = atoi(at);
|
||||
}
|
||||
|
||||
if (t->frame) {
|
||||
/* top|bottom|topbot|all|sides|none */
|
||||
if (!strcmp(t->frame, "NONE") || !strcmp(t->frame, "SIDES"))
|
||||
frametop = framebot = 0;
|
||||
else if (!strcmp(t->frame, "TOP")) framebot = 0;
|
||||
else if (!strcmp(t->frame, "BOTTOM")) frametop = 0;
|
||||
}
|
||||
|
||||
/* tbl and tex like lower case for units. convert. */
|
||||
if (t->colwidth) {
|
||||
char *cp;
|
||||
for (cp=t->colwidth; *cp; cp++)
|
||||
if (isupper(*cp)) *cp = tolower(*cp);
|
||||
}
|
||||
|
||||
/* Now, split (space-separated) strings into vectors. Hopefully, the
|
||||
* number of elements in each vector matches the number of columns.
|
||||
*/
|
||||
t->halign_v = Split(t->halign, &t->n_halign, S_STRDUP|S_ALVEC);
|
||||
t->model_v = Split(t->model, &t->n_model, S_STRDUP|S_ALVEC);
|
||||
t->colwidth_v = Split(t->colwidth, &t->n_colwidth, S_STRDUP|S_ALVEC);
|
||||
t->colweight_v = Split(t->colweight, &t->n_colweight, S_STRDUP|S_ALVEC);
|
||||
t->colsep_v = Split(t->colsep, &t->n_colsep, S_STRDUP|S_ALVEC);
|
||||
|
||||
/* Determin the _numeric_ number of columns, "nc". The order in which we
|
||||
* check things to set nc is: NCOLS attribute, # of child element of 1st
|
||||
* row, number of tokens in the various attr lists.
|
||||
*/
|
||||
if (t->ncols) t->nc = atoi(t->ncols);
|
||||
|
||||
/* If ncols attribute not set, see how many children first child has.
|
||||
* I can't see how this can be non-zero (unless there are no rows, or
|
||||
* no rows have any cells).
|
||||
*/
|
||||
if (!t->nc && e->necont) t->nc = e->econt[0]->necont;
|
||||
|
||||
/* If ncols still not set, guess it from other attrs. Last resort. */
|
||||
if (!t->nc) {
|
||||
if (t->n_halign) t->nc = t->n_halign;
|
||||
else if (t->n_model) t->nc = t->n_model;
|
||||
else if (t->n_colwidth) t->nc = t->n_colwidth;
|
||||
else if (t->n_colweight) t->nc = t->n_colweight;
|
||||
else if (t->n_colsep) t->nc = t->n_colsep;
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
/* Free the storage of info use by the table info structure. (not the
|
||||
* structure itself, but the strings its elements point to)
|
||||
* Arguments:
|
||||
* Pointer table info structure to be freed.
|
||||
*/
|
||||
void
|
||||
FreeTabAtts(
|
||||
TableInfo *t
|
||||
)
|
||||
{
|
||||
if (!t) return;
|
||||
if (t->halign_v) free(*t->halign_v);
|
||||
if (t->model_v) free(*t->model_v);
|
||||
if (t->colwidth_v) free(*t->colwidth_v);
|
||||
if (t->colweight_v) free(*t->colweight_v);
|
||||
if (t->colsep_v) free(*t->colsep_v);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Check the attributes and children of the table pointed to by e.
|
||||
* Report problems and inconsistencies to stderr.
|
||||
* Arguments:
|
||||
* Pointer to element (table) under consideration.
|
||||
*/
|
||||
|
||||
void
|
||||
CheckTable(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
int pr_loc=0; /* flag to say if we printed location */
|
||||
int i, r, c;
|
||||
float wt;
|
||||
char *tpref = "Table Check"; /* prefix for err messages */
|
||||
char *ncolchk =
|
||||
"Table Check: %s ('%s') has wrong number of tokens. Expecting %d.\n";
|
||||
|
||||
if (strcmp(e->gi, "TABLE")) {
|
||||
fprintf(stderr, "%s: Not pointing to a table!\n", tpref);
|
||||
return;
|
||||
}
|
||||
|
||||
FreeTabAtts(&TheTab); /* free storage, if allocated earlier */
|
||||
SetTabAtts(e, &TheTab, 1); /* look at attributes */
|
||||
|
||||
/* NCOLS attribute set? */
|
||||
if (!TheTab.ncols) {
|
||||
pr_loc++;
|
||||
fprintf(stderr, "%s: NCOLS attribute missing. Inferred as %d.\n",
|
||||
tpref, TheTab.nc);
|
||||
}
|
||||
|
||||
/* HALIGN attribute set? */
|
||||
if (!TheTab.halign) {
|
||||
pr_loc++;
|
||||
fprintf(stderr, "%s: HALIGN attribute missing.\n", tpref);
|
||||
}
|
||||
|
||||
/* See if the number of cells in each row matches */
|
||||
for (r=0; r<e->necont; r++) {
|
||||
if (e->econt[r]->necont != TheTab.nc) {
|
||||
pr_loc++;
|
||||
fprintf(stderr, "%s: NCOLS (%d) differs from actual number of cells (%d) in row %d.\n",
|
||||
tpref, TheTab.nc, e->econt[r]->necont, r);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check HALIGN */
|
||||
if (TheTab.halign) {
|
||||
if (TheTab.nc != TheTab.n_halign) { /* number of tokens OK? */
|
||||
pr_loc++;
|
||||
fprintf(stderr, ncolchk, "HALIGN", TheTab.halign, TheTab.nc);
|
||||
}
|
||||
else { /* values OK? */
|
||||
for (i=0; i<TheTab.nc; i++) {
|
||||
if (*TheTab.halign_v[i] != 'c' && *TheTab.halign_v[i] != 'l' &&
|
||||
*TheTab.halign_v[i] != 'r') {
|
||||
pr_loc++;
|
||||
fprintf(stderr, "%s: HALIGN (%d) value wrong: %s\n",
|
||||
tpref, i, TheTab.halign_v[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check COLWIDTH */
|
||||
if (TheTab.colwidth) {
|
||||
if (TheTab.nc != TheTab.n_colwidth) { /* number of tokens OK? */
|
||||
pr_loc++;
|
||||
fprintf(stderr, ncolchk, "COLWIDTH", TheTab.colwidth, TheTab.nc);
|
||||
}
|
||||
else { /* values OK? */
|
||||
for (i=0; i<TheTab.nc; i++) {
|
||||
|
||||
/* check that the units after the numbers are OK
|
||||
we want "in", "cm".
|
||||
*/
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check COLWEIGHT */
|
||||
if (TheTab.colweight) {
|
||||
if (TheTab.nc != TheTab.n_colweight) { /* number of tokens OK? */
|
||||
pr_loc++;
|
||||
fprintf(stderr, ncolchk, "COLWEIGHT", TheTab.colweight, TheTab.nc);
|
||||
}
|
||||
else { /* values OK? */
|
||||
for (i=0; i<TheTab.nc; i++) { /* check that magitude is reasonable */
|
||||
wt = atof(TheTab.colweight_v[i]);
|
||||
if (wt > 50.0) {
|
||||
pr_loc++;
|
||||
fprintf(stderr, "%s: unreasonable COLWEIGHT value: %f.\n",
|
||||
tpref, wt);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* check COLSEP */
|
||||
if (TheTab.colsep) {
|
||||
if (TheTab.nc != TheTab.n_colsep) { /* number of tokens OK? */
|
||||
pr_loc++;
|
||||
fprintf(stderr, ncolchk, "COLSEP", TheTab.colsep, TheTab.nc);
|
||||
}
|
||||
else { /* values OK? */
|
||||
for (i=0; i<TheTab.nc; i++) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* See if MODEL has the same number of tokens as NCOLS. Then do model. */
|
||||
if (TheTab.model) {
|
||||
if (TheTab.nc != TheTab.n_model) {
|
||||
pr_loc++;
|
||||
fprintf(stderr, ncolchk, "MODEL", TheTab.model, TheTab.nc);
|
||||
}
|
||||
|
||||
for (r=0; r<e->necont; r++) {
|
||||
/* only check normal rows */
|
||||
if (strcmp(e->econt[r]->gi, "ROW")) continue;
|
||||
for (c=0; c<e->econt[r]->necont; c++) {
|
||||
if (!strcmp(TheTab.model_v[c], "text") ||
|
||||
!strcmp(TheTab.model_v[c], "-")) continue;
|
||||
if (e->econt[r]->econt[c]->necont &&
|
||||
strcmp(e->econt[r]->econt[c]->econt[0]->gi, TheTab.model_v[c])) {
|
||||
fprintf(stderr, "%s: MODEL wants %s, but cell contains %s: row %d, cell %d.\n",
|
||||
tpref, TheTab.model_v[c],
|
||||
e->econt[r]->econt[c]->econt[0]->gi, r, c);
|
||||
pr_loc++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pr_loc) {
|
||||
fprintf(stderr, "%s: Above problem in table located at:\n", tpref);
|
||||
PrintLocation(e, stderr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Do the "right thing" for the table spec for tbl (troff) tables. This will
|
||||
* generate the "center,box,tab(@)..." and the column justification stuff.
|
||||
* Arguments:
|
||||
* Pointer to element (table) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TblTable(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
int i, n;
|
||||
char *fr;
|
||||
float tot;
|
||||
char *cp, wbuf[1500], **widths=0, **widths_v=0, *mp;
|
||||
|
||||
FreeTabAtts(&TheTab); /* free storage, if allocated earlier */
|
||||
SetTabAtts(e, &TheTab, 1); /* look at attributes */
|
||||
|
||||
fr = "box"; /* default framing */
|
||||
frameall = 1;
|
||||
siderules = 0;
|
||||
if (TheTab.frame) {
|
||||
if (!strcmp(TheTab.frame, "ALL")) {
|
||||
fr = "box";
|
||||
frametop = framebot = 0;
|
||||
}
|
||||
else {
|
||||
fr = "";
|
||||
frameall = 0;
|
||||
}
|
||||
if (!strcmp(TheTab.frame, "SIDES")) siderules = 1;
|
||||
}
|
||||
else frametop = framebot = 0; /* because 'box' is default */
|
||||
fprintf(fp, "center, %s%s tab(@);\n", fr, ((*fr)?",":""));
|
||||
|
||||
/* Figure out the widths, based either on "colwidth" or "colweight".
|
||||
* (we pick width over weight if both are specified). */
|
||||
if (TheTab.colwidth && TheTab.nc == TheTab.n_colwidth) {
|
||||
widths = TheTab.colwidth_v;
|
||||
}
|
||||
else if (TheTab.colweight && TheTab.nc == TheTab.n_colweight) {
|
||||
for (n=0,i=0; i<TheTab.nc; i++) n += atoi(TheTab.colweight_v[i]);
|
||||
tot = (float)n;
|
||||
cp = wbuf;
|
||||
for (i=0; i<TheTab.nc; i++) {
|
||||
sprintf(cp, "%5.3fin", atof(TheTab.colweight_v[i])*(TEXTWIDTH/tot));
|
||||
while (*cp) cp++;
|
||||
*cp++ = ' ';
|
||||
}
|
||||
*cp = EOS;
|
||||
widths_v = Split(wbuf, 0, S_ALVEC);
|
||||
widths = widths_v;
|
||||
}
|
||||
|
||||
/* Remember the base model in case we do spans later. We write it
|
||||
* into a static buffer, then output it at once. */
|
||||
mp = basemodel;
|
||||
if (siderules) *mp++ = '|';
|
||||
for (i=0; i<TheTab.nc; i++) {
|
||||
/* If width specified, use it; else if halign set, use it; else left. */
|
||||
if (widths && widths[i][0] != '0' && widths[i][1] != EOS) {
|
||||
if (i) *mp++ = ' ';
|
||||
strcpy(mp, TheTab.halign_v[i]);
|
||||
while (*mp) mp++;
|
||||
*mp++ = 'w';
|
||||
*mp++ = '(';
|
||||
strcpy(mp, widths[i]);
|
||||
while (*mp) mp++;
|
||||
*mp++ = ')';
|
||||
}
|
||||
else if (TheTab.halign && TheTab.nc == TheTab.n_halign) {
|
||||
if (i) *mp++ = ' ';
|
||||
strcpy(mp, TheTab.halign_v[i]);
|
||||
while (*mp) mp++;
|
||||
}
|
||||
else {
|
||||
if (i) *mp++ = ' ';
|
||||
*mp++ = 'l';
|
||||
}
|
||||
/* See if we want column separators. */
|
||||
|
||||
if (TheTab.colsep) {
|
||||
if ( (i+1) < TheTab.nc ) {
|
||||
if ( *TheTab.colsep_v[i] == '1' )
|
||||
*mp++ = '|';
|
||||
if ( *TheTab.colsep_v[i] == '2') {
|
||||
*mp++ = '|';
|
||||
*mp++ = '|';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (siderules) *mp++ = '|';
|
||||
/* *mp++ = '.';*/
|
||||
/* *mp++ = '^';*/
|
||||
*mp = EOS;
|
||||
OutputString(basemodel, fp, 1);
|
||||
OutputString(".^", fp, 1);
|
||||
|
||||
if (widths_v) free(widths_v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (cell) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TblTableCellStart(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
/* nothing to do at start of cell */
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (cell) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TblTableCellEnd(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
/* do cell/col separators */
|
||||
if (e->my_eorder < (TheTab.nc-1)) {
|
||||
if (spaninfo[e->my_eorder] == SPAN_NOT ||
|
||||
spaninfo[e->my_eorder+1] != SPAN_CONT)
|
||||
OutputString("@", fp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at model attribute for spanning. If set, remember info for when
|
||||
* doing the cells. Called by TblTableRowStart() and TexTableRowStart().
|
||||
* Arguments:
|
||||
* Pointer to element (row) under consideration.
|
||||
*/
|
||||
int
|
||||
check_for_spans(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
char *at;
|
||||
char **spans;
|
||||
int n, i, inspan;
|
||||
|
||||
/* See if MODEL attr is set */
|
||||
if ((at = FindAttValByName(e, "MODEL"))) {
|
||||
|
||||
/* Split into tokens, then look at each for the word "span" */
|
||||
n = TheTab.nc;
|
||||
spans = Split(at, &n, S_STRDUP|S_ALVEC);
|
||||
|
||||
/* Mark columns as start-of-span, in-span, or not spanned. Remember
|
||||
* in at list, "spaningo". (Span does not make sense in 1st column.)
|
||||
*/
|
||||
for (i=1,inspan=0; i<n; i++) {
|
||||
if (StrEq(spans[i], "span") || StrEq(spans[i], "s")) {
|
||||
if (inspan == 0) spaninfo[i-1] = SPAN_START;
|
||||
spaninfo[i] = SPAN_CONT;
|
||||
inspan = 1;
|
||||
}
|
||||
else {
|
||||
spaninfo[i] = SPAN_NOT;
|
||||
inspan = 0;
|
||||
}
|
||||
}
|
||||
free(*spans); /* free string */
|
||||
free(spans); /* free vector */
|
||||
spaninfo[TheTab.nc] = SPAN_NOT; /* after last cell */
|
||||
return 1;
|
||||
}
|
||||
/* if model not set, mark all as not spanning */
|
||||
else
|
||||
for (i=0; i<MAXCOLS; i++) spaninfo[i] = SPAN_NOT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Output format for cell. Called from TblTableRowStart().
|
||||
* Arguments:
|
||||
* Pointer to table info structure (for this row)
|
||||
* Which cell/column we're considering
|
||||
* Flag saying whether we're on last column
|
||||
* Default format of col, if none is set for this row or table
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
|
||||
void
|
||||
tbl_cell_fmt(
|
||||
TableInfo *t,
|
||||
int i,
|
||||
int lastcol,
|
||||
char *def_fmt,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
if (t->halign) OutputString(t->halign_v[i], fp, 1);
|
||||
else if (TheTab.halign) OutputString(TheTab.halign_v[i], fp, 1);
|
||||
else OutputString(def_fmt, fp, 1);
|
||||
|
||||
if (!lastcol && spaninfo[i+1] != SPAN_CONT) {
|
||||
if (t->colsep) {
|
||||
if (*t->colsep_v[i] == '1')
|
||||
OutputString("|", fp, 1);
|
||||
if (*t->colsep_v[i] == '2')
|
||||
OutputString("||", fp, 1);
|
||||
}
|
||||
else if (TheTab.colsep) {
|
||||
if (*TheTab.colsep_v[i] == '1')
|
||||
OutputString("|", fp, 1);
|
||||
if (*TheTab.colsep_v[i] == '2')
|
||||
OutputString("||", fp, 1);
|
||||
}
|
||||
else OutputString("|", fp, 1);
|
||||
}
|
||||
OutputString(" ", fp, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (row) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
|
||||
void
|
||||
TblTableRowStart(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
int i, lastcol, stayhere;
|
||||
char **basev, *cp;
|
||||
TableInfo RowInfo;
|
||||
|
||||
/* check if we're spanning, or if HALIGN set */
|
||||
stayhere = 0;
|
||||
if (check_for_spans(e)) stayhere = 1;
|
||||
SetTabAtts(e, &RowInfo, 0);
|
||||
if (RowInfo.halign) stayhere = 1;
|
||||
|
||||
if (!stayhere) return;
|
||||
|
||||
/* Change table layout because we have a span, or the row has HALIGN. */
|
||||
OutputString("^.T&^", fp, 1);
|
||||
basev = Split(basemodel, 0, S_ALVEC|S_STRDUP);
|
||||
|
||||
for (i=0; i<TheTab.nc; i++) {
|
||||
|
||||
lastcol = !(i < TheTab.nc-1);
|
||||
if (spaninfo[i] == SPAN_START) {
|
||||
tbl_cell_fmt(&RowInfo, i, lastcol, "c ", fp);
|
||||
}
|
||||
else if (spaninfo[i] == SPAN_CONT) {
|
||||
/* See if next col is NOT spanned, and we're not in last col */
|
||||
OutputString("s", fp, 1);
|
||||
if (!lastcol && spaninfo[i+1] != SPAN_CONT) {
|
||||
if (RowInfo.colsep) cp = RowInfo.colsep_v[i];
|
||||
else if (TheTab.colsep) cp = TheTab.colsep_v[i];
|
||||
else cp = "1";
|
||||
|
||||
if (*cp == '1')
|
||||
OutputString("|", fp, 1);
|
||||
if (*cp == '2')
|
||||
OutputString("||", fp, 1);
|
||||
}
|
||||
OutputString(" ", fp, 1);
|
||||
}
|
||||
else
|
||||
tbl_cell_fmt(&RowInfo, i, lastcol, "l ", fp);
|
||||
}
|
||||
OutputString("^", fp, 1);
|
||||
OutputString(basemodel, fp, 1);
|
||||
OutputString(".^", fp, 1);
|
||||
free(*basev);
|
||||
free(basev);
|
||||
FreeTabAtts(&RowInfo);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (row) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TblTableRowEnd(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
char *at;
|
||||
|
||||
/* See if we're on the last row, then if we're putting a frame
|
||||
* around the whole table. If so, we need no bottom separator. */
|
||||
if ((e->parent->necont-1) == e->my_eorder) {
|
||||
if (frameall || framebot) return;
|
||||
}
|
||||
/* check this row's attributes */
|
||||
if ((at = FindAttValByName(e, "ROWSEP"))) {
|
||||
if (at[0] == '1') fprintf(fp, "_\n");
|
||||
}
|
||||
else if (rowsep) /* fprintf(fp, "_\n") */
|
||||
;
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (table) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TblTableTop(Element_t *e, FILE *fp)
|
||||
{
|
||||
if (frametop) OutputString("^_^", fp, 1);
|
||||
}
|
||||
|
||||
void
|
||||
TblTableBottom(Element_t *e, FILE *fp)
|
||||
{
|
||||
if (framebot) OutputString("^_^", fp, 1);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Do the "right thing" for the table spec for TeX tables. This will
|
||||
* generate the arg to \begin{tabular}[xxx].
|
||||
* Arguments:
|
||||
* Pointer to element (table) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TexTable(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
int i, n;
|
||||
float tot;
|
||||
char *cp, wbuf[1500], **widths=0, **widths_v=0;
|
||||
|
||||
FreeTabAtts(&TheTab); /* free storage, if allocated earlier */
|
||||
SetTabAtts(e, &TheTab, 1); /* look at attributes */
|
||||
|
||||
/* Figure out the widths, based either on "colwidth" or "colweight".
|
||||
* (we pick width over weight if both are specified). */
|
||||
if (TheTab.colwidth && TheTab.nc == TheTab.n_colwidth) {
|
||||
widths = TheTab.colwidth_v;
|
||||
}
|
||||
else if (TheTab.colweight && TheTab.nc == TheTab.n_colweight) {
|
||||
for (n=0,i=0; i<TheTab.nc; i++) n += atoi(TheTab.colweight_v[i]);
|
||||
tot = (float)n;
|
||||
cp = wbuf;
|
||||
for (i=0; i<TheTab.nc; i++) {
|
||||
sprintf(cp, "%5.3fin", atof(TheTab.colweight_v[i])*(TEXTWIDTH/tot));
|
||||
while (*cp) cp++;
|
||||
*cp++ = ' ';
|
||||
}
|
||||
*cp = EOS;
|
||||
widths_v = Split(wbuf, 0, S_ALVEC);
|
||||
widths = widths_v;
|
||||
}
|
||||
siderules = 1;
|
||||
if (TheTab.frame)
|
||||
if (strcmp(TheTab.frame, "ALL") && strcmp(TheTab.frame, "SIDES"))
|
||||
siderules = 0;
|
||||
|
||||
if (siderules) OutputString("|", fp, 1);
|
||||
for (i=0; i<TheTab.nc; i++) {
|
||||
/* If width specified, use it; else if halign set, use it; else left. */
|
||||
if (widths && widths[i][0] != '0' && widths[i][1] != EOS) {
|
||||
fprintf(fp, "%sp{%s}", (i?" ":""), widths[i]);
|
||||
}
|
||||
else if (TheTab.halign && TheTab.nc == TheTab.n_halign) {
|
||||
fprintf(fp, "%s%s", (i?" ":""), TheTab.halign_v[i]);
|
||||
}
|
||||
else
|
||||
fprintf(fp, "%sl", (i?" ":""));
|
||||
/* See if we want column separators. */
|
||||
if (TheTab.colsep) {
|
||||
|
||||
if ( (i+1) < TheTab.nc ) {
|
||||
if ( *TheTab.colsep_v[i] == '1' ) {
|
||||
fprintf(fp, " |");
|
||||
}
|
||||
if ( *TheTab.colsep_v[i] == '2' ) {
|
||||
fprintf(fp, " ||");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (siderules) OutputString("|", fp, 1);
|
||||
|
||||
if (widths_v) free(widths_v);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (cell) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TexTableCellStart(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
int n, i;
|
||||
char buf[50], *at;
|
||||
|
||||
if (spaninfo[e->my_eorder] == SPAN_START) {
|
||||
for (i=e->my_eorder+1,n=1; ; i++) {
|
||||
if (spaninfo[i] == SPAN_CONT) n++;
|
||||
else break;
|
||||
}
|
||||
sprintf(buf, "\\\\multicolumn{%d}{%sc%s}", n,
|
||||
(siderules?"|":""), (siderules?"|":""));
|
||||
OutputString(buf, fp, 1);
|
||||
}
|
||||
#ifdef New
|
||||
if ((at = FindAttValByName(e->parent, "HALIGN"))) {
|
||||
/* no span, but user wants to change the alignment */
|
||||
h_v = Split(wbuf, 0, S_ALVEC|S_STRDUP);
|
||||
OutputString("\\\\multicolumn{1}{%sc%s}", n,
|
||||
fp, 1);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (spaninfo[e->my_eorder] != SPAN_CONT) OutputString("{", fp, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (cell) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TexTableCellEnd(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
if (spaninfo[e->my_eorder] != SPAN_CONT) OutputString("} ", fp, 1);
|
||||
|
||||
/* do cell/col separators */
|
||||
if (e->my_eorder < (TheTab.nc-1)) {
|
||||
if (spaninfo[e->my_eorder] == SPAN_NOT ||
|
||||
spaninfo[e->my_eorder+1] != SPAN_CONT)
|
||||
OutputString("& ", fp, 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Look at model for spanning. If set, remember it for when doing the cells.
|
||||
* Arguments:
|
||||
* Pointer to element (row) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TexTableRowStart(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
check_for_spans(e);
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (row) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TexTableRowEnd(
|
||||
Element_t *e,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
char *at;
|
||||
|
||||
/* check this row's attributes */
|
||||
if ((at = FindAttValByName(e, "ROWSEP"))) {
|
||||
if (at[0] == '1') OutputString("\\\\\\\\[2mm] \\\\hline ", fp, 1);
|
||||
}
|
||||
else if (rowsep) OutputString("\\\\\\\\ ", fp, 1);
|
||||
else
|
||||
OutputString("\\\\\\\\ ", fp, 1);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Arguments:
|
||||
* Pointer to element (table) under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TexTableTop(Element_t *e, FILE *fp)
|
||||
{
|
||||
if (frametop) OutputString("\\\\hline", fp, 1);
|
||||
}
|
||||
|
||||
void
|
||||
TexTableBottom(Element_t *e, FILE *fp)
|
||||
{
|
||||
if (framebot) OutputString("\\\\hline", fp, 1);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
436
cde/programs/dtdocbook/doc2sdl/instant/traninit.c
Normal file
436
cde/programs/dtdocbook/doc2sdl/instant/traninit.c
Normal file
@@ -0,0 +1,436 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Program to manipulate SGML instances.
|
||||
*
|
||||
* This module contains the initialization routines for translation module.
|
||||
* They mostly deal with reading data files (translation specs, SDATA
|
||||
* mappings, character mappings).
|
||||
*
|
||||
* Entry points:
|
||||
* ReadTransSpec(transfile) read/store translation spec from file
|
||||
* ReadSDATA(sdatafile) read/store SDATA mappings from file
|
||||
* ReadMapping(mapfile) read/store char mappings from file
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid =
|
||||
"$XConsortium: traninit.c /main/3 1996/06/19 17:13:22 drk $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "general.h"
|
||||
#include "translate.h"
|
||||
|
||||
/* forward references */
|
||||
void RememberTransSpec(Trans_t *, int);
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Read the translation specs from the input file, storing in memory.
|
||||
* Arguments:
|
||||
* Name of translation spec file.
|
||||
*/
|
||||
|
||||
void
|
||||
ReadTransSpec(
|
||||
char *transfile
|
||||
)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[LINESIZE], *cp, *fn, *cp2;
|
||||
int lineno=0, c, i;
|
||||
Trans_t T;
|
||||
int giLen;
|
||||
char *giBuf;
|
||||
|
||||
if ((fp=OpenFile(transfile)) == NULL) {
|
||||
fprintf(stderr, "Can not open translation spec file '%s'.\n%s\n",
|
||||
transfile, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
memset(&T, 0, sizeof T); /* initialize/clear structure */
|
||||
while (fgets(buf, LINESIZE, fp)) /* read line from .ts file */
|
||||
{
|
||||
lineno++;
|
||||
/* skip comment and blank lines */
|
||||
if (buf[0] == '#' || buf[0] == NL) continue;
|
||||
|
||||
/* '-' indicates end of a spec. When we hit one, remember what we've
|
||||
* accumulated so far, and null-out the accumulating structure. */
|
||||
if (buf[0] == '-') {
|
||||
T.lineno = lineno;
|
||||
RememberTransSpec(&T, lineno);
|
||||
memset(&T, 0, sizeof T);
|
||||
continue;
|
||||
}
|
||||
|
||||
stripNL(buf);
|
||||
|
||||
/* See if next line is continued from this one -- ie. it starts with
|
||||
* whitespace. If so, append to current line. (This is similar to
|
||||
* how e-mail headers work...) */
|
||||
while (1) {
|
||||
c = getc(fp); /* 1st char of next line */
|
||||
if (IsWhite(c)) { /* space or tab? */
|
||||
/* keep getting characters until it's a non-whitespace */
|
||||
c = getc(fp);
|
||||
while (IsWhite(c)) c = getc(fp);
|
||||
ungetc(c, fp); /* put back non-whitespace */
|
||||
i = strlen(buf);
|
||||
fn = buf + i; /* point to end of string in buffer */
|
||||
fgets(fn, LINESIZE-i, fp); /* read and append to buf */
|
||||
lineno++;
|
||||
stripNL(buf);
|
||||
}
|
||||
else {
|
||||
ungetc(c, fp); /* put back non-whitespace */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Isolate field value */
|
||||
if ((cp=strchr(buf, ':'))) {
|
||||
cp++; /* point past colon */
|
||||
while (*cp && IsWhite(*cp)) cp++; /* point to content */
|
||||
}
|
||||
else {
|
||||
fprintf(stderr,
|
||||
"Trans spec error, missing colon (skipping line):\n %s\n", fn);
|
||||
continue;
|
||||
}
|
||||
fn = buf; /* fn is name of the field, cp the value. */
|
||||
|
||||
/* Check field names in order that they're likely to occur. */
|
||||
if (!strncmp("GI:", fn, 3)) {
|
||||
/* if we are folding the case of GIs, make all upper (unless
|
||||
it's an internal pseudo-GI name, which starts with '_') */
|
||||
if (fold_case && cp[0] != '_' && cp[0] != '#') {
|
||||
for (cp2=cp; *cp2; cp2++)
|
||||
if (islower(*cp2)) *cp2 = toupper(*cp2);
|
||||
}
|
||||
if (T.gi) {
|
||||
giLen = strlen(T.gi) + strlen(cp) + 2;
|
||||
Malloc(giLen, giBuf, char);
|
||||
strcpy(giBuf, T.gi);
|
||||
strcat(giBuf, " "); /* why we added "2" above */
|
||||
strcat(giBuf, cp);
|
||||
T.gi = AddElemName(giBuf);
|
||||
free(giBuf);
|
||||
} else {
|
||||
T.gi = AddElemName(cp);
|
||||
}
|
||||
}
|
||||
else if (!strncmp("StartText:", fn, 10)) T.starttext = strdup(cp);
|
||||
else if (!strncmp("EndText:", fn, 8)) T.endtext = strdup(cp);
|
||||
else if (!strncmp("Relation:", fn, 9)) {
|
||||
if (!T.relations) T.relations = NewMap(IMS_relations);
|
||||
SetMapping(T.relations, cp);
|
||||
}
|
||||
else if (!strncmp("StartCode:", fn, 10)) T.startcode = strdup(cp);
|
||||
else if (!strncmp("EndCode:", fn, 8)) T.endcode = strdup(cp);
|
||||
else if (!strncmp("Replace:", fn, 8)) T.replace = strdup(cp);
|
||||
else if (!strncmp("AttValue:", fn, 9)) {
|
||||
if (!T.nattpairs) {
|
||||
Malloc(1, T.attpair, AttPair_t);
|
||||
}
|
||||
else
|
||||
Realloc((T.nattpairs+1), T.attpair, AttPair_t);
|
||||
/* we'll split name/value pairs later */
|
||||
T.attpair[T.nattpairs].name = strdup(cp);
|
||||
T.nattpairs++;
|
||||
}
|
||||
/* If there's only one item in context, it's the parent. Treat
|
||||
* it specially, since it's easier to just check parent gi.
|
||||
*/
|
||||
else if (!strncmp("Context:", fn, 8)) T.context = strdup(cp);
|
||||
else if (!strncmp("Message:", fn, 8)) T.message = strdup(cp);
|
||||
else if (!strncmp("SpecID:", fn, 7)) T.my_id = atoi(cp);
|
||||
else if (!strncmp("Action:", fn, 7)) T.use_id = atoi(cp);
|
||||
else if (!strncmp("Content:", fn, 8)) T.content = strdup(cp);
|
||||
else if (!strncmp("PAttSet:", fn, 8)) T.pattrset = strdup(cp);
|
||||
else if (!strncmp("Ignore:", fn, 7)) {
|
||||
if (!strcmp(cp, "all")) T.ignore = IGN_ALL;
|
||||
else if (!strcmp(cp, "data")) T.ignore = IGN_DATA;
|
||||
else if (!strcmp(cp, "children")) T.ignore = IGN_CHILDREN;
|
||||
else
|
||||
fprintf(stderr, "Bad 'Ignore:' arg in transpec (line %d): %s\n",
|
||||
lineno, cp);
|
||||
}
|
||||
else if (!strncmp("VarValue:", fn, 9)) {
|
||||
char **tok;
|
||||
i = 2;
|
||||
tok = Split(cp, &i, S_STRDUP);
|
||||
T.var_name = tok[0];
|
||||
T.var_value = tok[1];
|
||||
}
|
||||
else if (!strncmp("Set:", fn, 4)) {
|
||||
if (!T.set_var) T.set_var = NewMap(IMS_setvar);
|
||||
SetMapping(T.set_var, cp);
|
||||
}
|
||||
else if (!strncmp("Increment:", fn, 10)) {
|
||||
if (!T.incr_var) T.incr_var = NewMap(IMS_incvar);
|
||||
SetMapping(T.incr_var, cp);
|
||||
}
|
||||
else if (!strncmp("NthChild:", fn, 9)) T.nth_child = atoi(cp);
|
||||
else if (!strncmp("Var:", fn, 4)) SetMapping(Variables, cp);
|
||||
else if (!strncmp("Quit:", fn, 5)) T.quit = strdup(cp);
|
||||
else
|
||||
fprintf(stderr, "Unknown translation spec (skipping it): %s\n", fn);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Store translation spec 't' in memory.
|
||||
* Arguments:
|
||||
* Pointer to translation spec to remember.
|
||||
* Line number where translation spec ends.
|
||||
*/
|
||||
void
|
||||
RememberTransSpec(
|
||||
Trans_t *t,
|
||||
int lineno
|
||||
)
|
||||
{
|
||||
char *cp;
|
||||
int i, do_regex;
|
||||
static Trans_t *last_t;
|
||||
|
||||
/* If context testing, check some details and set things up for later. */
|
||||
if (t->context) {
|
||||
/* See if the context specified is a regular expression.
|
||||
* If so, compile the reg expr. It is assumed to be a regex if
|
||||
* it contains a character other than what's allowed for GIs in the
|
||||
* OSF sgml declaration (alphas, nums, '-', and '.').
|
||||
*/
|
||||
for (do_regex=0,cp=t->context; *cp; cp++) {
|
||||
if (!isalnum(*cp) && *cp != '-' && *cp != '.' && *cp != ' ') {
|
||||
do_regex = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (do_regex) {
|
||||
t->depth = MAX_DEPTH;
|
||||
if (regcomp(&t->context_re, t->context, 0)) {
|
||||
fprintf(stderr, "Regex error in Context: %s\n", t->context);
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* If there's only one item in context, it's the parent. Treat
|
||||
* it specially, since it's faster to just check parent gi.
|
||||
*/
|
||||
cp = t->context;
|
||||
if (!strchr(cp, ' ')) {
|
||||
t->parent = t->context;
|
||||
t->context = NULL;
|
||||
}
|
||||
else {
|
||||
/* Figure out depth of context string */
|
||||
t->depth = 0;
|
||||
while (*cp) {
|
||||
if (*cp) t->depth++;
|
||||
while (*cp && !IsWhite(*cp)) cp++; /* find end of gi */
|
||||
while (*cp && IsWhite(*cp)) cp++; /* skip space */
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Compile regular expressions for each attribute */
|
||||
for (i=0; i<t->nattpairs; i++) {
|
||||
/* Initially, name points to "name value". Split them... */
|
||||
cp = t->attpair[i].name;
|
||||
while (*cp && !IsWhite(*cp)) cp++; /* point past end of name */
|
||||
if (*cp) { /* value found */
|
||||
*cp++ = EOS; /* terminate name */
|
||||
while (*cp && IsWhite(*cp)) cp++; /* point to value */
|
||||
t->attpair[i].val = cp;
|
||||
}
|
||||
else { /* value not found */
|
||||
t->attpair[i].val = ".";
|
||||
}
|
||||
if (regcomp(&t->attpair[i].rex, t->attpair[i].val, 0)) {
|
||||
fprintf(stderr, "Regex error in AttValue: %s %s\n",
|
||||
t->attpair[i].name, t->attpair[i].val);
|
||||
}
|
||||
}
|
||||
|
||||
/* Compile regular expression for content */
|
||||
if (t->content) {
|
||||
if (regcomp(&t->content_re, t->content, 0))
|
||||
fprintf(stderr, "Regex error in Content: %s\n",
|
||||
t->content);
|
||||
}
|
||||
|
||||
/* If multiple GIs, break up into a vector, then remember it. We either
|
||||
* sture the individual, or the list - not both. */
|
||||
if (t->gi && strchr(t->gi, ' ')) {
|
||||
t->gilist = Split(t->gi, 0, S_ALVEC);
|
||||
t->gi = NULL;
|
||||
}
|
||||
|
||||
/* Now, store structure in linked list. */
|
||||
if (!TrSpecs) {
|
||||
Malloc(1, TrSpecs, Trans_t);
|
||||
last_t = TrSpecs;
|
||||
}
|
||||
else {
|
||||
Malloc(1, last_t->next, Trans_t);
|
||||
last_t = last_t->next;
|
||||
}
|
||||
*last_t = *t;
|
||||
}
|
||||
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Read mapping file, filling in structure slots (just name-value pairs).
|
||||
* Arguments:
|
||||
* Name of character mapping file.
|
||||
*/
|
||||
|
||||
void
|
||||
ReadCharMap(
|
||||
char *filename
|
||||
)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[LINESIZE], *name, *val;
|
||||
int lineno=0;
|
||||
int n_alloc=0; /* number of slots allocated so far */
|
||||
|
||||
if ((fp=OpenFile(filename)) == NULL) {
|
||||
fprintf(stderr, "Can not open character mapping file '%s'.\n%s\n",
|
||||
filename, strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
/* We allocate slots in blocks of N, so we don't have to call
|
||||
* malloc so many times. */
|
||||
n_alloc = 32;
|
||||
Calloc(n_alloc, CharMap, Mapping_t);
|
||||
|
||||
nCharMap = 0;
|
||||
while (fgets(buf, LINESIZE, fp))
|
||||
{
|
||||
lineno++;
|
||||
/* skip comment and blank lines */
|
||||
if (buf[0] == '#' || buf[0] == NL) continue;
|
||||
stripNL(buf);
|
||||
|
||||
/* Need more slots for mapping structures? */
|
||||
if (nCharMap >= n_alloc) {
|
||||
n_alloc += 32;
|
||||
Realloc(n_alloc, CharMap, Mapping_t);
|
||||
}
|
||||
name = val = buf;
|
||||
while (*val && !IsWhite(*val)) val++; /* point past end of name */
|
||||
if (*val) {
|
||||
*val++ = EOS; /* terminate name */
|
||||
while (*val && IsWhite(*val)) val++; /* point to value */
|
||||
}
|
||||
if (name) {
|
||||
CharMap[nCharMap].name = strdup(name);
|
||||
if (val) CharMap[nCharMap].sval = strdup(val);
|
||||
if (CharMap[nCharMap].name[0] == '\\') CharMap[nCharMap].name++;
|
||||
nCharMap++;
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Read SDATA mapping file, remembering the mappings in memory.
|
||||
* Input file format is 2 columns, name and value, separated by one or
|
||||
* more tabs (not spaces).
|
||||
* This can be called multuple times, reading several files.
|
||||
* Arguments:
|
||||
* Name of SDATA entity mapping file.
|
||||
*/
|
||||
|
||||
void
|
||||
ReadSDATA(
|
||||
char *filename
|
||||
)
|
||||
{
|
||||
FILE *fp;
|
||||
char buf[LINESIZE], *name, *val;
|
||||
int lineno=0;
|
||||
|
||||
if ((fp=OpenFile(filename)) == NULL) {
|
||||
fprintf(stderr, "Can not open SDATA file '%s': %s", filename,
|
||||
strerror(errno));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!SDATAmap) SDATAmap = NewMap(IMS_sdata);
|
||||
|
||||
while (fgets(buf, LINESIZE, fp))
|
||||
{
|
||||
lineno++;
|
||||
/* skip comment and blank lines */
|
||||
if (buf[0] == '#' || buf[0] == NL) continue;
|
||||
stripNL(buf);
|
||||
|
||||
name = val = buf;
|
||||
while (*val && *val != TAB) val++; /* point past end of name */
|
||||
if (*val) {
|
||||
*val++ = EOS; /* terminate name */
|
||||
while (*val && *val == TAB) val++; /* point to value */
|
||||
}
|
||||
|
||||
SetMappingNV(SDATAmap, name, val);
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
920
cde/programs/dtdocbook/doc2sdl/instant/translate.c
Normal file
920
cde/programs/dtdocbook/doc2sdl/instant/translate.c
Normal file
@@ -0,0 +1,920 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Program to manipulate SGML instances.
|
||||
*
|
||||
* This module is for "translating" an instance to another form, usually
|
||||
* suitable for a formatting application.
|
||||
*
|
||||
* Entry points for this module:
|
||||
* DoTranslate(elem, transfile, mapfile, fp)
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid =
|
||||
"$XConsortium: translate.c /main/10 1996/10/29 11:47:36 cde-hp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "general.h"
|
||||
#define STORAGE
|
||||
#include "translate.h"
|
||||
|
||||
static Trans_t NullTrans; /* an empty one */
|
||||
|
||||
/* forward references */
|
||||
void ProcesOutputSpec(char *, Element_t *, FILE *, int);
|
||||
void CallInterpreter(char *, Element_t *);
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Translate the subtree starting at 'e'. Use 'transfile' for translation
|
||||
* specs. Output goes to 'fp'. This is the entry point for translating
|
||||
* an instance.
|
||||
* Assumes you've read SDATA and CharMap files (optionally).
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* Pointer to name of translation spec file.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
|
||||
static void WasProcessed(Element_t *);
|
||||
void
|
||||
DoTranslate(
|
||||
Element_t *e,
|
||||
char *transfile,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
Trans_t *t, *tn;
|
||||
|
||||
if (!transfile) {
|
||||
fprintf(stderr,
|
||||
"Translation spec file not specified. Skipping translation.\n");
|
||||
return;
|
||||
}
|
||||
ReadTransSpec(transfile);
|
||||
|
||||
/* Find transpec for each node. */
|
||||
DescendTree(e, PrepTranspecs, 0, 0, 0);
|
||||
|
||||
/* Stuff to do at start of processing */
|
||||
if ((t = FindTransByName("_Start"))) {
|
||||
if (t->starttext) ProcesOutputSpec(t->starttext, 0, fp, 1);
|
||||
if (t->startcode) CallInterpreter(t->startcode, 0);
|
||||
if (t->replace) ProcesOutputSpec(t->replace, 0, fp, 1);
|
||||
if (t->message) ProcesOutputSpec(t->message, 0, stderr, 0);
|
||||
if (t->endcode) CallInterpreter(t->endcode, 0);
|
||||
if (t->endtext) ProcesOutputSpec(t->endtext, 0, fp, 1);
|
||||
}
|
||||
|
||||
/* Translate topmost/first element. This is recursive. */
|
||||
TransElement(e, fp, NULL);
|
||||
|
||||
/* Stuff to do at end of processing */
|
||||
if ((t = FindTransByName("_End"))) {
|
||||
if (t->starttext) ProcesOutputSpec(t->starttext, 0, fp, 1);
|
||||
if (t->startcode) CallInterpreter(t->startcode, 0);
|
||||
if (t->replace) ProcesOutputSpec(t->replace, 0, fp, 1);
|
||||
if (t->message) ProcesOutputSpec(t->message, 0, stderr, 0);
|
||||
if (t->endcode) CallInterpreter(t->endcode, 0);
|
||||
if (t->endtext) ProcesOutputSpec(t->endtext, 0, fp, 1);
|
||||
}
|
||||
|
||||
/* Warn about unprocessed elements in this doc tree, if verbose mode. */
|
||||
if (verbose)
|
||||
DescendTree(e, WasProcessed, 0, 0, 0);
|
||||
|
||||
/* Clean up. This is not yet complete, which is no big deal (since the
|
||||
* program is normally done at this point anyway. */
|
||||
for (t=TrSpecs; t; ) {
|
||||
tn = t->next;
|
||||
|
||||
regfree(&t->context_re);
|
||||
regfree(&t->content_re);
|
||||
|
||||
for (int i = 0; i < t->nattpairs; ++i) regfree(&t->attpair[i].rex);
|
||||
|
||||
/* free the contents of t here ... */
|
||||
(void)free((void* )t);
|
||||
|
||||
t = tn;
|
||||
}
|
||||
TrSpecs = 0;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Print warning about unprocessed elements in this doc tree (if they
|
||||
* were not explicitely ignored).
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
*/
|
||||
static void
|
||||
WasProcessed(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
Trans_t *t;
|
||||
t = e->trans;
|
||||
if (!e->processed && (t && !t->ignore)) {
|
||||
fprintf(stderr, "Warning: element '%s' was not processed:\n", e->gi);
|
||||
PrintLocation(e, stderr);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* For each element find transpec.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
*/
|
||||
void
|
||||
PrepTranspecs(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
Trans_t *t;
|
||||
t = FindTrans(e);
|
||||
e->trans = t;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Copy a buffer/string into another, expanding regular variables. (Special
|
||||
* variables are done later.)
|
||||
* Arguments:
|
||||
* Pointer to string to expand.
|
||||
* Pointer to expanded string. (return)
|
||||
* Pointer to element under consideration.
|
||||
*/
|
||||
void
|
||||
ExpandVariables(
|
||||
char *in,
|
||||
char *out,
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
char *ip, *vp, *op;
|
||||
char *def_val, *s, *atval, *modifier;
|
||||
char vbuf[500];
|
||||
int lev;
|
||||
size_t len = 0, totlen;
|
||||
|
||||
ip = in;
|
||||
op = out;
|
||||
totlen = strlen(ip);
|
||||
while (totlen >= len && *ip) {
|
||||
/* start of regular variable? */
|
||||
if (*ip == VDELIM && *(ip+1) == L_CURLY && *(ip+2) != '_') {
|
||||
ip++;
|
||||
ip++; /* point at variable name */
|
||||
len += 2;
|
||||
vp = vbuf;
|
||||
/* Look for matching (closing) curly. (watch for nesting)
|
||||
* We store the variable content in a tmp buffer, so we don't
|
||||
* clobber the input buffer.
|
||||
*/
|
||||
lev = 0;
|
||||
while (*ip) {
|
||||
if (*ip == L_CURLY) lev++;
|
||||
if (*ip == R_CURLY) {
|
||||
if (lev == 0) {
|
||||
ip++;
|
||||
len++;
|
||||
break;
|
||||
}
|
||||
else lev--;
|
||||
}
|
||||
*vp++ = *ip++; /* copy to variable buffer */
|
||||
len++;
|
||||
}
|
||||
*vp = EOS;
|
||||
/* vbuf now contains the variable name (stuff between curlys). */
|
||||
if (lev != 0) {
|
||||
fprintf(stderr, "Botched variable use: %s\n", in);
|
||||
/* copy rest of string if we can't recover ?? */
|
||||
return;
|
||||
}
|
||||
/* Now, expand variable. */
|
||||
vp = vbuf;
|
||||
|
||||
/* See if this variable has a default [ format: ${varname def} ] */
|
||||
def_val = vp;
|
||||
while (*def_val && *def_val != ' ') def_val++;
|
||||
if (*def_val) *def_val++ = EOS;
|
||||
else def_val = 0;
|
||||
/* def_val now points to default, if it exists, null if not. */
|
||||
|
||||
modifier = vp;
|
||||
while (*modifier && *modifier != ':') modifier++;
|
||||
if (*modifier) *modifier++ = EOS;
|
||||
else modifier = 0;
|
||||
/* modifier now points to modifier if it exists, null if not. */
|
||||
|
||||
s = 0;
|
||||
/* if attribute of current elem with this name found, use value */
|
||||
if (e && (atval = FindAttValByName(e, vp)))
|
||||
s = atval;
|
||||
else /* else try for (global) variable with this name */
|
||||
s = FindMappingVal(Variables, vp);
|
||||
|
||||
if (!s) {
|
||||
modifier = 0; /* assume user gave us the exact string */
|
||||
s = def_val; /* may be null if no default value given */
|
||||
}
|
||||
|
||||
/* If we found a value, copy it to the output buffer. */
|
||||
|
||||
if (s) {
|
||||
if ( modifier && *modifier == 'l' ) {
|
||||
while (*s) {
|
||||
*op = tolower(*s);
|
||||
op++, s++;
|
||||
}
|
||||
} else
|
||||
while (*s) *op++ = *s++;
|
||||
}
|
||||
}
|
||||
*op++ = *ip++;
|
||||
len++;
|
||||
}
|
||||
*op = EOS; /* terminate string */
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Call ProcesOutputSpec to expand parser variables then call the
|
||||
* interpreter passing the resulting string.
|
||||
* Arguments:
|
||||
* Input buffer (string) to be expanded and passed.
|
||||
* Pointer to element under consideration.
|
||||
*/
|
||||
void
|
||||
CallInterpreter(
|
||||
char *ib,
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
int result;
|
||||
int recursive;
|
||||
char *tcl_str;
|
||||
Tcl_DString tcl_dstr;
|
||||
Tcl_Encoding tcl_enc;
|
||||
|
||||
#if 0
|
||||
if (ib)
|
||||
{
|
||||
fprintf(stderr, "JET: %s: IB = '%s'\n", __FUNCTION__,
|
||||
ib);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* save the value of this "e" to be used by Tcl_PrintLocation in
|
||||
* the case of a user error
|
||||
*/
|
||||
tclE = e;
|
||||
|
||||
/* if there's something in the output buffer, we're recursing,
|
||||
* just append, don't call the interpreter or clear the buffer
|
||||
*/
|
||||
recursive = OutputBufferActive();
|
||||
|
||||
ProcesOutputSpec(ib, e, 0, 1);
|
||||
if (!recursive) {
|
||||
tcl_enc = Tcl_GetEncoding(NULL, NULL);
|
||||
tcl_str = Tcl_ExternalToUtfDString(
|
||||
tcl_enc, GetOutputBuffer(), -1, &tcl_dstr);
|
||||
result = Tcl_Eval(interpreter, tcl_str);
|
||||
Tcl_DStringFree(&tcl_dstr);
|
||||
ClearOutputBuffer();
|
||||
|
||||
if (result != TCL_OK) {
|
||||
static char errMessConst[] = "puts stderr $errorInfo";
|
||||
char errMessVar[sizeof(errMessConst)];
|
||||
|
||||
fprintf(stderr, "Interpreter (internal to DtDocBook) error\n");
|
||||
strcpy(errMessVar, errMessConst);
|
||||
Tcl_Eval(interpreter, errMessVar);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Process an "output" translation spec - one of StartText, EndText,
|
||||
* Replace, Message (these are the ones that produce output), or
|
||||
* StartCode and EndCode (these get passed to the interpreter).
|
||||
* Steps done:
|
||||
* Expand attributes and regular variables in input string.
|
||||
* Pass thru string, accumulating chars to be sent to output stream.
|
||||
* If we find the start of a special variable, output what we've
|
||||
* accumulated, then find the special variable's "bounds" (ie, the
|
||||
* stuff between the curly brackets), and expand that by passing to
|
||||
* ExpandSpecialVar(). Continue until done the input string.
|
||||
* Arguments:
|
||||
* Input buffer (string) to be expanded and output.
|
||||
* Pointer to element under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
* Flag saying whether to track the character position we're on
|
||||
* (passed to OutputString).
|
||||
*/
|
||||
void
|
||||
ProcesOutputSpec(
|
||||
char *ib,
|
||||
Element_t *e,
|
||||
FILE *fp,
|
||||
int track_pos
|
||||
)
|
||||
{
|
||||
char obuf[LINESIZE];
|
||||
char vbuf[LINESIZE];
|
||||
char *dest, vname[LINESIZE], *cp;
|
||||
int esc;
|
||||
|
||||
obuf[0] = EOS; /* start with empty output buffer */
|
||||
|
||||
ExpandVariables(ib, vbuf, e); /* expand regular variables */
|
||||
ib = vbuf;
|
||||
dest = obuf;
|
||||
|
||||
esc = 0;
|
||||
while (*ib) {
|
||||
/* Is esc-$ next? If so, just copy the '$'. */
|
||||
if (*ib == '\\' && ib[1] == VDELIM) {
|
||||
ib++; /* skip esc */
|
||||
*dest++ = *ib++; /* copy $ */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* If not a $, it's a regular char. Just copy it and go to next. */
|
||||
if (*ib != VDELIM) { /* look for att/variable marker */
|
||||
*dest++ = *ib++; /* it's not. just copy character */
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We have a $. What we have must be a "special variable" since
|
||||
* regular variables have already been expanded, or just a lone $. */
|
||||
|
||||
if (ib[1] != L_CURLY) { /* just a stray dollar sign (no variable) */
|
||||
*dest++ = *ib++;
|
||||
continue;
|
||||
}
|
||||
|
||||
ib++; /* point past $ */
|
||||
|
||||
/* Output what we have in buffer so far. */
|
||||
*dest = EOS; /* terminate string */
|
||||
if (obuf[0]) OutputString(obuf, fp, track_pos);
|
||||
dest = obuf; /* ready for new stuff in buffer */
|
||||
|
||||
if (!strchr(ib, R_CURLY)) {
|
||||
fprintf(stderr, "Mismatched braces in TranSpec: %s\n", ib);
|
||||
/* how do we recover from this? */
|
||||
}
|
||||
ib++;
|
||||
cp = vname;
|
||||
while (*ib && *ib != R_CURLY) *cp++ = *ib++;
|
||||
*cp = EOS; /* terminate att/var name */
|
||||
ib++; /* point past closing curly */
|
||||
/* we now have special variable name (stuff in curly {}'s) in vname */
|
||||
/* if the special variable is _break and it's true, we're done */
|
||||
if (ExpandSpecialVar(&vname[1], e, fp, track_pos) == CONT_BREAK) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
*dest = EOS; /* terminate string in output buffer */
|
||||
|
||||
if (obuf[0]) OutputString(obuf, fp, track_pos);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Find the translation spec for the given tag.
|
||||
* Returns pointer to first spec that matches (name, depth, etc., of tag).
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* Return:
|
||||
* Pointer to translation spec that matches given element's context.
|
||||
*/
|
||||
|
||||
Trans_t *
|
||||
FindTrans(
|
||||
Element_t *e
|
||||
)
|
||||
{
|
||||
char context[LINESIZE], *cp, **vec, *atval;
|
||||
int i, a, match;
|
||||
Trans_t *t, *tt;
|
||||
|
||||
/* loop through all transpecs */
|
||||
for (t=TrSpecs; t; t=t->next)
|
||||
{
|
||||
/* Only one of gi or gilist will be set. */
|
||||
/* Check if elem name matches */
|
||||
if (t->gi && !StrEq(t->gi, e->gi)) continue;
|
||||
|
||||
/* Match one in the list of GIs? */
|
||||
if (t->gilist) {
|
||||
for (match=0,vec=t->gilist; *vec; vec++) {
|
||||
if (StrEq(*vec, e->gi)) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) continue;
|
||||
}
|
||||
|
||||
/* Check context */
|
||||
|
||||
/* Special case of context */
|
||||
if (t->parent)
|
||||
if (!QRelation(e, t->parent, REL_Parent)) continue;
|
||||
|
||||
if (t->context) { /* no context specified -> a match */
|
||||
FindContext(e, t->depth, context);
|
||||
|
||||
if (regexec(&t->context_re, context, 0, NULL, 0)) continue;
|
||||
|
||||
/* Is depth of spec deeper than element's depth? */
|
||||
if (t->depth > e->depth) continue;
|
||||
|
||||
/* See if context of element matches "context" of transpec */
|
||||
match = ( (t->context[0] == context[0]) &&
|
||||
!strcmp(t->context, context) );
|
||||
if (!match) continue;
|
||||
}
|
||||
|
||||
/* Check attributes. Loop through list, comparing each. */
|
||||
if (t->nattpairs) { /* no att specified -> a match */
|
||||
for (match=1,a=0; a<t->nattpairs; a++) {
|
||||
if (!(atval = FindAttValByName(e, t->attpair[a].name))) {
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
if (regexec(&t->attpair[a].rex, atval, 0, NULL, 0))
|
||||
match = 0;
|
||||
}
|
||||
if (!match) continue;
|
||||
}
|
||||
|
||||
/* Check relationships: child, parent, ancestor, sib, ... */
|
||||
if (t->relations) {
|
||||
Mapping_t *r;
|
||||
match = 1;
|
||||
for (r=t->relations->maps,i=0; i<t->relations->n_used; i++) {
|
||||
if (!CheckRelation(e, r[i].name, r[i].sval, 0, 0, RA_Current)) {
|
||||
match = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) continue;
|
||||
}
|
||||
|
||||
/* check this element's parent's attribute */
|
||||
if (t->pattrset && e->parent) {
|
||||
char *p, **tok;
|
||||
|
||||
i = 2;
|
||||
match = 1;
|
||||
tok = Split(t->pattrset, &i, S_STRDUP);
|
||||
if ( i == 2 ) {
|
||||
p = FindAttValByName(e->parent, tok[0]);
|
||||
if ( !p || strcmp(p, tok[1]) )
|
||||
match = 0;
|
||||
} else {
|
||||
if (!FindAttValByName(e->parent, t->pattrset))
|
||||
match = 0;
|
||||
}
|
||||
free(tok[0]);
|
||||
if (!match) continue;
|
||||
}
|
||||
|
||||
/* check this element's "birth order" */
|
||||
if (t->nth_child) {
|
||||
/* First one is called "1" by the user. Internally called "0". */
|
||||
i = t->nth_child;
|
||||
if (i > 0) { /* positive # -- count from beginning */
|
||||
if (e->my_eorder != (i-1)) continue;
|
||||
}
|
||||
else { /* negative # -- count from end */
|
||||
i = e->parent->necont + i;
|
||||
if (e->my_eorder != i) continue;
|
||||
}
|
||||
}
|
||||
|
||||
/* check that variables match */
|
||||
if (t->var_name) {
|
||||
cp = FindMappingVal(Variables, t->var_name);
|
||||
if (!cp || strcmp(cp, t->var_value)) continue;
|
||||
}
|
||||
|
||||
/* check content */
|
||||
if (t->content) { /* no att specified -> a match */
|
||||
for (match=0,i=0; i<e->ndcont; i++) {
|
||||
if (!regexec(&t->content_re, e->dcont[i], 0, NULL, 0)) {
|
||||
match = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) continue;
|
||||
}
|
||||
|
||||
/* -------- at this point we've passed all criteria -------- */
|
||||
|
||||
/* See if we should be using another transpec's actions. */
|
||||
if (t->use_id) {
|
||||
if (t->use_id < 0) return &NullTrans; /* missing? */
|
||||
/* see if we have a pointer to that transpec */
|
||||
if (t->use_trans) return t->use_trans;
|
||||
for (tt=TrSpecs; tt; tt=tt->next) {
|
||||
if (t->use_id == tt->my_id) {
|
||||
/* remember pointer for next time */
|
||||
t->use_trans = tt;
|
||||
return t->use_trans;
|
||||
}
|
||||
}
|
||||
t->use_id = -1; /* flag it as missing */
|
||||
fprintf(stderr, "Warning: transpec ID (%d) not found for %s.\n",
|
||||
t->use_id, e->gi);
|
||||
return &NullTrans;
|
||||
}
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/* At this point, we have not found a matching spec. See if there
|
||||
* is a wildcard, and if so, use it. (Wildcard GI is named "*".) */
|
||||
if ((t = FindTransByName("*"))) return t;
|
||||
|
||||
if (warnings)
|
||||
fprintf(stderr, "Warning: transpec not found for %s\n", e->gi);
|
||||
|
||||
/* default spec - pass character data and descend node */
|
||||
return &NullTrans;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Find translation spec by (GI) name. Returns the first one that matches.
|
||||
* Arguments:
|
||||
* Pointer to name of transpec (the "gi" field of the Trans structure).
|
||||
* Return:
|
||||
* Pointer to translation spec that matches name.
|
||||
*/
|
||||
|
||||
Trans_t *
|
||||
FindTransByName(
|
||||
char *s
|
||||
)
|
||||
{
|
||||
Trans_t *t;
|
||||
|
||||
for (t=TrSpecs; t; t=t->next) {
|
||||
/* check if tag name matches (first check 1st char, for efficiency) */
|
||||
if (t->gi) {
|
||||
if (*(t->gi) != *s) continue; /* check 1st character */
|
||||
if (!strcmp(t->gi, s)) return t;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Find translation spec by its ID (SpecID).
|
||||
* Arguments:
|
||||
* Spec ID (an int).
|
||||
* Return:
|
||||
* Pointer to translation spec that matches name.
|
||||
*/
|
||||
Trans_t *
|
||||
FindTranByID(int n)
|
||||
{
|
||||
Trans_t *t;
|
||||
|
||||
for (t=TrSpecs; t; t=t->next)
|
||||
if (n == t->my_id) return t;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Process a "chunk" of content data of an element.
|
||||
* Arguments:
|
||||
* Pointer to data content to process
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
|
||||
void
|
||||
DoData(
|
||||
char *data,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
char *cp, buf[LINESIZE], *dp, *sub, prev;
|
||||
int i, mapped;
|
||||
|
||||
/* Worry about embedded newlines? */
|
||||
|
||||
if (!fp) return;
|
||||
|
||||
/* CLEANUP: this should really all be done in OutputString(). (I think) */
|
||||
|
||||
if (nCharMap) {
|
||||
/* for each character, see if it's mapped to something else */
|
||||
for (prev=0,cp=data,dp=buf; *cp; cp++) {
|
||||
if (prev == '\\') {
|
||||
*dp++ = *cp;
|
||||
prev = *cp;
|
||||
continue;
|
||||
}
|
||||
for (mapped=0,i=0; i<nCharMap; i++) {
|
||||
if (*cp != CharMap[i].name[0]) continue;
|
||||
sub = CharMap[i].sval;
|
||||
while (*sub) *dp++ = *sub++;
|
||||
mapped = 1;
|
||||
break;
|
||||
}
|
||||
if (!mapped) *dp++ = *cp;
|
||||
prev = *cp;
|
||||
}
|
||||
*dp = EOS;
|
||||
dp = buf;
|
||||
}
|
||||
else dp = data;
|
||||
OutputString(dp, fp, 1);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Handle a processing instruction. This is done similarly to elements,
|
||||
* where we find a transpec, then do what it says. Differences: PI names
|
||||
* start with '_' in the spec file (if a GI does not start with '_', it
|
||||
* may be forced to upper case, sgmls keeps PIs as mixed case); the args
|
||||
* to the PI are treated as the data of an element.
|
||||
* Arguments:
|
||||
* Pointer to the PI.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
|
||||
void
|
||||
DoPI(
|
||||
char *pi,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
char buf[250], **tok;
|
||||
int n;
|
||||
Trans_t *t;
|
||||
|
||||
buf[0] = '_';
|
||||
strcpy(&buf[1], pi);
|
||||
n = 2;
|
||||
tok = Split(buf, &n, 0);
|
||||
if ((t = FindTransByName(tok[0]))) {
|
||||
if (t->replace) ProcesOutputSpec(t->replace, 0, fp, 1);
|
||||
else {
|
||||
if (t->starttext) ProcesOutputSpec(t->starttext, 0, fp, 1);
|
||||
if (t->startcode) CallInterpreter(t->startcode, 0);
|
||||
if (n > 1) OutputString(tok[1], fp, 1);
|
||||
if (t->endcode) CallInterpreter(t->endcode, 0);
|
||||
if (t->endtext) ProcesOutputSpec(t->endtext, 0, fp, 1);
|
||||
}
|
||||
if (t->message) ProcesOutputSpec(t->message, 0, stderr, 0);
|
||||
}
|
||||
else {
|
||||
/* If not found, just print the PI in square brackets, along
|
||||
* with a warning message. */
|
||||
/* fprintf(fp, "[%s]", pi); don't clutter up the output -- steve */
|
||||
if (warnings) fprintf(stderr, "Warning: Unrecognized PI: [%s]\n", pi);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Set and increment variables, as appropriate, if the transpec says to.
|
||||
* Arguments:
|
||||
* Pointer to translation spec for current element.
|
||||
*/
|
||||
|
||||
static void
|
||||
set_and_increment(
|
||||
Trans_t *t
|
||||
)
|
||||
{
|
||||
Mapping_t *m;
|
||||
int i, inc, n;
|
||||
char *cp, buf[50];
|
||||
|
||||
/* set/reset variables */
|
||||
if (t->set_var) {
|
||||
for (m=t->set_var->maps,i=0; i<t->set_var->n_used; i++)
|
||||
SetMappingNV(Variables, m[i].name, m[i].sval);
|
||||
}
|
||||
|
||||
/* increment counters */
|
||||
if (t->incr_var) {
|
||||
for (m=t->incr_var->maps,i=0; i<t->incr_var->n_used; i++) {
|
||||
cp = FindMappingVal(Variables, m[i].name);
|
||||
/* if not set at all, set to 1 */
|
||||
if (!cp) SetMappingNV(Variables, m[i].name, "1");
|
||||
else {
|
||||
if (isdigit(*cp) || (*cp == '-' && isdigit(cp[1]))) {
|
||||
n = atoi(cp);
|
||||
if (m[i].sval && isdigit(*m[i].sval)) inc = atoi(m[i].sval);
|
||||
else inc = 1;
|
||||
sprintf(buf, "%d", (n + inc));
|
||||
SetMappingNV(Variables, m[i].name, buf);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Translate one element.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
* Pointer to translation spec for current element, or null.
|
||||
*/
|
||||
void
|
||||
TransElement(
|
||||
Element_t *e,
|
||||
FILE *fp,
|
||||
Trans_t *t
|
||||
)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!t) t = ((e && e->trans) ? e->trans : &NullTrans);
|
||||
|
||||
/* see if we should quit. */
|
||||
if (t->quit) {
|
||||
fprintf(stderr, "Quitting at location:\n");
|
||||
PrintLocation(e, fp);
|
||||
fprintf(stderr, "%s\n", t->quit);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/* See if we want to replace subtree (do text, don't descend subtree) */
|
||||
if (t->replace) {
|
||||
ProcesOutputSpec(t->replace, e, fp, 1);
|
||||
if (t->message) ProcesOutputSpec(t->message, e, stderr, 0);
|
||||
set_and_increment(t); /* adjust variables, if appropriate */
|
||||
return;
|
||||
}
|
||||
|
||||
if (t->starttext) ProcesOutputSpec(t->starttext, e, fp, 1);
|
||||
if (t->startcode) CallInterpreter(t->startcode, e);
|
||||
if (t->message) ProcesOutputSpec(t->message, e, stderr, 0);
|
||||
|
||||
/* Process data for this node and descend child elements/nodes. */
|
||||
if (t->ignore != IGN_ALL) {
|
||||
/* Is there a "generated" node at the front of this one? */
|
||||
if (e->gen_trans[0]) {
|
||||
Trans_t *tp;
|
||||
if ((tp = FindTranByID(e->gen_trans[0]))) {
|
||||
if (tp->starttext) ProcesOutputSpec(tp->starttext, e, fp, 1);
|
||||
if (tp->startcode) CallInterpreter(t->startcode, e);
|
||||
if (tp->message) ProcesOutputSpec(tp->message, e, stderr, 0);
|
||||
if (tp->endcode) CallInterpreter(t->endcode, e);
|
||||
if (tp->endtext) ProcesOutputSpec(tp->endtext, e, fp, 1);
|
||||
}
|
||||
}
|
||||
/* Loop thruthe "nodes", whether data, child element, or PI. */
|
||||
for (i=0; i<e->ncont; i++) {
|
||||
if (IsContElem(e,i)) {
|
||||
if (t->ignore != IGN_CHILDREN) /* skip child nodes? */
|
||||
TransElement(ContElem(e,i), fp, NULL);
|
||||
}
|
||||
else if (IsContData(e,i)) {
|
||||
if (t->ignore != IGN_DATA) /* skip data nodes? */
|
||||
DoData(ContData(e,i), fp);
|
||||
}
|
||||
else if (IsContPI(e,i))
|
||||
DoPI(e->cont[i].ch.data, fp);
|
||||
}
|
||||
/* Is there a "generated" node at the end of this one? */
|
||||
if (e->gen_trans[1]) {
|
||||
Trans_t *tp;
|
||||
if ((tp = FindTranByID(e->gen_trans[1]))) {
|
||||
if (tp->starttext) ProcesOutputSpec(tp->starttext, e, fp, 1);
|
||||
if (tp->startcode) CallInterpreter(t->startcode, e);
|
||||
if (tp->message) ProcesOutputSpec(tp->message, e, stderr, 0);
|
||||
if (tp->endcode) CallInterpreter(t->endcode, e);
|
||||
if (tp->endtext) ProcesOutputSpec(tp->endtext, e, fp, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
set_and_increment(t); /* adjust variables, if appropriate */
|
||||
|
||||
if (t->endcode) CallInterpreter(t->endcode, e);
|
||||
if (t->endtext) ProcesOutputSpec(t->endtext, e, fp, 1);
|
||||
|
||||
e->processed = 1;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Check if element matches specified relationship, and, if it does, perform
|
||||
* action on either current element or matching element (depends on flag).
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* Pointer to relationship name.
|
||||
* Pointer to related element name (GI).
|
||||
* Pointer to action to take (string - turned into an int).
|
||||
* FILE pointer to where to write output.
|
||||
* Flag saying whether to do action on related element (RA_Related)
|
||||
* or on current element (RA_Current).
|
||||
* Return:
|
||||
* Bool, saying whether (1) or not (0) relationship matches.
|
||||
*/
|
||||
|
||||
int
|
||||
CheckRelation(
|
||||
Element_t *e,
|
||||
char *relname, /* relationship name */
|
||||
char *related, /* related element */
|
||||
char *actname, /* action to take */
|
||||
FILE *fp,
|
||||
RelAction_t flag
|
||||
)
|
||||
{
|
||||
Element_t *ep;
|
||||
Relation_t r;
|
||||
|
||||
if ((r = FindRelByName(relname)) == REL_Unknown) return 0;
|
||||
if (!(ep=QRelation(e, related, r))) return 0;
|
||||
|
||||
if (!actname) return 1; /* no action - return what we found */
|
||||
|
||||
switch (flag) {
|
||||
case RA_Related: TranByAction(ep, atoi(actname), fp); break;
|
||||
case RA_Current: TranByAction(e, atoi(actname), fp); break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Perform action given by a SpecID on the given element.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* SpecID of action to perform.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
TranByAction(
|
||||
Element_t *e,
|
||||
int n,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
Trans_t *t;
|
||||
|
||||
t = FindTranByID(n);
|
||||
if (!t) {
|
||||
fprintf(stderr, "Could not find named action for %d.\n", n);
|
||||
return;
|
||||
}
|
||||
TransElement(e, fp, t);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
155
cde/programs/dtdocbook/doc2sdl/instant/translate.h
Normal file
155
cde/programs/dtdocbook/doc2sdl/instant/translate.h
Normal file
@@ -0,0 +1,155 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* Program to manipulate SGML instances.
|
||||
*
|
||||
* These are data definitions for the "translating" portion of the program.
|
||||
*
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#include <regex.h>
|
||||
|
||||
#ifdef STORAGE
|
||||
#ifndef lint
|
||||
static char *tr_h_RCSid =
|
||||
"$XConsortium: translate.h /main/3 1996/06/19 17:13:31 drk $";
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define L_CURLY '{'
|
||||
#define R_CURLY '}'
|
||||
|
||||
/* things to ignore when processing an element */
|
||||
#define IGN_NONE 0
|
||||
#define IGN_ALL 1
|
||||
#define IGN_DATA 2
|
||||
#define IGN_CHILDREN 3
|
||||
|
||||
/* for CheckRelation() */
|
||||
typedef enum { RA_Current, RA_Related } RelAction_t;
|
||||
|
||||
/* for ExpandSpecialVar() */
|
||||
typedef enum { CONT_CONTINUE, CONT_BREAK } ContParse_t;
|
||||
|
||||
typedef struct {
|
||||
char *name; /* attribute name string */
|
||||
char *val; /* attribute value string */
|
||||
regex_t rex; /* attribute value reg expr (compiled) */
|
||||
} AttPair_t;
|
||||
|
||||
typedef struct _Trans {
|
||||
/* criteria */
|
||||
char *gi; /* element name of tag under consideration */
|
||||
char **gilist; /* list of element names (multiple gi's) */
|
||||
char *context; /* context in tree - looking depth levels up */
|
||||
regex_t context_re; /* tree hierarchy looking depth levels up */
|
||||
int depth; /* number of levels to look up the tree */
|
||||
AttPair_t *attpair; /* attr name-value pairs */
|
||||
int nattpairs; /* number of name-value pairs */
|
||||
char *parent; /* GI has this element as parent */
|
||||
int nth_child; /* GI is Nth child of this of parent element */
|
||||
char *content; /* element has this string in content */
|
||||
regex_t content_re; /* content reg expr (compiled) */
|
||||
char *pattrset; /* is this attr set (any value) in parent? */
|
||||
char *var_name; /* variable name */
|
||||
char *var_value; /* variable value */
|
||||
Map_t *relations; /* various relations to check */
|
||||
|
||||
/* actions */
|
||||
char *starttext; /* string to output at the start tag */
|
||||
char *startcode; /* Tcl code to execute at the start tag */
|
||||
char *endtext; /* string to output at the end tag */
|
||||
char *endcode; /* Tcl code to execute at the end tag */
|
||||
char *replace; /* string to replace this subtree with */
|
||||
char *message; /* message for stderr, if element encountered */
|
||||
int ignore; /* flag - ignore content or data of element? */
|
||||
char *var_reset;
|
||||
char *increment; /* increment these variables */
|
||||
Map_t *set_var; /* set these variables */
|
||||
Map_t *incr_var; /* increment these variables */
|
||||
char *quit; /* print message and exit */
|
||||
|
||||
/* pointers and bookkeeping */
|
||||
int my_id; /* unique (hopefully) ID of this transpec */
|
||||
int use_id; /* use transpec whose ID is this */
|
||||
struct _Trans *use_trans; /* pointer to other transpec */
|
||||
struct _Trans *next; /* linked list */
|
||||
int lineno; /* line number of end of transpec */
|
||||
} Trans_t;
|
||||
|
||||
#ifdef def
|
||||
#undef def
|
||||
#endif
|
||||
#ifdef STORAGE
|
||||
# define def
|
||||
#else
|
||||
# define def extern
|
||||
#endif
|
||||
|
||||
def Trans_t *TrSpecs;
|
||||
def Mapping_t *CharMap;
|
||||
def int nCharMap;
|
||||
|
||||
/* prototypes for things defined in translate.c */
|
||||
int CheckRelation(Element_t *, char *, char *, char *, FILE*, RelAction_t);
|
||||
Trans_t *FindTrans(Element_t *);
|
||||
Trans_t *FindTransByName(char *);
|
||||
Trans_t *FindTransByID(int);
|
||||
void PrepTranspecs(Element_t *);
|
||||
void ProcessOneSpec(char *, Element_t *, FILE *, int);
|
||||
void TransElement(Element_t *, FILE *, Trans_t *);
|
||||
void TranByAction(Element_t *, int, FILE *);
|
||||
|
||||
/* prototypes for things defined in tranvar.c */
|
||||
ContParse_t ExpandSpecialVar(char *, Element_t *, FILE *, int);
|
||||
|
||||
/* prototypes for things defined in tables.c */
|
||||
void OSFtable(Element_t *, FILE *, char **, int);
|
||||
|
||||
/* prototypes for things defines in util.c */
|
||||
void ClearOutputBuffer();
|
||||
char *GetOutputBuffer();
|
||||
int OutputBufferActive();
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
801
cde/programs/dtdocbook/doc2sdl/instant/tranvar.c
Normal file
801
cde/programs/dtdocbook/doc2sdl/instant/tranvar.c
Normal file
@@ -0,0 +1,801 @@
|
||||
/*
|
||||
* CDE - Common Desktop Environment
|
||||
*
|
||||
* Copyright (c) 1993-2012, The Open Group. All rights reserved.
|
||||
*
|
||||
* These libraries and programs are free software; you can
|
||||
* redistribute them and/or modify them under the terms of the GNU
|
||||
* Lesser General Public License as published by the Free Software
|
||||
* Foundation; either version 2 of the License, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* These libraries and programs are distributed in the hope that
|
||||
* they will be useful, but WITHOUT ANY WARRANTY; without even the
|
||||
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU Lesser General Public License for more
|
||||
* details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with these libraries and programs; if not, write
|
||||
* to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
|
||||
* Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
/*
|
||||
* Copyright 1993 Open Software Foundation, Inc., Cambridge, Massachusetts.
|
||||
* All rights reserved.
|
||||
*/
|
||||
/*
|
||||
* Copyright (c) 1994
|
||||
* Open Software Foundation, Inc.
|
||||
*
|
||||
* Permission is hereby granted to use, copy, modify and freely distribute
|
||||
* the software in this file and its documentation for any purpose without
|
||||
* fee, provided that the above copyright notice appears in all copies and
|
||||
* that both the copyright notice and this permission notice appear in
|
||||
* supporting documentation. Further, provided that the name of Open
|
||||
* Software Foundation, Inc. ("OSF") not be used in advertising or
|
||||
* publicity pertaining to distribution of the software without prior
|
||||
* written permission from OSF. OSF makes no representations about the
|
||||
* suitability of this software for any purpose. It is provided "as is"
|
||||
* without express or implied warranty.
|
||||
*/
|
||||
/* ________________________________________________________________________
|
||||
*
|
||||
* instant - a program to manipulate SGML instances.
|
||||
*
|
||||
* This module is for handling "special variables". These act a lot like
|
||||
* procedure calls
|
||||
* ________________________________________________________________________
|
||||
*/
|
||||
|
||||
#ifndef lint
|
||||
static char *RCSid =
|
||||
"$XConsortium: tranvar.c /main/7 1996/08/08 14:42:09 cde-hp $";
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <ctype.h>
|
||||
#include <string.h>
|
||||
#include <memory.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "general.h"
|
||||
#include "translate.h"
|
||||
|
||||
static char **idrefs; /* list of IDREF att names to follow */
|
||||
static char *def_idrefs[] = { "LINKEND", "LINKENDS", "IDREF", 0 };
|
||||
|
||||
/* forward references */
|
||||
void ChaseIDRefs(Element_t *, char *, int, FILE *);
|
||||
void Find(Element_t *, int, char **, FILE *);
|
||||
void GetIDREFnames();
|
||||
|
||||
static void OutputCDATA(Content_t *cp, void *client_data);
|
||||
typedef struct _cdata_info {
|
||||
int track_pos;
|
||||
FILE *fp;
|
||||
} OutputCDATA_info_t;
|
||||
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Handle "special" variable - read file, run command, do action, etc.
|
||||
* Arguments:
|
||||
* Name of special variable to expand.
|
||||
* Pointer to element under consideration.
|
||||
* FILE pointer to where to write output.
|
||||
* Flag saying whether to track the character position we're on
|
||||
* (passed to OutputString).
|
||||
*/
|
||||
|
||||
ContParse_t
|
||||
ExpandSpecialVar(
|
||||
char *name,
|
||||
Element_t *e,
|
||||
FILE *fp,
|
||||
int track_pos
|
||||
)
|
||||
{
|
||||
FILE *infile;
|
||||
char buf[LINESIZE], tempbuf[LINESIZE], *cp, *atval, letter;
|
||||
char **tok;
|
||||
int ntok, n, i, action, action1, number;
|
||||
Element_t *ep;
|
||||
Trans_t *t, *tt;
|
||||
static char *s_A, *s_C;
|
||||
|
||||
/* Run a command.
|
||||
* Format: _! command args ... */
|
||||
if (*name == '!') {
|
||||
name++;
|
||||
if ((infile = popen(name, "r"))) {
|
||||
while (fgets(buf, LINESIZE, infile)) FPuts(buf, fp);
|
||||
pclose(infile);
|
||||
FFlush(fp);
|
||||
}
|
||||
else {
|
||||
fprintf(stderr, "Could not start program '%s': %s",
|
||||
name, strerror(errno));
|
||||
}
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
|
||||
/* See if caller wants one of the tokens from _eachatt or _eachcon.
|
||||
* If so, output it and return. (Yes, I admit that this is a hack.)
|
||||
*/
|
||||
if (*name == 'A' && name[1] == EOS && s_A) {
|
||||
OutputString(s_A, fp, track_pos);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
if (*name == 'C' && name[1] == EOS && s_C) {
|
||||
OutputString(s_C, fp, track_pos);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
|
||||
ntok = 0;
|
||||
tok = Split(name, &ntok, 0);
|
||||
|
||||
/* Include another file.
|
||||
* Format: _include filename */
|
||||
if (StrEq(tok[0], "include")) {
|
||||
name = tok[1];
|
||||
if (ntok > 1 ) {
|
||||
if ((infile=OpenFile(name)) == NULL) {
|
||||
sprintf(buf, "Can not open included file '%s'", name);
|
||||
perror(buf);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
while (fgets(buf, LINESIZE, infile)) FPuts(buf, fp);
|
||||
fclose(infile);
|
||||
}
|
||||
else fprintf(stderr, "No file name specified for include\n");
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
|
||||
/* Print location (nearest title, line no, path).
|
||||
* Format: _location */
|
||||
else if (StrEq(tok[0], "location")) {
|
||||
PrintLocation(e, fp);
|
||||
}
|
||||
|
||||
/* Print path to this element.
|
||||
* Format: _path */
|
||||
else if (StrEq(tok[0], "path")) {
|
||||
(void)FindElementPath(e, buf);
|
||||
OutputString(buf, fp, track_pos);
|
||||
}
|
||||
|
||||
/* Print name of this element (gi).
|
||||
* Format: _gi [M|L|U] */
|
||||
else if (StrEq(tok[0], "gi")) {
|
||||
strcpy(buf, e->gi);
|
||||
if (ntok >= 2) {
|
||||
if (*tok[1] == 'L' || *tok[1] == 'l' ||
|
||||
*tok[1] == 'M' || *tok[1] == 'm') {
|
||||
for (cp=buf; *cp; cp++)
|
||||
if (isupper(*cp)) *cp = tolower(*cp);
|
||||
}
|
||||
if (*tok[1] == 'M' || *tok[1] == 'm')
|
||||
if (islower(buf[0])) buf[0] = toupper(buf[0]);
|
||||
}
|
||||
OutputString(buf, fp, track_pos);
|
||||
}
|
||||
|
||||
/* Print name of the parent of this element (parent).
|
||||
* If a parent number is given, go that far up the parent tree
|
||||
* (e.g., "_parent 1 U" returns the parent in upper case
|
||||
* "_parent 2 L" returns the grandparent in lower case
|
||||
* "_parent 0" is equivalent to "_gi"
|
||||
* "_parent" is equivalent to "_parent 1")
|
||||
* Format: _parent [<number>] [M|L|U] */
|
||||
else if (StrEq(tok[0], "parent")) {
|
||||
number = 1;
|
||||
letter = 'U';
|
||||
if (ntok >= 2) {
|
||||
if (isdigit(*tok[1])) {
|
||||
number = atoi(tok[1]);
|
||||
if (ntok >= 3) {
|
||||
letter = *tok[2];
|
||||
}
|
||||
} else {
|
||||
letter = *tok[1];
|
||||
}
|
||||
}
|
||||
|
||||
ep = e;
|
||||
while (--number >= 0) {
|
||||
if (ep) ep = ep->parent;
|
||||
}
|
||||
if (ep) {
|
||||
strcpy(buf, ep->gi);
|
||||
} else {
|
||||
*buf = 0;
|
||||
}
|
||||
|
||||
if (letter == 'L' || letter == 'l' ||
|
||||
letter == 'M' || letter == 'm') {
|
||||
for (cp=buf; *cp; cp++)
|
||||
if (isupper(*cp)) *cp = tolower(*cp);
|
||||
}
|
||||
if (letter == 'M' || letter == 'm')
|
||||
if (islower(buf[0])) buf[0] = toupper(buf[0]);
|
||||
|
||||
OutputString(buf, fp, track_pos);
|
||||
}
|
||||
|
||||
/* Print filename of this element's associated external entity.
|
||||
* Format: _filename */
|
||||
else if (StrEq(tok[0], "filename")) {
|
||||
if (!e->entity) {
|
||||
fprintf(stderr, "Expected ext entity (internal error? bug?):\n");
|
||||
PrintLocation(e, stderr);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
if (!e->entity->fname) {
|
||||
fprintf(stderr, "Expected filename ");
|
||||
if (e->entity->sysid) {
|
||||
fprintf(stderr,
|
||||
"(could not find \"%s\"):\n",
|
||||
e->entity->sysid);
|
||||
} else if (e->entity->pubid) {
|
||||
fprintf(stderr,
|
||||
"(could not resolve \"%s\"):\n",
|
||||
e->entity->pubid);
|
||||
} else {
|
||||
fprintf(stderr, "(internal error? bug?):\n");
|
||||
}
|
||||
PrintLocation(e, stderr);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
OutputString(e->entity->fname, fp, track_pos);
|
||||
}
|
||||
|
||||
/* Value of parent's attribute, by attr name.
|
||||
* Format: _pattr attname */
|
||||
else if (StrEq(tok[0], "pattr")) {
|
||||
ep = e->parent;
|
||||
if (!ep) {
|
||||
fprintf(stderr, "Element does not have a parent:\n");
|
||||
PrintLocation(ep, stderr);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
if ((atval = FindAttValByName(ep, tok[1]))) {
|
||||
OutputString(atval, fp, track_pos);
|
||||
}
|
||||
}
|
||||
|
||||
/* Use an action, given transpec's SID.
|
||||
* Format: _action action */
|
||||
else if (StrEq(tok[0], "action")) {
|
||||
action = atoi(tok[1]);
|
||||
if (action) TranByAction(e, action, fp);
|
||||
}
|
||||
|
||||
/* Number of child elements of this element.
|
||||
* Format: _nchild */
|
||||
else if (StrEq(tok[0], "nchild")) {
|
||||
if (ntok > 1) {
|
||||
for (n=0,i=0; i<e->necont; i++)
|
||||
if (StrEq(e->econt[i]->gi, tok[1])) n++;
|
||||
}
|
||||
else n = e->necont;
|
||||
sprintf(buf, "%d", n);
|
||||
OutputString(buf, fp, track_pos);
|
||||
}
|
||||
|
||||
/* number of 1st child's child elements (grandchildren from first child).
|
||||
* Format: _n1gchild */
|
||||
else if (StrEq(tok[0], "n1gchild")) {
|
||||
if (e->necont) {
|
||||
sprintf(buf, "%d", e->econt[0]->necont);
|
||||
OutputString(buf, fp, track_pos);
|
||||
}
|
||||
}
|
||||
|
||||
/* Chase this element's pointers until we hit the named GI.
|
||||
* Do the action if it matches.
|
||||
* Format: _chasetogi gi action */
|
||||
else if (StrEq(tok[0], "chasetogi")) {
|
||||
if (ntok < 3) {
|
||||
fprintf(stderr, "Error: Not enough args for _chasetogi.\n");
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
action = atoi(tok[2]);
|
||||
if (action) ChaseIDRefs(e, tok[1], action, fp);
|
||||
}
|
||||
|
||||
/* Follow link to element pointed to, then do action.
|
||||
* Format: _followlink [attname] action. */
|
||||
else if (StrEq(tok[0], "followlink")) {
|
||||
char **s;
|
||||
if (ntok > 2) {
|
||||
action = atoi(tok[2]);
|
||||
if ((atval = FindAttValByName(e, tok[1]))) {
|
||||
if ((ep = FindElemByID(atval))) {
|
||||
TranByAction(ep, action, fp);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
}
|
||||
else fprintf(stderr, "Error: Did not find attr: %s.\n", tok[1]);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
else action = atoi(tok[1]);
|
||||
GetIDREFnames();
|
||||
for (s=idrefs; *s; s++) {
|
||||
/* is this IDREF attr set? */
|
||||
if ((atval = FindAttValByName(e, *s))) {
|
||||
ntok = 0;
|
||||
tok = Split(atval, &ntok, S_STRDUP);
|
||||
/* we'll follow the first one... */
|
||||
if ((ep = FindElemByID(tok[0]))) {
|
||||
TranByAction(ep, action, fp);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
else fprintf(stderr, "Error: Can not find elem for ID: %s.\n",
|
||||
tok[0]);
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "Error: Element does not have IDREF attribute set:\n");
|
||||
PrintLocation(e, stderr);
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
|
||||
/* Starting at this element, decend tree (in-order), finding GI.
|
||||
* Do the action if it matches.
|
||||
* Format: _find args ... */
|
||||
else if (StrEq(tok[0], "find")) {
|
||||
Find(e, ntok, tok, fp);
|
||||
}
|
||||
|
||||
/* Starting at this element's parent, decend tree (in-order), finding GI.
|
||||
* Do the action if it matches.
|
||||
* Format: _pfind args ... */
|
||||
else if (StrEq(tok[0], "pfind")) {
|
||||
Find(e->parent ? e->parent : e, ntok, tok, fp);
|
||||
}
|
||||
|
||||
/* Content is supposed to be a list of IDREFs. Follow each, doing action.
|
||||
* If 2 actions are specified, use 1st for the 1st ID, 2nd for the rest.
|
||||
* Format: _namelist action [action2] */
|
||||
else if (StrEq(tok[0], "namelist")) {
|
||||
int id;
|
||||
action1 = atoi(tok[1]);
|
||||
if (ntok > 2) action = atoi(tok[2]);
|
||||
else action = action1;
|
||||
for (i=0; i<e->ndcont; i++) {
|
||||
n = 0;
|
||||
tok = Split(e->dcont[i], &n, S_STRDUP);
|
||||
for (id=0; id<n; id++) {
|
||||
if (fold_case)
|
||||
for (cp=tok[id]; *cp; cp++)
|
||||
if (islower(*cp)) *cp = toupper(*cp);
|
||||
if ((e = FindElemByID(tok[id]))) {
|
||||
if (id) TranByAction(e, action, fp);
|
||||
else TranByAction(e, action1, fp); /* first one */
|
||||
}
|
||||
else fprintf(stderr, "Error: Can not find ID: %s.\n", tok[id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* For each word in the element's content, do action.
|
||||
* Format: _eachcon action [action] */
|
||||
else if (StrEq(tok[0], "eachcon")) {
|
||||
int id;
|
||||
action1 = atoi(tok[1]);
|
||||
if (ntok > 3) action = atoi(tok[2]);
|
||||
else action = action1;
|
||||
for (i=0; i<e->ndcont; i++) {
|
||||
n = 0;
|
||||
tok = Split(e->dcont[i], &n, S_STRDUP|S_ALVEC);
|
||||
for (id=0; id<n; id++) {
|
||||
s_C = tok[id];
|
||||
TranByAction(e, action, fp);
|
||||
}
|
||||
free(*tok);
|
||||
}
|
||||
}
|
||||
/* For each word in the given attribute's value, do action.
|
||||
* Format: _eachatt attname action [action] */
|
||||
else if (StrEq(tok[0], "eachatt")) {
|
||||
int id;
|
||||
action1 = atoi(tok[2]);
|
||||
if (ntok > 3) action = atoi(tok[3]);
|
||||
else action = action1;
|
||||
if ((atval = FindAttValByName(e, tok[1]))) {
|
||||
n = 0;
|
||||
tok = Split(atval, &n, S_STRDUP|S_ALVEC);
|
||||
for (id=0; id<n; id++) {
|
||||
s_A = tok[id];
|
||||
if (id) TranByAction(e, action, fp);
|
||||
else TranByAction(e, action1, fp); /* first one */
|
||||
}
|
||||
free(*tok);
|
||||
}
|
||||
}
|
||||
|
||||
/* Do action on this element if element has [relationship] with gi.
|
||||
* Format: _relation relationship gi action [action] */
|
||||
else if (StrEq(tok[0], "relation")) {
|
||||
if (ntok >= 4) {
|
||||
if (!CheckRelation(e, tok[1], tok[2], tok[3], fp, RA_Current)) {
|
||||
/* action not done, see if alt action specified */
|
||||
if (ntok >= 5)
|
||||
TranByAction(e, atoi(tok[4]), fp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Do action on followed element if element has [relationship] with gi.
|
||||
* Format: _followrel relationship gi action */
|
||||
else if (StrEq(tok[0], "followrel")) {
|
||||
if (ntok >= 4)
|
||||
(void)CheckRelation(e, tok[1], tok[2], tok[3], fp, RA_Related);
|
||||
}
|
||||
|
||||
/* Find element with matching ID and do action. If action not specified,
|
||||
* choose the right one appropriate for its context.
|
||||
* Format: _id id [action] */
|
||||
else if (StrEq(tok[0], "id")) {
|
||||
if (ntok > 2) action = atoi(tok[2]);
|
||||
else action = 0;
|
||||
if ((ep = FindElemByID(tok[1]))) {
|
||||
if (action) TranByAction(ep, action, fp);
|
||||
else {
|
||||
t = FindTrans(ep);
|
||||
TransElement(ep, fp, t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Set variable to value.
|
||||
* Format: _set name value */
|
||||
else if (StrEq(tok[0], "set")) {
|
||||
SetMappingNV(Variables, tok[1], tok[2]);
|
||||
}
|
||||
|
||||
/* Do action if variable is set, optionally to value.
|
||||
* If not set, do nothing.
|
||||
* Format: _isset varname [value] action */
|
||||
else if (StrEq(tok[0], "isset")) {
|
||||
if ((cp = FindMappingVal(Variables, tok[1]))) {
|
||||
if (ntok == 3) TranByAction(e, atoi(tok[2]), fp);
|
||||
else if (ntok > 3 && !strcmp(cp, tok[2]))
|
||||
TranByAction(e, atoi(tok[3]), fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* If variable is unset or not set to optional value, return an
|
||||
* indication that the parsing of this specification should
|
||||
* continue; otherwise, return an indication that the parse should
|
||||
* quit. */
|
||||
else if (StrEq(tok[0], "break")) {
|
||||
if ((cp = FindMappingVal(Variables, tok[1]))) {
|
||||
if ((ntok <= 2) || (strcmp(cp, tok[2]) == 0)) return CONT_BREAK;
|
||||
}
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
|
||||
/* Insert a node into the tree at start/end, pointing to action to perform.
|
||||
* Format: _insertnode S|E action */
|
||||
else if (StrEq(tok[0], "insertnode")) {
|
||||
action = atoi(tok[2]);
|
||||
if (*tok[1] == 'S') e->gen_trans[0] = action;
|
||||
else if (*tok[1] == 'E') e->gen_trans[1] = action;
|
||||
}
|
||||
|
||||
/* Do an OSF DTD table spec for TeX or troff. Looks through attributes
|
||||
* and determines what to output. "check" means to check consistency,
|
||||
* and print error messages.
|
||||
* This is (hopefully) the only hard-coded part of the program.
|
||||
* Format: _osftable [tex|roff|check] [cell|top|bottom|rowend] */
|
||||
else if (StrEq(tok[0], "osftable")) {
|
||||
OSFtable(e, fp, tok, ntok);
|
||||
}
|
||||
|
||||
/* Do action if element's attr is set, optionally to value.
|
||||
* If not set, do nothing.
|
||||
* Format: _attval att [value] action */
|
||||
else if (StrEq(tok[0], "attval")) {
|
||||
if ((atval = FindAttValByName(e, tok[1]))) {
|
||||
if (ntok == 3) TranByAction(e, atoi(tok[2]), fp);
|
||||
else if (ntok > 3 && !strcmp(atval, tok[2]))
|
||||
TranByAction(e, atoi(tok[3]), fp);
|
||||
}
|
||||
}
|
||||
/* Same thing, but look at parent */
|
||||
else if (StrEq(tok[0], "pattval")) {
|
||||
if ((atval = FindAttValByName(e->parent, tok[1]))) {
|
||||
if (ntok == 3) {
|
||||
TranByAction(e, atoi(tok[2]), fp);
|
||||
}
|
||||
if (ntok > 3 && !strcmp(atval, tok[2]))
|
||||
TranByAction(e, atoi(tok[3]), fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print each attribute and value for the current element, hopefully
|
||||
* in a legal sgml form: <elem-name att1="value1" att2="value2:> .
|
||||
* Format: _allatts */
|
||||
else if (StrEq(tok[0], "allatts")) {
|
||||
for (i=0; i<e->natts; i++) {
|
||||
if (i != 0) Putc(' ', fp);
|
||||
FPuts(e->atts[i].name, fp);
|
||||
FPuts("=\"", fp);
|
||||
FPuts(e->atts[i].sval, fp);
|
||||
Putc('"', fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* Print the element's input filename, and optionally, the line number.
|
||||
* Format: _infile [line] */
|
||||
else if (StrEq(tok[0], "infile")) {
|
||||
if (e->infile) {
|
||||
if (ntok > 1 && !strcmp(tok[1], "root")) {
|
||||
strcpy(buf, e->infile);
|
||||
if ((cp = strrchr(buf, '.'))) *cp = EOS;
|
||||
FPuts(buf, fp);
|
||||
}
|
||||
else {
|
||||
FPuts(e->infile, fp);
|
||||
if (ntok > 1 && !strcmp(tok[1], "line"))
|
||||
{
|
||||
sprintf(tempbuf, " %d", e->lineno);
|
||||
FPuts(tempbuf, fp);
|
||||
}
|
||||
}
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
else FPuts("input-file??", fp);
|
||||
}
|
||||
|
||||
/* Get value of an environement variable */
|
||||
else if (StrEq(tok[0], "env")) {
|
||||
if (ntok > 1 && (cp = getenv(tok[1]))) {
|
||||
OutputString(cp, fp, track_pos);
|
||||
}
|
||||
}
|
||||
|
||||
/* Get the cdata content of the node (and descendents) */
|
||||
else if (StrEq(tok[0], "cdata")) {
|
||||
OutputCDATA_info_t client_data;
|
||||
|
||||
client_data.track_pos = track_pos;
|
||||
client_data.fp = fp;
|
||||
DescendTree(e, 0, 0, OutputCDATA, (void *) &client_data);
|
||||
}
|
||||
|
||||
/* Something unknown */
|
||||
else {
|
||||
fprintf(stderr, "Unknown special variable: %s\n", tok[0]);
|
||||
tt = e->trans;
|
||||
if (tt && tt->lineno)
|
||||
fprintf(stderr, "Used in transpec, line %d\n", tt->lineno);
|
||||
}
|
||||
return CONT_CONTINUE;
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* A routine to pass to DescendTree(). This routine will be called
|
||||
* on each data node in the tree from the current element (e) down -
|
||||
* putting any cdata on the output stream.
|
||||
* Arguments:
|
||||
* Pointer to content of the node
|
||||
* Client data - holds fp and track_pos from ExpandSpecialVariable()
|
||||
*/
|
||||
static void
|
||||
OutputCDATA(Content_t *cp, void *client_data)
|
||||
{
|
||||
OutputCDATA_info_t *pInfo = (OutputCDATA_info_t *) client_data;
|
||||
|
||||
if (cp->type == CMD_DATA)
|
||||
OutputString(cp->ch.data, pInfo->fp, pInfo->track_pos);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Chase IDs until we find an element whose GI matches. We also check
|
||||
* child element names, not just the names of elements directly pointed
|
||||
* at (by IDREF attributes).
|
||||
*/
|
||||
|
||||
void
|
||||
GetIDREFnames(void)
|
||||
{
|
||||
char *cp;
|
||||
|
||||
if (!idrefs) {
|
||||
/* did user or transpec set the variable */
|
||||
if ((cp = FindMappingVal(Variables, "link_atts")))
|
||||
idrefs = Split(cp, 0, S_STRDUP|S_ALVEC);
|
||||
else
|
||||
idrefs = def_idrefs;
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Chase ID references - follow IDREF(s) attributes until we find
|
||||
* a GI named 'gi', then perform given action on that GI.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* Name of GI we're looking for.
|
||||
* Spec ID of action to take.
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
ChaseIDRefs(
|
||||
Element_t *e,
|
||||
char *gi,
|
||||
int action,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
int ntok, i, ei;
|
||||
char **tok, **s, *atval;
|
||||
|
||||
/* First, see if we got what we came for with this element */
|
||||
if (StrEq(e->gi, gi)) {
|
||||
TranByAction(e, action, fp);
|
||||
return;
|
||||
}
|
||||
GetIDREFnames();
|
||||
|
||||
/* loop for each attribute of type IDREF(s) */
|
||||
for (s=idrefs; *s; s++) {
|
||||
/* is this IDREF attr set? */
|
||||
if ((atval = FindAttValByName(e, *s))) {
|
||||
ntok = 0;
|
||||
tok = Split(atval, &ntok, 0);
|
||||
for (i=0; i<ntok; i++) {
|
||||
/* get element pointed to */
|
||||
if ((e = FindElemByID(tok[i]))) {
|
||||
/* OK, we found a matching GI name */
|
||||
if (StrEq(e->gi, gi)) {
|
||||
/* process using named action */
|
||||
TranByAction(e, action, fp);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
/* this elem itself did not match, try its children */
|
||||
for (ei=0; ei<e->necont; ei++) {
|
||||
if (StrEq(e->econt[ei]->gi, gi)) {
|
||||
TranByAction(e->econt[ei], action, fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
/* try this elem's IDREF attributes */
|
||||
ChaseIDRefs(e, gi, action, fp);
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
/* should not happen, since parser checks ID/IDREFs */
|
||||
fprintf(stderr, "Error: Could not find ID %s\n", atval);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* if the pointers didn't lead to the GI, give error */
|
||||
if (!s)
|
||||
fprintf(stderr, "Error: Could not find '%s'\n", gi);
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
/* state to pass to recursive routines - so we don't have to use
|
||||
* global variables. */
|
||||
typedef struct {
|
||||
char *gi;
|
||||
char *gi2;
|
||||
int action;
|
||||
Element_t *elem;
|
||||
FILE *fp;
|
||||
} Descent_t;
|
||||
|
||||
static void
|
||||
tr_find_gi(
|
||||
Element_t *e,
|
||||
Descent_t *ds
|
||||
)
|
||||
{
|
||||
if (StrEq(ds->gi, e->gi))
|
||||
if (ds->action) TranByAction(e, ds->action, ds->fp);
|
||||
}
|
||||
|
||||
static void
|
||||
tr_find_gipar(
|
||||
Element_t *e,
|
||||
Descent_t *ds
|
||||
)
|
||||
{
|
||||
if (StrEq(ds->gi, e->gi) && e->parent &&
|
||||
StrEq(ds->gi2, e->parent->gi))
|
||||
if (ds->action) TranByAction(e, ds->action, ds->fp);
|
||||
}
|
||||
|
||||
static void
|
||||
tr_find_attr(
|
||||
Element_t *e,
|
||||
Descent_t *ds
|
||||
)
|
||||
{
|
||||
char *atval;
|
||||
if ((atval = FindAttValByName(e, ds->gi)) && StrEq(ds->gi2, atval))
|
||||
TranByAction(e, ds->action, ds->fp);
|
||||
}
|
||||
|
||||
static void
|
||||
tr_find_parent(
|
||||
Element_t *e,
|
||||
Descent_t *ds
|
||||
)
|
||||
{
|
||||
if (QRelation(e, ds->gi, REL_Parent)) {
|
||||
if (ds->action) TranByAction(e, ds->action, ds->fp);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
/* Descend tree, finding elements that match criteria, then perform
|
||||
* given action.
|
||||
* Arguments:
|
||||
* Pointer to element under consideration.
|
||||
* Number of tokens in special variable.
|
||||
* Vector of tokens in special variable (eg, "find" "gi" "TITLE")
|
||||
* FILE pointer to where to write output.
|
||||
*/
|
||||
void
|
||||
Find(
|
||||
Element_t *e,
|
||||
int ac,
|
||||
char **av,
|
||||
FILE *fp
|
||||
)
|
||||
{
|
||||
Descent_t DS; /* state passed to recursive routine */
|
||||
|
||||
memset(&DS, 0, sizeof(Descent_t));
|
||||
DS.elem = e;
|
||||
DS.fp = fp;
|
||||
|
||||
/* see if we should start at the top of instance tree */
|
||||
if (StrEq(av[1], "top")) {
|
||||
av++;
|
||||
ac--;
|
||||
e = DocTree;
|
||||
}
|
||||
if (ac < 4) {
|
||||
fprintf(stderr, "Bad '_find' specification - missing args.\n");
|
||||
return;
|
||||
}
|
||||
/* Find elem whose GI is av[2] */
|
||||
if (StrEq(av[1], "gi")) {
|
||||
DS.gi = av[2];
|
||||
DS.action = atoi(av[3]);
|
||||
DescendTree(e, tr_find_gi, 0, 0, &DS);
|
||||
}
|
||||
/* Find elem whose GI is av[2] and whose parent GI is av[3] */
|
||||
else if (StrEq(av[1], "gi-parent")) {
|
||||
DS.gi = av[2];
|
||||
DS.gi2 = av[3];
|
||||
DS.action = atoi(av[4]);
|
||||
DescendTree(e, tr_find_gipar, 0, 0, &DS);
|
||||
}
|
||||
/* Find elem whose parent GI is av[2] */
|
||||
else if (StrEq(av[0], "parent")) {
|
||||
DS.gi = av[2];
|
||||
DS.action = atoi(av[3]);
|
||||
DescendTree(e, tr_find_parent, 0, 0, &DS);
|
||||
}
|
||||
/* Find elem whose attribute av[2] has value av[3] */
|
||||
else if (StrEq(av[0], "attr")) {
|
||||
DS.gi = av[2];
|
||||
DS.gi2 = av[3];
|
||||
DS.action = atoi(av[4]);
|
||||
DescendTree(e, tr_find_attr, 0, 0, &DS);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
1277
cde/programs/dtdocbook/doc2sdl/instant/util.c
Normal file
1277
cde/programs/dtdocbook/doc2sdl/instant/util.c
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user