mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-26 11:47:31 +00:00
279 lines
5.3 KiB
C
279 lines
5.3 KiB
C
/* sgmlsasp.c
|
|
Translate sgmls output using ASP replacement file.
|
|
|
|
Written by James Clark (jjc@jclark.com). */
|
|
|
|
#include "sgmlsasp.h"
|
|
#include "sgmls.h"
|
|
#include "replace.h"
|
|
#include "getopt.h"
|
|
|
|
/* Non-zero if general (non-entity) names should be folded to upper case. */
|
|
int fold_general_names = 1;
|
|
|
|
static char *program_name;
|
|
static char last_char = '\n';
|
|
|
|
static void output_begin_line P((void));
|
|
static void output_data P((struct sgmls_data *, int));
|
|
static void output_pi P((char *, unsigned));
|
|
static void output_token P((char *));
|
|
static void output_attribute P((struct sgmls_attribute *));
|
|
static void output_data_char P((int));
|
|
static void output_replacement
|
|
P((struct replacement *, struct sgmls_attribute *));
|
|
static void do_file P((FILE *, struct replacement_table *));
|
|
static void usage P((void));
|
|
static void input_error P((int, char *, unsigned long));
|
|
|
|
#define output_char(c) (last_char = (c), putchar(c))
|
|
|
|
int main(argc, argv)
|
|
int argc;
|
|
char **argv;
|
|
{
|
|
struct replacement_table *tablep;
|
|
int i;
|
|
int opt;
|
|
program_name = argv[0];
|
|
|
|
while ((opt = getopt(argc, argv, "n")) != EOF)
|
|
switch (opt) {
|
|
case 'n':
|
|
fold_general_names = 0;
|
|
break;
|
|
case '?':
|
|
usage();
|
|
default:
|
|
assert(0);
|
|
}
|
|
if (argc - optind <= 0)
|
|
usage();
|
|
tablep = make_replacement_table();
|
|
for (i = optind; i < argc; i++)
|
|
load_replacement_file(tablep, argv[i]);
|
|
(void)sgmls_set_errhandler(input_error);
|
|
do_file(stdin, tablep);
|
|
exit(0);
|
|
}
|
|
|
|
static
|
|
void usage()
|
|
{
|
|
fprintf(stderr, "usage: %s [-n] replacement_file...\n", program_name);
|
|
exit(1);
|
|
}
|
|
|
|
static
|
|
void input_error(num, str, lineno)
|
|
int num;
|
|
char *str;
|
|
unsigned long lineno;
|
|
{
|
|
error("Error at input line %lu: %s", lineno, str);
|
|
}
|
|
|
|
static
|
|
void do_file(fp, tablep)
|
|
FILE *fp;
|
|
struct replacement_table *tablep;
|
|
{
|
|
struct sgmls *sp;
|
|
struct sgmls_event e;
|
|
|
|
sp = sgmls_create(fp);
|
|
while (sgmls_next(sp, &e))
|
|
switch (e.type) {
|
|
case SGMLS_EVENT_DATA:
|
|
output_data(e.u.data.v, e.u.data.n);
|
|
break;
|
|
case SGMLS_EVENT_ENTITY:
|
|
/* XXX what should we do here? */
|
|
break;
|
|
case SGMLS_EVENT_PI:
|
|
output_pi(e.u.pi.s, e.u.pi.len);
|
|
break;
|
|
case SGMLS_EVENT_START:
|
|
output_replacement(lookup_replacement(tablep,
|
|
START_ELEMENT, e.u.start.gi),
|
|
e.u.start.attributes);
|
|
sgmls_free_attributes(e.u.start.attributes);
|
|
break;
|
|
case SGMLS_EVENT_END:
|
|
output_replacement(lookup_replacement(tablep, END_ELEMENT, e.u.end.gi),
|
|
0);
|
|
break;
|
|
case SGMLS_EVENT_SUBSTART:
|
|
break;
|
|
case SGMLS_EVENT_SUBEND:
|
|
break;
|
|
case SGMLS_EVENT_APPINFO:
|
|
break;
|
|
case SGMLS_EVENT_CONFORMING:
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
sgmls_free(sp);
|
|
}
|
|
|
|
static
|
|
void output_data(v, n)
|
|
struct sgmls_data *v;
|
|
int n;
|
|
{
|
|
int i;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
char *s = v[i].s;
|
|
int len = v[i].len;
|
|
for (; len > 0; len--, s++)
|
|
output_data_char(*s);
|
|
}
|
|
}
|
|
|
|
static
|
|
void output_pi(s, len)
|
|
char *s;
|
|
unsigned len;
|
|
{
|
|
for (; len > 0; len--, s++)
|
|
output_data_char(*s);
|
|
}
|
|
|
|
static
|
|
void output_replacement(repl, attributes)
|
|
struct replacement *repl;
|
|
struct sgmls_attribute *attributes;
|
|
{
|
|
struct replacement_item *p;
|
|
struct sgmls_attribute *a;
|
|
int i;
|
|
|
|
if (!repl)
|
|
return;
|
|
if (repl->flags & NEWLINE_BEGIN)
|
|
output_begin_line();
|
|
|
|
for (p = repl->items; p; p = p->next)
|
|
switch (p->type) {
|
|
case DATA_REPL:
|
|
for (i = 0; i < p->u.data.n; i++)
|
|
output_char(p->u.data.s[i]);
|
|
break;
|
|
case ATTR_REPL:
|
|
for (a = attributes; a; a = a->next)
|
|
if (strcmp(a->name, p->u.attr) == 0) {
|
|
output_attribute(a);
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
|
|
if (repl->flags & NEWLINE_END)
|
|
output_begin_line();
|
|
}
|
|
|
|
static
|
|
void output_attribute(p)
|
|
struct sgmls_attribute *p;
|
|
{
|
|
switch (p->type) {
|
|
case SGMLS_ATTR_IMPLIED:
|
|
break;
|
|
case SGMLS_ATTR_CDATA:
|
|
output_data(p->value.data.v, p->value.data.n);
|
|
break;
|
|
case SGMLS_ATTR_TOKEN:
|
|
{
|
|
char **token = p->value.token.v;
|
|
int n = p->value.token.n;
|
|
|
|
if (n > 0) {
|
|
int i;
|
|
output_token(token[0]);
|
|
for (i = 1; i < n; i++) {
|
|
output_char(' ');
|
|
output_token(token[i]);
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
case SGMLS_ATTR_ENTITY:
|
|
{
|
|
struct sgmls_entity **v = p->value.entity.v;
|
|
int n = p->value.entity.n;
|
|
int i;
|
|
|
|
for (i = 0; i < n; i++) {
|
|
if (i > 0)
|
|
output_char(' ');
|
|
output_token(v[i]->is_internal
|
|
? v[i]->u.internal.name
|
|
: v[i]->u.external.name);
|
|
}
|
|
}
|
|
break;
|
|
case SGMLS_ATTR_NOTATION:
|
|
if (p->value.notation)
|
|
output_token(p->value.notation->name);
|
|
break;
|
|
default:
|
|
abort();
|
|
}
|
|
}
|
|
|
|
static
|
|
void output_token(s)
|
|
char *s;
|
|
{
|
|
for (; *s; s++)
|
|
output_char(*s);
|
|
}
|
|
|
|
static
|
|
void output_data_char(c)
|
|
int c;
|
|
{
|
|
if (c != RSCHAR) {
|
|
if (c == RECHAR)
|
|
c = '\n';
|
|
output_char(c);
|
|
}
|
|
}
|
|
|
|
static
|
|
void output_begin_line()
|
|
{
|
|
if (last_char != '\n')
|
|
output_char('\n');
|
|
}
|
|
|
|
NO_RETURN
|
|
#ifdef VARARGS
|
|
void error(va_alist) va_dcl
|
|
#else
|
|
void error(char *message,...)
|
|
#endif
|
|
{
|
|
#ifdef VARARGS
|
|
char *message;
|
|
#endif
|
|
va_list ap;
|
|
|
|
fprintf(stderr, "%s: ", program_name);
|
|
#ifdef VARARGS
|
|
va_start(ap);
|
|
message = va_arg(ap, char *);
|
|
#else
|
|
va_start(ap, message);
|
|
#endif
|
|
vfprintf(stderr, message, ap);
|
|
va_end(ap);
|
|
fputc('\n', stderr);
|
|
fflush(stderr);
|
|
exit(EXIT_FAILURE);
|
|
}
|