home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Fresh Fish 10
/
Fresh_Fish_10_2352.bin
/
new
/
dev
/
lang
/
sgmls
/
src
/
entgen.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-07-10
|
12KB
|
518 lines
/* entgen.c -
Implement entgen() which generates a list of filenames from a struct fpi.
Written by James Clark (jjc@jclark.com).
*/
#include "config.h"
#ifdef HAVE_ACCESS
#ifdef HAVE_UNISTD_H
#include <unistd.h> /* For R_OK. */
#endif /* HAVE_UNISTD_H */
#ifndef R_OK
#define R_OK 4
#endif /* not R_OK */
#endif /* HAVE_ACCESS */
#include "sgmlaux.h"
/* Environment variable that contains path. */
#ifndef PATH_ENV_VAR
#define PATH_ENV_VAR "SGML_PATH"
#endif
/* Default search path. See field() for interpretation of %*. */
#ifndef DEFAULT_PATH
#define DEFAULT_PATH "/usr/local/lib/sgml/%O/%C/%T:%N.%X:%N.%D"
#endif
#ifndef PATH_FILE_SEP
#define PATH_FILE_SEP ':'
#endif
#ifndef SYSID_FILE_SEP
#define SYSID_FILE_SEP ':'
#endif
/* This says: change space to underscore, slash to percent. */
#ifndef MIN_DAT_SUBS_FROM
#define MIN_DAT_SUBS_FROM " /"
#endif
#ifndef MIN_DAT_SUBS_TO
#define MIN_DAT_SUBS_TO "_%"
#endif
static int field P((struct fpi *, int, char *));
static int mindatcpy P((char *, char *, int, int));
static int testopen P((char *));
static UNIV sysidgen P((char *));
static UNIV catsysidgen P((const char *, const char *));
static const char *basename P((const char *));
static char *path = 0;
/* Non-zero if searching should be performed when a system identifier
is specified. */
static int sysidsrch = 0;
#define EMPTY_VERSION "default"
static char *classes[] = {
"capacity",
"charset",
"notation",
"syntax",
"document",
"dtd",
"elements",
"entities",
"lpd",
"nonsgml",
"shortref",
"subdoc",
"text"
};
/* This is mainly for compatibility with arcsgml. */
static char *genext[] = {
"nsd", /* Non-SGML data entity. */
"gml", /* GML document or text entity. */
"spe", /* System parameter entity. */
"dtd", /* Document type definition. */
"lpd", /* Link process definition. */
"pns", /* Public non-SGML data entity. */
"pge", /* Public general entity. */
"ppe", /* Public parameter entity. */
"pdt", /* Public document type definition. */
"plp", /* Public link process definition. */
"vns", /* Display version non-SGML data entity. */
"vge", /* Display version general entity. */
"vpe", /* Display version parameter entity. */
"vdt", /* Display version document type definition.*/
"vlp", /* Display version link process definition.*/
};
static char *ext[] = {
"sgml", /* SGML subdocument */
"data", /* Data */
"text", /* General text */
"parm", /* Parameter entity */
"dtd", /* Document type definition */
"lpd", /* Link process definition */
};
static CATALOG catalog;
VOID entginit(swp)
struct switches *swp;
{
catalog = swp->catalog;
}
/* Like memcpy, but substitute, fold to lower case (if fold is
non-zero) and null terminate. This is used both for minimum data and
for names. If p is NULL, do nothing. Return len. */
static int mindatcpy(p, q, len, fold)
char *p, *q;
int len;
int fold;
{
static char subsfrom[] = MIN_DAT_SUBS_FROM;
static char substo[] = MIN_DAT_SUBS_TO;
int n;
if (!p)
return len;
for (n = len; --n >= 0; q++) {
char *r = strchr(subsfrom, *q);
if (!r) {
if (fold && ISASCII(*q) && isupper((UNCH)*q))
*p++ = tolower((UNCH)*q);
else
*p++ = *q;
}
else {
int i = r - subsfrom;
if (i < sizeof(substo) - 1)
*p++ = substo[i];
}
}
*p = '\0';
return len;
}
/* Return length of field. Copy into buf if non-NULL. */
static int field(f, c, buf)
struct fpi *f;
int c;
char *buf;
{
int n;
switch (c) {
case '%':
if (buf) {
buf[0] = '%';
buf[1] = '\0';
}
return 1;
case 'N': /* the entity, document or dcn name */
return mindatcpy(buf, (char *)f->fpinm, ustrlen(f->fpinm),
(f->fpistore != 1 && f->fpistore != 2 && f->fpistore != 3
? NAMECASE
: ENTCASE));
case 'D': /* dcn name */
if (f->fpistore != 1) /* not a external data entity */
return -1;
if (f->fpinedcn == 0) /* it's a SUBDOC */
return -1;
return mindatcpy(buf, (char *)f->fpinedcn, ustrlen(f->fpinedcn),
NAMECASE);
case 'X':
/* This is for compatibility with arcsgml */
if (f->fpistore < 1 || f->fpistore > 5)
return -1;
n = (f->fpipubis != 0)*(f->fpiversw > 0 ? 2 : 1)*5+f->fpistore - 1;
if (buf)
strcpy(buf, genext[n]);
return (int)strlen(genext[n]);
case 'Y': /* tYpe */
n = f->fpistore;
if (n < 1 || n > 5)
return -1;
if (n == 1 && f->fpinedcn == 0) /* it's a SUBDOC */
n = 0;
if (buf)
strcpy(buf, ext[n]);
return (int)strlen(ext[n]);
case 'P': /* public identifier */
if (!f->fpipubis)
return -1;
return mindatcpy(buf, (char *)f->fpipubis, ustrlen(f->fpipubis), 0);
case 'S': /* system identifier */
if (!f->fpisysis)
return -1;
else {
UNCH *p;
n = 0;
for (p = f->fpisysis; *p; p++)
if (*p != RSCHAR) {
if (buf)
buf[n] = *p == RECHAR ? '\n' : *p;
n++;
}
return n;
}
}
/* Other fields need a formal public identifier. */
/* return -1 if the formal public identifier was invalid or missing. */
if (f->fpiversw < 0 || !f->fpipubis)
return -1;
switch (c) {
case 'A': /* Is it available? */
return f->fpitt == '+' ? 0 : -1;
case 'I': /* Is it ISO? */
return f->fpiot == '!' ? 0 : -1;
case 'R': /* Is it registered? */
return f->fpiot == '+' ? 0 : -1;
case 'U': /* Is it unregistered? */
return f->fpiot == '-' ? 0 : -1;
case 'L': /* public text language */
if (f->fpic == FPICHARS)
return -1;
/* it's entered in all upper case letters */
return mindatcpy(buf, (char *)f->fpipubis + f->fpil, f->fpill, 1);
case 'O': /* owner identifier */
return mindatcpy(buf, (char *)f->fpipubis + f->fpio, f->fpiol, 0);
case 'C': /* public text class */
n = f->fpic - 1;
if (n < 0 || n >= sizeof(classes)/sizeof(classes[0]))
return -1;
if (buf)
strcpy(buf, classes[n]);
return (int)strlen(classes[n]);
case 'T': /* text description */
return mindatcpy(buf, (char *)f->fpipubis + f->fpit, f->fpitl, 0);
case 'V':
if (f->fpic < FPICMINV) /* class doesn't have version */
return -1;
if (f->fpiversw > 0) /* no version */
return -1;
if (f->fpivl == 0) { /* empty version: */
/* use device-independent version*/
if (buf)
strcpy(buf, EMPTY_VERSION);
return (int)strlen(EMPTY_VERSION);
}
return mindatcpy(buf, (char *)f->fpipubis + f->fpiv, f->fpivl, 0);
case 'E': /* public text designating (escape) sequence */
if (f->fpic != FPICHARS)
return -1;
return mindatcpy(buf, (char *)f->fpipubis + f->fpil, f->fpill, 0);
default:
break;
}
return -1;
}
static int testopen(pathname)
char *pathname;
{
#ifdef HAVE_ACCESS
return access(pathname, R_OK) >= 0;
#else /* not HAVE_ACCESS */
FILE *fp;
fp = fopen(pathname, "r");
if (!fp)
return 0;
fclose(fp);
return 1;
#endif /* not HAVE_ACCESS */
}
/* Return a pointer to an dynamically-allocated buffer that contains
the names of the files containing this entity, with each filename
terminated by a '\0', and with the list of filenames terminated by
another '\0'. */
UNIV entgen(f)
struct fpi *f;
{
char *qname;
char *file;
enum catalog_decl_type dtype;
char *subst = 0;
const char *sysid;
const char *catfile;
assert(f->fpistore != 6); /* Musn't call entgen for a notation. */
if (!path) {
char *p;
char c;
path = getenv(PATH_ENV_VAR);
if (!path)
path = DEFAULT_PATH;
p = path;
/* Only search for system identifiers if path uses %S. */
while ((c = *p++) != '\0')
if (c == '%') {
if (*p == 'S') {
sysidsrch = 1;
break;
}
if (*p != '\0' && *p != PATH_FILE_SEP)
p++;
}
}
if