Initial import of the CDE 2.1.30 sources from the Open Group.
This commit is contained in:
468
cde/programs/dtdocbook/sgmls/replace.c
Normal file
468
cde/programs/dtdocbook/sgmls/replace.c
Normal file
@@ -0,0 +1,468 @@
|
||||
/* $XConsortium: replace.c /main/3 1996/06/19 17:16:59 drk $ */
|
||||
/* replace.c
|
||||
Parse ASP style replacement file.
|
||||
|
||||
Written by James Clark (jjc@jclark.com). */
|
||||
|
||||
#include "sgmlsasp.h"
|
||||
#include "replace.h"
|
||||
|
||||
#define TABLE_SIZE 251
|
||||
|
||||
struct table_entry {
|
||||
enum event_type type;
|
||||
char *gi;
|
||||
struct replacement replacement;
|
||||
struct table_entry *next;
|
||||
};
|
||||
|
||||
struct replacement_table {
|
||||
struct table_entry *table[TABLE_SIZE];
|
||||
};
|
||||
|
||||
struct buffer {
|
||||
char *s;
|
||||
unsigned len;
|
||||
unsigned size;
|
||||
};
|
||||
|
||||
/* Tokens returned by get_token(). */
|
||||
|
||||
#define STRING 1
|
||||
#define STAGO 2
|
||||
#define ETAGO 3
|
||||
#define PLUS 4
|
||||
|
||||
static int get P((void));
|
||||
static int peek P((void));
|
||||
static int get_token P((void));
|
||||
static void scan_name P((struct buffer *, int));
|
||||
static struct replacement *define_replacement
|
||||
P((struct replacement_table *, enum event_type, char *));
|
||||
static struct replacement_item **parse_string
|
||||
P((struct replacement_item **, int));
|
||||
static UNIV xmalloc P((unsigned));
|
||||
static UNIV xrealloc P((UNIV, unsigned));
|
||||
static struct replacement_item **add_replacement_data
|
||||
P((struct replacement_item **, char *, unsigned));
|
||||
static struct replacement_item **add_replacement_attr
|
||||
P((struct replacement_item **, char *));
|
||||
static int hash P((enum event_type, char *));
|
||||
static NO_RETURN void parse_error VP((char *,...));
|
||||
static VOID buffer_init P((struct buffer *));
|
||||
static VOID buffer_append P((struct buffer *, int));
|
||||
static char *buffer_extract P((struct buffer *));
|
||||
#if 0
|
||||
static VOID buffer_free P((struct buffer *));
|
||||
#endif
|
||||
|
||||
#define buffer_length(buf) ((buf)->len)
|
||||
|
||||
#define NEW(type) ((type *)xmalloc(sizeof(type)))
|
||||
|
||||
static int current_lineno;
|
||||
static char *current_file;
|
||||
static FILE *fp;
|
||||
|
||||
struct replacement_table *make_replacement_table()
|
||||
{
|
||||
int i;
|
||||
struct replacement_table *tablep;
|
||||
|
||||
tablep = NEW(struct replacement_table);
|
||||
for (i = 0; i < TABLE_SIZE; i++)
|
||||
tablep->table[i] = 0;
|
||||
return tablep;
|
||||
}
|
||||
|
||||
void load_replacement_file(tablep, file)
|
||||
struct replacement_table *tablep;
|
||||
char *file;
|
||||
{
|
||||
int tok;
|
||||
struct buffer name;
|
||||
|
||||
buffer_init(&name);
|
||||
errno = 0;
|
||||
fp = fopen(file, "r");
|
||||
if (!fp) {
|
||||
if (errno)
|
||||
error("can't open `%s': %s", file, strerror(errno));
|
||||
else
|
||||
error("can't open `%s'", file);
|
||||
}
|
||||
|
||||
current_lineno = 1;
|
||||
current_file = file;
|
||||
tok = get_token();
|
||||
while (tok != EOF) {
|
||||
struct replacement *p;
|
||||
struct replacement_item **tail;
|
||||
enum event_type type;
|
||||
|
||||
if (tok != STAGO && tok != ETAGO)
|
||||
parse_error("syntax error");
|
||||
type = tok == STAGO ? START_ELEMENT : END_ELEMENT;
|
||||
scan_name(&name, '>');
|
||||
p = define_replacement(tablep, type, buffer_extract(&name));
|
||||
tok = get_token();
|
||||
if (tok == PLUS) {
|
||||
if (p)
|
||||
p->flags |= NEWLINE_BEGIN;
|
||||
tok = get_token();
|
||||
}
|
||||
tail = p ? &p->items : 0;
|
||||
while (tok == STRING) {
|
||||
tail = parse_string(tail, type == START_ELEMENT);
|
||||
tok = get_token();
|
||||
}
|
||||
if (tok == PLUS) {
|
||||
if (p)
|
||||
p->flags |= NEWLINE_END;
|
||||
tok = get_token();
|
||||
}
|
||||
}
|
||||
fclose(fp);
|
||||
}
|
||||
|
||||
static
|
||||
struct replacement_item **parse_string(tail, recog_attr)
|
||||
struct replacement_item **tail;
|
||||
int recog_attr;
|
||||
{
|
||||
struct buffer buf;
|
||||
unsigned len;
|
||||
|
||||
buffer_init(&buf);
|
||||
for (;;) {
|
||||
int c = get();
|
||||
if (c == '\"')
|
||||
break;
|
||||
if (recog_attr && c == '[') {
|
||||
if (buffer_length(&buf)) {
|
||||
len = buffer_length(&buf);
|
||||
tail = add_replacement_data(tail, buffer_extract(&buf), len);
|
||||
}
|
||||
scan_name(&buf, ']');
|
||||
tail = add_replacement_attr(tail, buffer_extract(&buf));
|
||||
}
|
||||
else {
|
||||
if (c == '\\') {
|
||||
c = get();
|
||||
switch (c) {
|
||||
case EOF:
|
||||
parse_error("unfinished string at end of file");
|
||||
case 's':
|
||||
buffer_append(&buf, ' ');
|
||||
break;
|
||||
case 'n':
|
||||
buffer_append(&buf, '\n');
|
||||
break;
|
||||
case 't':
|
||||
buffer_append(&buf, '\t');
|
||||
break;
|
||||
case 'r':
|
||||
buffer_append(&buf, '\r');
|
||||
break;
|
||||
case 'f':
|
||||
buffer_append(&buf, '\f');
|
||||
break;
|
||||
case '0':
|
||||
case '1':
|
||||
case '2':
|
||||
case '3':
|
||||
case '4':
|
||||
case '5':
|
||||
case '6':
|
||||
case '7':
|
||||
{
|
||||
int val = c - '0';
|
||||
c = peek();
|
||||
if ('0' <= c && c <= '7') {
|
||||
(void)get();
|
||||
val = val*8 + (c - '0');
|
||||
c = peek();
|
||||
if ('0' <= c && c <= '7') {
|
||||
(void)get();
|
||||
val = val*8 + (c - '0');
|
||||
}
|
||||
}
|
||||
buffer_append(&buf, val);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
buffer_append(&buf, c);
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
buffer_append(&buf, c);
|
||||
}
|
||||
}
|
||||
len = buffer_length(&buf);
|
||||
if (len > 0)
|
||||
tail = add_replacement_data(tail, buffer_extract(&buf), len);
|
||||
return tail;
|
||||
}
|
||||
|
||||
static
|
||||
struct replacement_item **add_replacement_data(tail, buf, n)
|
||||
struct replacement_item **tail;
|
||||
char *buf;
|
||||
unsigned n;
|
||||
{
|
||||
if (!tail)
|
||||
free(buf);
|
||||
else {
|
||||
*tail = NEW(struct replacement_item);
|
||||
(*tail)->type = DATA_REPL;
|
||||
(*tail)->u.data.n = n;
|
||||
(*tail)->next = 0;
|
||||
(*tail)->u.data.s = buf;
|
||||
tail = &(*tail)->next;
|
||||
}
|
||||
return tail;
|
||||
}
|
||||
|
||||
static
|
||||
struct replacement_item **add_replacement_attr(tail, name)
|
||||
struct replacement_item **tail;
|
||||
char *name;
|
||||
{
|
||||
if (!tail)
|
||||
free(name);
|
||||
else {
|
||||
*tail = NEW(struct replacement_item);
|
||||
(*tail)->type = ATTR_REPL;
|
||||
(*tail)->next = 0;
|
||||
(*tail)->u.attr = name;
|
||||
tail = &(*tail)->next;
|
||||
}
|
||||
return tail;
|
||||
}
|
||||
|
||||
static
|
||||
int get_token()
|
||||
{
|
||||
int c;
|
||||
|
||||
for (;;) {
|
||||
c = get();
|
||||
while (isspace(c))
|
||||
c = get();
|
||||
if (c != '%')
|
||||
break;
|
||||
do {
|
||||
c = get();
|
||||
if (c == EOF)
|
||||
return EOF;
|
||||
} while (c != '\n');
|
||||
}
|
||||
switch (c) {
|
||||
case '+':
|
||||
return PLUS;
|
||||
case '<':
|
||||
c = peek();
|
||||
if (c == '/') {
|
||||
(void)get();
|
||||
return ETAGO;
|
||||
}
|
||||
return STAGO;
|
||||
case '"':
|
||||
return STRING;
|
||||
case EOF:
|
||||
return EOF;
|
||||
default:
|
||||
parse_error("bad input character `%c'", c);
|
||||
}
|
||||
}
|
||||
|
||||
static
|
||||
void scan_name(buf, term)
|
||||
struct buffer *buf;
|
||||
int term;
|
||||
{
|
||||
int c;
|
||||
for (;;) {
|
||||
c = get();
|
||||
if (c == term)
|
||||
break;
|
||||
if (c == '\n' || c == EOF)
|
||||
parse_error("missing `%c'", term);
|
||||
if (fold_general_names) {
|
||||
if (islower((unsigned char)c))
|
||||
c = toupper((unsigned char)c);
|
||||
}
|
||||
buffer_append(buf, c);
|
||||
}
|
||||
if (buffer_length(buf) == 0)
|
||||
parse_error("empty name");
|
||||
buffer_append(buf, '\0');
|
||||
}
|
||||
|
||||
static
|
||||
int get()
|
||||
{
|
||||
int c = getc(fp);
|
||||
if (c == '\n')
|
||||
current_lineno++;
|
||||
return c;
|
||||
}
|
||||
|
||||
static
|
||||
int peek()
|
||||
{
|
||||
int c = getc(fp);
|
||||
if (c != EOF)
|
||||
ungetc(c, fp);
|
||||
return c;
|
||||
}
|
||||
|
||||
struct replacement *lookup_replacement(tablep, type, name)
|
||||
struct replacement_table *tablep;
|
||||
enum event_type type;
|
||||
char *name;
|
||||
{
|
||||
int h = hash(type, name);
|
||||
struct table_entry *p;
|
||||
|
||||
for (p = tablep->table[h]; p; p = p->next)
|
||||
if (strcmp(name, p->gi) == 0 && type == p->type)
|
||||
return &p->replacement;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Return 0 if already defined. */
|
||||
|
||||
static
|
||||
struct replacement *define_replacement(tablep, type, name)
|
||||
struct replacement_table *tablep;
|
||||
enum event_type type;
|
||||
char *name;
|
||||
{
|
||||
int h = hash(type, name);
|
||||
struct table_entry *p;
|
||||
|
||||
for (p = tablep->table[h]; p; p = p->next)
|
||||
if (strcmp(name, p->gi) == 0 && type == p->type)
|
||||
return 0;
|
||||
p = NEW(struct table_entry);
|
||||
p->next = tablep->table[h];
|
||||
tablep->table[h] = p;
|
||||
p->type = type;
|
||||
p->gi = name;
|
||||
p->replacement.flags = 0;
|
||||
p->replacement.items = 0;
|
||||
return &p->replacement;
|
||||
}
|
||||
|
||||
static
|
||||
VOID buffer_init(buf)
|
||||
struct buffer *buf;
|
||||
{
|
||||
buf->size = buf->len = 0;
|
||||
buf->s = 0;
|
||||
}
|
||||
|
||||
static
|
||||
char *buffer_extract(buf)
|
||||
struct buffer *buf;
|
||||
{
|
||||
char *s = buf->s;
|
||||
buf->s = 0;
|
||||
buf->len = 0;
|
||||
buf->size = 0;
|
||||
return s;
|
||||
}
|
||||
|
||||
#if 0
|
||||
static
|
||||
VOID buffer_free(buf)
|
||||
struct buffer *buf;
|
||||
{
|
||||
if (buf->s) {
|
||||
free((UNIV)buf->s);
|
||||
buf->s = 0;
|
||||
buf->size = buf->size = 0;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static
|
||||
VOID buffer_append(buf, c)
|
||||
struct buffer *buf;
|
||||
int c;
|
||||
{
|
||||
if (buf->len >= buf->size) {
|
||||
if (!buf->size)
|
||||
buf->s = (char *)xmalloc(buf->size = 10);
|
||||
else
|
||||
buf->s = (char *)xrealloc((UNIV)buf->s, buf->size *= 2);
|
||||
}
|
||||
buf->s[buf->len] = c;
|
||||
buf->len += 1;
|
||||
}
|
||||
|
||||
static
|
||||
int hash(type, s)
|
||||
enum event_type type;
|
||||
char *s;
|
||||
{
|
||||
unsigned long h = 0, g;
|
||||
|
||||
while (*s != 0) {
|
||||
h <<= 4;
|
||||
h += *s++;
|
||||
if ((g = h & 0xf0000000) != 0) {
|
||||
h ^= g >> 24;
|
||||
h ^= g;
|
||||
}
|
||||
}
|
||||
h ^= (int)type;
|
||||
return (int)(h % TABLE_SIZE);
|
||||
}
|
||||
|
||||
static
|
||||
UNIV xmalloc(n)
|
||||
unsigned n;
|
||||
{
|
||||
UNIV p = (UNIV)malloc(n);
|
||||
if (!p)
|
||||
parse_error("out of memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
static
|
||||
UNIV xrealloc(p, size)
|
||||
UNIV p;
|
||||
unsigned size;
|
||||
{
|
||||
p = (UNIV)realloc(p, size);
|
||||
if (!p)
|
||||
parse_error("out of memory");
|
||||
return p;
|
||||
}
|
||||
|
||||
static NO_RETURN
|
||||
#ifdef VARARGS
|
||||
void parse_error(va_alist) va_dcl
|
||||
#else
|
||||
void parse_error(char *message,...)
|
||||
#endif
|
||||
{
|
||||
char buf[512];
|
||||
#ifdef VARARGS
|
||||
char *message;
|
||||
#endif
|
||||
va_list ap;
|
||||
|
||||
#ifdef VARARGS
|
||||
va_start(ap);
|
||||
message = va_arg(ap, char *);
|
||||
#else
|
||||
va_start(ap, message);
|
||||
#endif
|
||||
vsprintf(buf, message, ap);
|
||||
va_end(ap);
|
||||
error("%s:%d: %s", current_file, current_lineno, buf);
|
||||
}
|
||||
Reference in New Issue
Block a user