Blame sgmls-1.1/rast.c

Packit 9741aa
/* rast.c
Packit 9741aa
   Translate sgmls output to RAST result format.
Packit 9741aa
Packit 9741aa
   Written by James Clark (jjc@jclark.com). */
Packit 9741aa
Packit 9741aa
#include "config.h"
Packit 9741aa
#include "std.h"
Packit 9741aa
#include "sgmls.h"
Packit 9741aa
#include "getopt.h"
Packit 9741aa
Packit 9741aa
#ifdef USE_PROTOTYPES
Packit 9741aa
#define P(parms) parms
Packit 9741aa
#else
Packit 9741aa
#define P(parms) ()
Packit 9741aa
#endif
Packit 9741aa
Packit 9741aa
#ifdef __GNUC__
Packit 9741aa
#define NO_RETURN volatile
Packit 9741aa
#else
Packit 9741aa
#define NO_RETURN /* as nothing */
Packit 9741aa
#endif
Packit 9741aa
Packit 9741aa
#ifdef VARARGS
Packit 9741aa
#define VP(parms) ()
Packit 9741aa
#else
Packit 9741aa
#define VP(parms) P(parms)
Packit 9741aa
#endif
Packit 9741aa
Packit 9741aa
#ifdef USE_ISASCII
Packit 9741aa
#define ISASCII(c) isascii(c)
Packit 9741aa
#else
Packit 9741aa
#define ISASCII(c) (1)
Packit 9741aa
#endif
Packit 9741aa
Packit 9741aa
NO_RETURN void error VP((char *,...));
Packit 9741aa
Packit 9741aa
static void input_error P((int, char *, unsigned long));
Packit 9741aa
static int do_file P((FILE *));
Packit 9741aa
static void usage P((void));
Packit 9741aa
Packit 9741aa
static void output_processing_instruction P((char *, unsigned));
Packit 9741aa
static void output_data P((struct sgmls_data *, int));
Packit 9741aa
static void output_data_lines P((char *, unsigned));
Packit 9741aa
static void output_internal_sdata P((char *, unsigned));
Packit 9741aa
static void output_external_entity P((struct sgmls_external_entity *));
Packit 9741aa
static void output_external_entity_info P((struct sgmls_external_entity *));
Packit 9741aa
static void output_element_start P((char *, struct sgmls_attribute *));
Packit 9741aa
static void output_element_end P((char *));
Packit 9741aa
static void output_attribute P((struct sgmls_attribute *));
Packit 9741aa
static void output_tokens P((char **, int));
Packit 9741aa
static void output_markup_chars P((char *, unsigned));
Packit 9741aa
static void output_markup_string P((char *));
Packit 9741aa
static void output_char P((int, int));
Packit 9741aa
static void output_flush P((int));
Packit 9741aa
static void output_external_id P((char *, char *));
Packit 9741aa
static void output_entity P((struct sgmls_entity *));
Packit 9741aa
static void output_external_entity_info P((struct sgmls_external_entity *));
Packit 9741aa
static void output_internal_entity P((struct sgmls_internal_entity *));
Packit 9741aa
Packit 9741aa
#define output_flush_markup() output_flush('!')
Packit 9741aa
#define output_flush_data() output_flush('|')
Packit 9741aa
Packit 9741aa
static FILE *outfp;
Packit 9741aa
static int char_count = 0;
Packit 9741aa
static char *program_name;
Packit 9741aa
Packit 9741aa
int main(argc, argv)
Packit 9741aa
     int argc;
Packit 9741aa
     char **argv;
Packit 9741aa
{
Packit 9741aa
  int c;
Packit 9741aa
  int opt;
Packit 9741aa
  char *output_file = 0;
Packit 9741aa
Packit 9741aa
  program_name = argv[0];
Packit 9741aa
Packit 9741aa
  while ((opt = getopt(argc, argv, "o:")) != EOF)
Packit 9741aa
    switch (opt) {
Packit 9741aa
    case 'o':
Packit 9741aa
      output_file = optarg;
Packit 9741aa
      break;
Packit 9741aa
    case '?':
Packit 9741aa
      usage();
Packit 9741aa
    default:
Packit 9741aa
      abort();
Packit 9741aa
    }
Packit 9741aa
Packit 9741aa
  if (output_file) {
Packit 9741aa
    errno = 0;
Packit 9741aa
    outfp = fopen(output_file, "w");
Packit 9741aa
    if (!outfp)
Packit 9741aa
      error("couldn't open `%s' for output: %s", strerror(errno));
Packit 9741aa
  }
Packit 9741aa
  else {
Packit 9741aa
    outfp = tmpfile();
Packit 9741aa
    if (!outfp)
Packit 9741aa
      error("couldn't create temporary file: %s", strerror(errno));
Packit 9741aa
  }
Packit 9741aa
Packit 9741aa
  if (argc - optind > 1)
Packit 9741aa
    usage();
Packit 9741aa
Packit 9741aa
  if (argc - optind == 1) {
Packit 9741aa
    if (!freopen(argv[optind], "r", stdin))
Packit 9741aa
      error("couldn't open `%s' for input: %s", argv[optind], strerror(errno));
Packit 9741aa
  }
Packit 9741aa
Packit 9741aa
  (void)sgmls_set_errhandler(input_error);
Packit 9741aa
Packit 9741aa
  if (!do_file(stdin)) {
Packit 9741aa
    fclose(outfp);
Packit 9741aa
    if (output_file) {
Packit 9741aa
      if (!freopen(output_file, "w", stdout))
Packit 9741aa
	error("couldn't reopen `%s' for output: %s", strerror(errno));
Packit 9741aa
    }
Packit 9741aa
    fputs("#ERROR\n", stdout);
Packit 9741aa
    exit(EXIT_FAILURE);
Packit 9741aa
  }
Packit 9741aa
Packit 9741aa
  if (output_file) {
Packit 9741aa
    errno = 0;
Packit 9741aa
    if (fclose(outfp) == EOF)
Packit 9741aa
      error("error closing `%s': %s", output_file, strerror(errno));
Packit 9741aa
  }
Packit 9741aa
  else {
Packit 9741aa
    errno = 0;
Packit 9741aa
    if (fseek(outfp, 0L, SEEK_SET))
Packit 9741aa
      error("couldn't rewind temporary file: %s", strerror(errno));
Packit 9741aa
    while ((c = getc(outfp)) != EOF)
Packit 9741aa
      if (putchar(c) == EOF)
Packit 9741aa
	error("error writing standard output: %s", strerror(errno));
Packit 9741aa
  }
Packit 9741aa
  exit(EXIT_SUCCESS);
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void usage()
Packit 9741aa
{
Packit 9741aa
  fprintf(stderr, "usage: %s [-o output_file] [input_file]\n", program_name);
Packit 9741aa
  exit(EXIT_FAILURE);
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
int do_file(fp)
Packit 9741aa
     FILE *fp;
Packit 9741aa
{
Packit 9741aa
  struct sgmls *sp;
Packit 9741aa
  struct sgmls_event e;
Packit 9741aa
  int conforming = 0;
Packit 9741aa
Packit 9741aa
  sp = sgmls_create(fp);
Packit 9741aa
  while (sgmls_next(sp, &e))
Packit 9741aa
    switch (e.type) {
Packit 9741aa
    case SGMLS_EVENT_DATA:
Packit 9741aa
      output_data(e.u.data.v, e.u.data.n);
Packit 9741aa
      break;
Packit 9741aa
    case SGMLS_EVENT_ENTITY:
Packit 9741aa
      output_external_entity(e.u.entity);
Packit 9741aa
      break;
Packit 9741aa
    case SGMLS_EVENT_PI:
Packit 9741aa
      output_processing_instruction(e.u.pi.s, e.u.pi.len);
Packit 9741aa
      break;
Packit 9741aa
    case SGMLS_EVENT_START:
Packit 9741aa
      output_element_start(e.u.start.gi, e.u.start.attributes);
Packit 9741aa
      sgmls_free_attributes(e.u.start.attributes);
Packit 9741aa
      break;
Packit 9741aa
    case SGMLS_EVENT_END:
Packit 9741aa
      output_element_end(e.u.end.gi);
Packit 9741aa
      break;
Packit 9741aa
    case SGMLS_EVENT_SUBSTART:
Packit 9741aa
      {
Packit 9741aa
	int level = 1;
Packit 9741aa
	output_external_entity(e.u.entity);
Packit 9741aa
	while (level > 0) {
Packit 9741aa
	  if (!sgmls_next(sp, &e))
Packit 9741aa
	    return 0;
Packit 9741aa
	  switch (e.type) {
Packit 9741aa
	  case SGMLS_EVENT_SUBSTART:
Packit 9741aa
	    level++;
Packit 9741aa
	    break;
Packit 9741aa
	  case SGMLS_EVENT_SUBEND:
Packit 9741aa
	    level--;
Packit 9741aa
	    break;
Packit 9741aa
	  case SGMLS_EVENT_START:
Packit 9741aa
	    sgmls_free_attributes(e.u.start.attributes);
Packit 9741aa
	    break;
Packit 9741aa
	  default:
Packit 9741aa
	    /* prevent compiler warnings */
Packit 9741aa
	    break;
Packit 9741aa
	  }
Packit 9741aa
	}
Packit 9741aa
      }
Packit 9741aa
      break;
Packit 9741aa
    case SGMLS_EVENT_APPINFO:
Packit 9741aa
      break;
Packit 9741aa
    case SGMLS_EVENT_CONFORMING:
Packit 9741aa
      conforming = 1;
Packit 9741aa
      break;
Packit 9741aa
    default:
Packit 9741aa
      abort();
Packit 9741aa
    }
Packit 9741aa
  sgmls_free(sp);
Packit 9741aa
  return conforming;
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_processing_instruction(s, len)
Packit 9741aa
     char *s;
Packit 9741aa
     unsigned len;
Packit 9741aa
{
Packit 9741aa
  fputs("[?", outfp);
Packit 9741aa
  if (len > 0) {
Packit 9741aa
    putc('\n', outfp);
Packit 9741aa
    output_data_lines(s, len);
Packit 9741aa
    output_flush_data();
Packit 9741aa
  }
Packit 9741aa
  fputs("]\n", outfp);
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_data(v, n)
Packit 9741aa
     struct sgmls_data *v;
Packit 9741aa
     int n;
Packit 9741aa
{
Packit 9741aa
  int i;
Packit 9741aa
  for (i = 0; i < n; i++) {
Packit 9741aa
    if (v[i].is_sdata)
Packit 9741aa
      output_internal_sdata(v[i].s, v[i].len);
Packit 9741aa
    else if (v[i].len > 0)
Packit 9741aa
      output_data_lines(v[i].s, v[i].len);
Packit 9741aa
  }
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_data_lines(s, n)
Packit 9741aa
     char *s;
Packit 9741aa
     unsigned n;
Packit 9741aa
{
Packit 9741aa
  assert(n > 0);
Packit 9741aa
  for (; n > 0; --n)
Packit 9741aa
    output_char((unsigned char)*s++, '|');
Packit 9741aa
  output_flush_data();
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_internal_sdata(s, n)
Packit 9741aa
     char *s;
Packit 9741aa
     unsigned n;
Packit 9741aa
{
Packit 9741aa
  fputs("#SDATA-TEXT\n", outfp);
Packit 9741aa
  output_markup_chars(s, n);
Packit 9741aa
  output_flush_markup();
Packit 9741aa
  fputs("#END-SDATA\n", outfp);
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_external_entity(e)
Packit 9741aa
     struct sgmls_external_entity *e;
Packit 9741aa
{
Packit 9741aa
  fprintf(outfp, "[&%s\n", e->name);
Packit 9741aa
  output_external_entity_info(e);
Packit 9741aa
  fputs("]\n", outfp);
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_element_start(gi, att)
Packit 9741aa
     char *gi;
Packit 9741aa
     struct sgmls_attribute *att;
Packit 9741aa
{
Packit 9741aa
  fprintf(outfp, "[%s", gi);
Packit 9741aa
  if (att) {
Packit 9741aa
    struct sgmls_attribute *p;
Packit 9741aa
    putc('\n', outfp);
Packit 9741aa
    for (p = att; p; p = p->next)
Packit 9741aa
      output_attribute(p);
Packit 9741aa
  }
Packit 9741aa
  fputs("]\n", outfp);
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_element_end(gi)
Packit 9741aa
     char *gi;
Packit 9741aa
{
Packit 9741aa
  fprintf(outfp, "[/%s]\n", gi);
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_attribute(p)
Packit 9741aa
     struct sgmls_attribute *p;
Packit 9741aa
{
Packit 9741aa
  fprintf(outfp, "%s=\n", p->name);
Packit 9741aa
  switch (p->type) {
Packit 9741aa
  case SGMLS_ATTR_IMPLIED:
Packit 9741aa
    fputs("#IMPLIED\n", outfp);
Packit 9741aa
    break;
Packit 9741aa
  case SGMLS_ATTR_CDATA:
Packit 9741aa
    {
Packit 9741aa
      struct sgmls_data *v = p->value.data.v;
Packit 9741aa
      int n = p->value.data.n;
Packit 9741aa
      int i;
Packit 9741aa
      for (i = 0; i < n; i++)
Packit 9741aa
	if (v[i].is_sdata)
Packit 9741aa
	  output_internal_sdata(v[i].s, v[i].len);
Packit 9741aa
	else {
Packit 9741aa
	  output_markup_chars(v[i].s, v[i].len);
Packit 9741aa
	  output_flush_markup();
Packit 9741aa
	}
Packit 9741aa
    }
Packit 9741aa
    break;
Packit 9741aa
  case SGMLS_ATTR_TOKEN:
Packit 9741aa
    output_tokens(p->value.token.v, p->value.token.n);
Packit 9741aa
    break;
Packit 9741aa
  case SGMLS_ATTR_ENTITY:
Packit 9741aa
    {
Packit 9741aa
      int i;
Packit 9741aa
      for (i = 0; i < p->value.entity.n; i++) {
Packit 9741aa
	struct sgmls_entity *e = p->value.entity.v[i];
Packit 9741aa
	char *name;
Packit 9741aa
Packit 9741aa
	if (e->is_internal)
Packit 9741aa
	  name = e->u.internal.name;
Packit 9741aa
	else
Packit 9741aa
	  name = e->u.external.name;
Packit 9741aa
	if (i > 0)
Packit 9741aa
	  output_markup_string(" ");
Packit 9741aa
	output_markup_string(name);
Packit 9741aa
      }
Packit 9741aa
      output_flush_markup();
Packit 9741aa
      for (i = 0; i < p->value.entity.n; i++)
Packit 9741aa
	output_entity(p->value.entity.v[i]);
Packit 9741aa
    }
Packit 9741aa
    break;
Packit 9741aa
  case SGMLS_ATTR_NOTATION:
Packit 9741aa
    output_tokens(&p->value.notation->name, 1);
Packit 9741aa
    output_external_id(p->value.notation->pubid, p->value.notation->sysid);
Packit 9741aa
    break;
Packit 9741aa
  }
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static void output_tokens(v, n)
Packit 9741aa
     char **v;
Packit 9741aa
     int n;
Packit 9741aa
{
Packit 9741aa
  int i;
Packit 9741aa
  assert(n > 0);
Packit 9741aa
  output_markup_string(v[0]);
Packit 9741aa
  for (i = 1; i < n; i++) {
Packit 9741aa
    output_markup_string(" ");
Packit 9741aa
    output_markup_string(v[i]);
Packit 9741aa
  }
Packit 9741aa
  output_flush_markup();
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_markup_chars(s, n)
Packit 9741aa
     char *s;
Packit 9741aa
     unsigned n;
Packit 9741aa
{
Packit 9741aa
  for (; n > 0; --n)
Packit 9741aa
    output_char((unsigned char)*s++, '!');
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_markup_string(s)
Packit 9741aa
     char *s;
Packit 9741aa
{
Packit 9741aa
  while (*s)
Packit 9741aa
    output_char((unsigned char)*s++, '!');
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_char(c, delim)
Packit 9741aa
     int c;
Packit 9741aa
     int delim;
Packit 9741aa
{
Packit 9741aa
  if (ISASCII(c) && isprint(c)) {
Packit 9741aa
    if (char_count == 0)
Packit 9741aa
      putc(delim, outfp);
Packit 9741aa
    putc(c, outfp);
Packit 9741aa
    char_count++;
Packit 9741aa
    if (char_count == 60) {
Packit 9741aa
      putc(delim, outfp);
Packit 9741aa
      putc('\n', outfp);
Packit 9741aa
      char_count = 0;
Packit 9741aa
    }
Packit 9741aa
  }
Packit 9741aa
  else {
Packit 9741aa
    output_flush(delim);
Packit 9741aa
    switch (c) {
Packit 9741aa
    case RECHAR:
Packit 9741aa
      fputs("#RE\n", outfp);
Packit 9741aa
      break;
Packit 9741aa
    case RSCHAR:
Packit 9741aa
      fputs("#RS\n", outfp);
Packit 9741aa
      break;
Packit 9741aa
    case TABCHAR:
Packit 9741aa
      fputs("#TAB\n", outfp);
Packit 9741aa
      break;
Packit 9741aa
    default:
Packit 9741aa
      fprintf(outfp, "#%d\n", c);
Packit 9741aa
    }
Packit 9741aa
  }
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_flush(delim)
Packit 9741aa
     int delim;
Packit 9741aa
{
Packit 9741aa
  if (char_count > 0) {
Packit 9741aa
    putc(delim, outfp);
Packit 9741aa
    putc('\n', outfp);
Packit 9741aa
    char_count = 0;
Packit 9741aa
  }
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_external_id(pubid, sysid)
Packit 9741aa
  char *pubid;
Packit 9741aa
  char *sysid;
Packit 9741aa
{
Packit 9741aa
  if (!pubid && !sysid)
Packit 9741aa
    fputs("#SYSTEM\n#NONE\n", outfp);
Packit 9741aa
  else {
Packit 9741aa
    if (pubid) {
Packit 9741aa
      fputs("#PUBLIC\n", outfp);
Packit 9741aa
      if (*pubid) {
Packit 9741aa
	output_markup_string(pubid);
Packit 9741aa
	output_flush_markup();
Packit 9741aa
      }
Packit 9741aa
      else
Packit 9741aa
	fputs("#EMPTY\n", outfp);
Packit 9741aa
    }
Packit 9741aa
    if (sysid) {
Packit 9741aa
      fputs("#SYSTEM\n", outfp);
Packit 9741aa
      if (*sysid) {
Packit 9741aa
	output_markup_string(sysid);
Packit 9741aa
	output_flush_markup();
Packit 9741aa
      }
Packit 9741aa
      else
Packit 9741aa
	fputs("#EMPTY\n", outfp);
Packit 9741aa
    }
Packit 9741aa
  }
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_entity(e)
Packit 9741aa
     struct sgmls_entity *e;
Packit 9741aa
{
Packit 9741aa
  if (e->is_internal)
Packit 9741aa
    output_internal_entity(&e->u.internal);
Packit 9741aa
  else
Packit 9741aa
    output_external_entity_info(&e->u.external);
Packit 9741aa
  fputs("#END-ENTITY", outfp);
Packit 9741aa
#ifndef ASIS
Packit 9741aa
  putc('\n', outfp);
Packit 9741aa
#endif
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_external_entity_info(e)
Packit 9741aa
     struct sgmls_external_entity *e;
Packit 9741aa
{
Packit 9741aa
  switch (e->type) {
Packit 9741aa
  case SGMLS_ENTITY_CDATA:
Packit 9741aa
    fputs("#CDATA-EXTERNAL", outfp);
Packit 9741aa
    break;
Packit 9741aa
  case SGMLS_ENTITY_SDATA:
Packit 9741aa
    fputs("#SDATA-EXTERNAL", outfp);
Packit 9741aa
    break;
Packit 9741aa
  case SGMLS_ENTITY_NDATA:
Packit 9741aa
    fputs("#NDATA-EXTERNAL", outfp);
Packit 9741aa
    break;
Packit 9741aa
  case SGMLS_ENTITY_SUBDOC:
Packit 9741aa
    fputs("#SUBDOC", outfp);
Packit 9741aa
    break;
Packit 9741aa
  }
Packit 9741aa
  putc('\n', outfp);
Packit 9741aa
  output_external_id(e->pubid, e->sysid);
Packit 9741aa
  if (e->type != SGMLS_ENTITY_SUBDOC) {
Packit 9741aa
    struct sgmls_attribute *p;
Packit 9741aa
    fprintf(outfp, "#NOTATION=%s\n", e->notation->name);
Packit 9741aa
    output_external_id(e->notation->pubid, e->notation->sysid);
Packit 9741aa
    for (p = e->attributes; p; p = p->next)
Packit 9741aa
      output_attribute(p);
Packit 9741aa
  }
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void output_internal_entity(e)
Packit 9741aa
     struct sgmls_internal_entity *e;
Packit 9741aa
{
Packit 9741aa
  if (e->data.is_sdata)
Packit 9741aa
    fputs("#SDATA-INTERNAL", outfp);
Packit 9741aa
  else
Packit 9741aa
    fputs("#CDATA-INTERNAL", outfp);
Packit 9741aa
  putc('\n', outfp);
Packit 9741aa
  output_markup_chars(e->data.s, e->data.len);
Packit 9741aa
  output_flush_markup();
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
static
Packit 9741aa
void input_error(num, str, lineno)
Packit 9741aa
     int num;
Packit 9741aa
     char *str;
Packit 9741aa
     unsigned long lineno;
Packit 9741aa
{
Packit 9741aa
  error("Error at input line %lu: %s", lineno, str);
Packit 9741aa
}
Packit 9741aa
Packit 9741aa
NO_RETURN
Packit 9741aa
#ifdef VARARGS
Packit 9741aa
void error(va_alist) va_dcl
Packit 9741aa
#else
Packit 9741aa
void error(char *message,...)
Packit 9741aa
#endif
Packit 9741aa
{
Packit 9741aa
#ifdef VARARGS
Packit 9741aa
     char *message;
Packit 9741aa
#endif
Packit 9741aa
     va_list ap;
Packit 9741aa
     
Packit 9741aa
     fprintf(stderr, "%s: ", program_name);
Packit 9741aa
#ifdef VARARGS
Packit 9741aa
     va_start(ap);
Packit 9741aa
     message = va_arg(ap, char *);
Packit 9741aa
#else
Packit 9741aa
     va_start(ap, message);
Packit 9741aa
#endif
Packit 9741aa
     vfprintf(stderr, message, ap);
Packit 9741aa
     va_end(ap);
Packit 9741aa
     fputc('\n', stderr);
Packit 9741aa
     fflush(stderr);
Packit 9741aa
     exit(EXIT_FAILURE);
Packit 9741aa
}