Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
780
cde/programs/dtdocbook/instant/tranvar.c
Normal file
780
cde/programs/dtdocbook/instant/tranvar.c
Normal file
@@ -0,0 +1,780 @@
|
||||
/*
|
||||
* 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 <tptregexp.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()
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/* ______________________________________________________________________ */
|
||||
|
||||
Reference in New Issue
Block a user