home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 10 / Fresh_Fish_10_2352.bin / new / dev / lang / sgmls / src / rast.c < prev    next >
C/C++ Source or Header  |  1994-07-10  |  13KB  |  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_CDAT