home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / dev / lang / sgmls / src / rast.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-07-10  |  12.4 KB  |  601 lines

  1. /* rast.c
  2.    Translate sgmls output to RAST result format.
  3.  
  4.    Written by James Clark (jjc@jclark.com). */
  5.  
  6. #include "config.h"
  7. #include "std.h"
  8. #include "sgmls.h"
  9. #include "getopt.h"
  10.  
  11. #ifdef USE_PROTOTYPES
  12. #define P(parms) parms
  13. #else
  14. #define P(parms) ()
  15. #endif
  16.  
  17. #ifdef __GNUC__
  18. #define NO_RETURN volatile
  19. #else
  20. #define NO_RETURN /* as nothing */
  21. #endif
  22.  
  23. #ifdef VARARGS
  24. #define VP(parms) ()
  25. #else
  26. #define VP(parms) P(parms)
  27. #endif
  28.  
  29. #ifdef USE_ISASCII
  30. #define ISASCII(c) isascii(c)
  31. #else
  32. #define ISASCII(c) (1)
  33. #endif
  34.  
  35. NO_RETURN void error VP((char *,...));
  36.  
  37. static void input_error P((int, char *, unsigned long));
  38. static int do_file P((FILE *));
  39. static void usage P((void));
  40. static void init_sort_code P((void));
  41.  
  42. static void output_processing_instruction P((char *, unsigned));
  43. static void output_data P((struct sgmls_data *, int));
  44. static void output_data_lines P((char *, unsigned));
  45. static void output_internal_sdata P((char *, unsigned));
  46. static void output_external_entity P((struct sgmls_external_entity *));
  47. static void output_external_entity_info P((struct sgmls_external_entity *));
  48. static void output_element_start P((char *, struct sgmls_attribute *));
  49. static void output_element_end P((char *));
  50. static void output_attribute P((struct sgmls_attribute *));
  51. static void output_attribute_list P((struct sgmls_attribute *));
  52. static void output_tokens P((char **, int));
  53. static void output_markup_chars P((char *, unsigned));
  54. static void output_markup_string P((char *));
  55. static void output_char P((int, int));
  56. static void output_flush P((int));
  57. static void output_external_id P((char *, char *));
  58. static void output_entity P((struct sgmls_entity *));
  59. static void output_external_entity_info P((struct sgmls_external_entity *));
  60. static void output_internal_entity P((struct sgmls_internal_entity *));
  61. /* Don't use a prototype here to avoid problems with qsort. */
  62. static int compare_attributes();
  63.  
  64. #define output_flush_markup() output_flush('!')
  65. #define output_flush_data() output_flush('|')
  66.  
  67. static FILE *outfp;
  68. static int char_count = 0;
  69. static char *program_name;
  70.  
  71. static short sort_code[256];
  72. static struct sgmls_attribute **attribute_vector = 0;
  73. static int attribute_vector_length = 0;
  74.  
  75. int main(argc, argv)
  76.      int argc;
  77.      char **argv;
  78. {
  79.   int c;
  80.   int opt;
  81.   char *output_file = 0;
  82.  
  83.   program_name = argv[0];
  84.  
  85.   while ((opt = getopt(argc, argv, "o:")) != EOF)
  86.     switch (opt) {
  87.     case 'o':
  88.       output_file = optarg;
  89.       break;
  90.     case '?':
  91.       usage();
  92.     default:
  93.       abort();
  94.     }
  95.  
  96.   if (output_file) {
  97.     errno = 0;
  98.     outfp = fopen(output_file, "w");
  99.     if (!outfp)
  100.       error("couldn't open `%s' for output: %s", strerror(errno));
  101.   }
  102.   else {
  103.     outfp = tmpfile();
  104.     if (!outfp)
  105.       error("couldn't create temporary file: %s", strerror(errno));
  106.   }
  107.  
  108.   if (argc - optind > 1)
  109.     usage();
  110.  
  111.   if (argc - optind == 1) {
  112.     if (!freopen(argv[optind], "r", stdin))
  113.       error("couldn't open `%s' for input: %s", argv[optind], strerror(errno));
  114.   }
  115.  
  116.   (void)sgmls_set_errhandler(input_error);
  117.  
  118.   init_sort_code();
  119.  
  120.   if (!do_file(stdin)) {
  121.     fclose(outfp);
  122.     if (output_file) {
  123.       if (!freopen(output_file, "w", stdout))
  124.     error("couldn't reopen `%s' for output: %s", strerror(errno));
  125.     }
  126.     fputs("#ERROR\n", stdout);
  127.     exit(EXIT_FAILURE);
  128.   }
  129.  
  130.   if (output_file) {
  131.     errno = 0;
  132.     if (fclose(outfp) == EOF)
  133.       error("error closing `%s': %s", output_file, strerror(errno));
  134.   }
  135.   else {
  136.     errno = 0;
  137.     if (fseek(outfp, 0L, SEEK_SET))
  138.       error("couldn't rewind temporary file: %s", strerror(errno));
  139.     while ((c = getc(outfp)) != EOF)
  140.       if (putchar(c) == EOF)
  141.     error("error writing standard output: %s", strerror(errno));
  142.   }
  143.   exit(EXIT_SUCCESS);
  144. }
  145.  
  146. static
  147. void usage()
  148. {
  149.   fprintf(stderr, "usage: %s [-o output_file] [input_file]\n", program_name);
  150.   exit(EXIT_FAILURE);
  151. }
  152.  
  153. static
  154. void init_sort_code()
  155. {
  156.   int i;
  157.   static char print[] = "!\"#$%&'()*+,-./0123456789:;<=>?\
  158. @ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";
  159.   for (i = 0; i < 256; i++)
  160.     sort_code[i] = i + 128;
  161.   for (i = 0; print[i]; i++)
  162.     sort_code[(unsigned char)print[i]] = i;
  163. }
  164.  
  165. static
  166. int do_file(fp)
  167.      FILE *fp;
  168. {
  169.   struct sgmls *sp;
  170.   struct sgmls_event e;
  171.   int conforming = 0;
  172.  
  173.   sp = sgmls_create(fp);
  174.   while (sgmls_next(sp, &e))
  175.     switch (e.type) {
  176.     case SGMLS_EVENT_DATA:
  177.       output_data(e.u.data.v, e.u.data.n);
  178.       break;
  179.     case SGMLS_EVENT_ENTITY:
  180.       output_external_entity(e.u.entity);
  181.       break;
  182.     case SGMLS_EVENT_PI:
  183.       output_processing_instruction(e.u.pi.s, e.u.pi.len);
  184.       break;
  185.     case SGMLS_EVENT_START:
  186.       output_element_start(e.u.start.gi, e.u.start.attributes);
  187.       sgmls_free_attributes(e.u.start.attributes);
  188.       break;
  189.     case SGMLS_EVENT_END:
  190.       output_element_end(e.u.end.gi);
  191.       break;
  192.     case SGMLS_EVENT_SUBSTART:
  193.       {
  194.     int level = 1;
  195.     output_external_entity(e.u.entity);
  196.     while (level > 0) {
  197.       if (!sgmls_next(sp, &e))
  198.         return 0;
  199.       switch (e.type) {
  200.       case SGMLS_EVENT_SUBSTART:
  201.         level++;
  202.         break;
  203.       case SGMLS_EVENT_SUBEND:
  204.         level--;
  205.         break;
  206.       case SGMLS_EVENT_START:
  207.         sgmls_free_attributes(e.u.start.attributes);
  208.         break;
  209.       default:
  210.         /* prevent compiler warnings */
  211.         break;
  212.       }
  213.     }
  214.       }
  215.       break;
  216.     case SGMLS_EVENT_APPINFO:
  217.       break;
  218.     case SGMLS_EVENT_CONFORMING:
  219.       conforming = 1;
  220.       break;
  221.     default:
  222.       abort();
  223.     }
  224.   sgmls_free(sp);
  225.   return conforming;
  226. }
  227.  
  228. static
  229. void output_processing_instruction(s, len)
  230.      char *s;
  231.      unsigned len;
  232. {
  233.   fputs("[?", outfp);
  234.   if (len > 0) {
  235.     putc('\n', outfp);
  236.     output_data_lines(s, len);
  237.     output_flush_data();
  238.   }
  239.   fputs("]\n", outfp);
  240. }
  241.  
  242. static
  243. void output_data(v, n)
  244.      struct sgmls_data *v;
  245.      int n;
  246. {
  247.   int i;
  248.   for (i = 0; i < n; i++) {
  249.     if (v[i].is_sdata)
  250.       output_internal_sdata(v[i].s, v[i].len);
  251.     else if (v[i].len > 0)
  252.       output_data_lines(v[i].s, v[i].len);
  253.   }
  254. }
  255.  
  256. static
  257. void output_data_lines(s, n)
  258.      char *s;
  259.      unsigned n;
  260. {
  261.   assert(n > 0);
  262.   for (; n > 0; --n)
  263.     output_char((unsigned char)*s++, '|');
  264.   output_flush_data();
  265. }
  266.  
  267. static
  268. void output_internal_sdata(s, n)
  269.      char *s;
  270.      unsigned n;
  271. {
  272.   fputs("#SDATA-TEXT\n", outfp);
  273.   output_markup_chars(s, n);
  274.   output_flush_markup();
  275.   fputs("#END-SDATA\n", outfp);
  276. }
  277.  
  278. static
  279. void output_external_entity(e)
  280.      struct sgmls_external_entity *e;
  281. {
  282.   fprintf(outfp, "[&%s\n", e->name);
  283.   output_external_entity_info(e);
  284.   fputs("]\n", outfp);
  285. }
  286.  
  287. static
  288. void output_element_start(gi, att)
  289.      char *gi;
  290.      struct sgmls_attribute *att;
  291. {
  292.   fprintf(outfp, "[%s", gi);
  293.   if (att) {
  294.     putc('\n', outfp);
  295.     output_attribute_list(att);
  296.   }
  297.   fputs("]\n", outfp);
  298. }
  299.  
  300. static
  301. void output_element_end(gi)
  302.      char *gi;
  303. {
  304.   fprintf(outfp, "[/%s]\n", gi);
  305. }
  306.  
  307. static
  308. void output_attribute_list(att)
  309.      struct sgmls_attribute *att;
  310. {
  311.   struct sgmls_attribute *p;
  312.   int n = 0;
  313.   int i;
  314.  
  315.   for (p = att; p; p = p->next)
  316.     n++;
  317.   if (attribute_vector_length < n) {
  318.     if (attribute_vector_length == 0)
  319.       attribute_vector
  320.     = (struct sgmls_attribute **)malloc(n*sizeof(*attribute_vector));
  321.     else
  322.       attribute_vector
  323.     = (struct sgmls_attribute **)realloc((UNIV)attribute_vector,
  324.                          n*sizeof(*attribute_vector));
  325.     attribute_vector_length = n;
  326.     if (!attribute_vector)
  327.       error("Out of memory");
  328.   }
  329.   i = 0;
  330.   for (p = att; p; p = p->next)
  331.     attribute_vector[i++] = p;
  332.   qsort(attribute_vector, n, sizeof(attribute_vector[0]), compare_attributes);
  333.   for (i = 0; i < n; i++)
  334.     output_attribute(attribute_vector[i]);
  335. }
  336.  
  337. static
  338. int compare_attributes(UNIV p1, UNIV p2)
  339.  
  340. {
  341.   char *s1 = (*(struct sgmls_attribute **)p1)->name;
  342.   char *s2 = (*(struct sgmls_attribute **)p2)->name;
  343.  
  344.   for (; *s1 && *s2; s1++, s2++)
  345.     if (*s1 != *s2)
  346.       return sort_code[(unsigned char)*s1] - sort_code[(unsigned char)*s2];
  347.   if (*s1)
  348.     return 1;
  349.   else if (*s2)
  350.     return -1;
  351.   else
  352.     return 0;
  353. }
  354.  
  355. static
  356. void output_attribute(p)
  357.      struct sgmls_attribute *p;
  358. {
  359.   fprintf(outfp, "%s=\n", p->name);
  360.   switch (p->type) {
  361.   case SGMLS_ATTR_IMPLIED:
  362.     fputs("#IMPLIED\n", outfp);
  363.     break;
  364.   case SGMLS_ATTR_CDATA:
  365.     {
  366.       struct sgmls_data *v = p->value.data.v;
  367.       int n = p->value.data.n;
  368.       int i;
  369.       for (i = 0; i < n; i++)
  370.     if (v[i].is_sdata)
  371.       output_internal_sdata(v[i].s, v[i].len);
  372.     else {
  373.       output_markup_chars(v[i].s, v[i].len);
  374.       output_flush_markup();
  375.     }
  376.     }
  377.     break;
  378.   case SGMLS_ATTR_TOKEN:
  379.     output_tokens(p->value.token.v, p->value.token.n);
  380.     break;
  381.   case SGMLS_ATTR_ENTITY:
  382.     {
  383.       int i;
  384.       for (i = 0; i < p->value.entity.n; i++) {
  385.     struct sgmls_entity *e = p->value.entity.v[i];
  386.     char *name;
  387.  
  388.     if (e->is_internal)
  389.       name = e->u.internal.name;
  390.     else
  391.       name = e->u.external.name;
  392.     if (i > 0)
  393.       output_markup_string(" ");
  394.     output_markup_string(name);
  395.       }
  396.       output_flush_markup();
  397.       for (i = 0; i < p->value.entity.n; i++)
  398.     output_entity(p->value.entity.v[i]);
  399.     }
  400.     break;
  401.   case SGMLS_ATTR_NOTATION:
  402.     output_tokens(&p->value.notation->name, 1);
  403.     output_external_id(p->value.notation->pubid, p->value.notation->sysid);
  404.     break;
  405.   }
  406. }
  407.  
  408. static void output_tokens(v, n)
  409.      char **v;
  410.      int n;
  411. {
  412.   int i;
  413.   assert(n > 0);
  414.   output_markup_string(v[0]);
  415.   for (i = 1; i < n; i++) {
  416.     output_markup_string(" ");
  417.     output_markup_string(v[i]);
  418.   }
  419.   output_flush_markup();
  420. }
  421.  
  422. static
  423. void output_markup_chars(s, n)
  424.      char *s;
  425.      unsigned n;
  426. {
  427.   for (; n > 0; --n)
  428.     output_char((unsigned char)*s++, '!');
  429. }
  430.  
  431. static
  432. void output_markup_string(s)
  433.      char *s;
  434. {
  435.   while (*s)
  436.     output_char((unsigned char)*s++, '!');
  437. }
  438.  
  439. static
  440. void output_char(c, delim)
  441.      int c;
  442.      int delim;
  443. {
  444.   if (ISASCII(c) && isprint(c)) {
  445.     if (char_count == 0)
  446.       putc(delim, outfp);
  447.     putc(c, outfp);
  448.     char_count++;
  449.     if (char_count == 60) {
  450.       putc(delim, outfp);
  451.       putc('\n', outfp);
  452.       char_count = 0;
  453.     }
  454.   }
  455.   else {
  456.     output_flush(delim);
  457.     switch (c) {
  458.     case RECHAR:
  459.       fputs("#RE\n", outfp);
  460.       break;
  461.     case RSCHAR:
  462.       fputs("#RS\n", outfp);
  463.       break;
  464.     case TABCHAR:
  465.       fputs("#TAB\n", outfp);
  466.       break;
  467.     default:
  468.       fprintf(outfp, "#%d\n", c);
  469.     }
  470.   }
  471. }
  472.  
  473. static
  474. void output_flush(delim)
  475.      int delim;
  476. {
  477.   if (char_count > 0) {
  478.     putc(delim, outfp);
  479.     putc('\n', outfp);
  480.     char_count = 0;
  481.   }
  482. }
  483.  
  484. static
  485. void output_external_id(pubid, sysid)
  486.   char *pubid;
  487.   char *sysid;
  488. {
  489.   if (!pubid && !sysid)
  490.     fputs("#SYSTEM\n#NONE\n", outfp);
  491.   else {
  492.     if (pubid) {
  493.       fputs("#PUBLIC\n", outfp);
  494.       if (*pubid) {
  495.     output_markup_string(pubid);
  496.     output_flush_markup();
  497.       }
  498.       else
  499.     fputs("#EMPTY\n", outfp);
  500.     }
  501.     if (sysid) {
  502.       fputs("#SYSTEM\n", outfp);
  503.       if (*sysid) {
  504.     output_markup_string(sysid);
  505.     output_flush_markup();
  506.       }
  507.       else
  508.     fputs("#EMPTY\n", outfp);
  509.     }
  510.   }
  511. }
  512.  
  513. static
  514. void output_entity(e)
  515.      struct sgmls_entity *e;
  516. {
  517.   if (e->is_internal)
  518.     output_internal_entity(&e->u.internal);
  519.   else
  520.     output_external_entity_info(&e->u.external);
  521.   fputs("#END-ENTITY", outfp);
  522. #ifndef ASIS
  523.   putc('\n', outfp);
  524. #endif
  525. }
  526.  
  527. static
  528. void output_external_entity_info(e)
  529.      struct sgmls_external_entity *e;
  530. {
  531.   switch (e->type) {
  532.   case SGMLS_ENTITY_CDATA:
  533.     fputs("#CDATA-EXTERNAL", outfp);
  534.     break;
  535.   case SGMLS_ENTITY_SDATA:
  536.     fputs("#SDATA-EXTERNAL", outfp);
  537.     break;
  538.   case SGMLS_ENTITY_NDATA:
  539.     fputs("#NDATA-EXTERNAL", outfp);
  540.     break;
  541.   case SGMLS_ENTITY_SUBDOC:
  542.     fputs("#SUBDOC", outfp);
  543.     break;
  544.   }
  545.   putc('\n', outfp);
  546.   output_external_id(e->pubid, e->sysid);
  547.   if (e->type != SGMLS_ENTITY_SUBDOC) {
  548.     fprintf(outfp, "#NOTATION=%s\n", e->notation->name);
  549.     output_external_id(e->notation->pubid, e->notation->sysid);
  550.     output_attribute_list(e->attributes);
  551.   }
  552. }
  553.  
  554. static
  555. void output_internal_entity(e)
  556.      struct sgmls_internal_entity *e;
  557. {
  558.   if (e->data.is_sdata)
  559.     fputs("#SDATA-INTERNAL", outfp);
  560.   else
  561.     fputs("#CDATA-INTERNAL", outfp);
  562.   putc('\n', outfp);
  563.   output_markup_chars(e->data.s, e->data.len);
  564.   output_flush_markup();
  565. }
  566.  
  567. static
  568. void input_error(num, str, lineno)
  569.      int num;
  570.      char *str;
  571.      unsigned long lineno;
  572. {
  573.   error("Error at input line %lu: %s", lineno, str);
  574. }
  575.  
  576. NO_RETURN
  577. #ifdef VARARGS
  578. void error(va_alist) va_dcl
  579. #else
  580. void error(char *message,...)
  581. #endif
  582. {
  583. #ifdef VARARGS
  584.      char *message;
  585. #endif
  586.      va_list ap;
  587.  
  588.      fprintf(stderr, "%s: ", program_name);
  589. #ifdef VARARGS
  590.      va_start(ap);
  591.      message = va_arg(ap, char *);
  592. #else
  593.      va_start(ap, message);
  594. #endif
  595.      vfprintf(stderr, message, ap);
  596.      va_end(ap);
  597.      fputc('\n', stderr);
  598.      fflush(stderr);
  599.      exit(EXIT_FAILURE);
  600. }
  601.