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

  1. /* lineout.c -
  2.    Implements line-oriented output format.
  3.  
  4.      Written by James Clark (jjc@jclark.com).
  5. */
  6.  
  7. #include "config.h"
  8. #include "std.h"
  9. #include "entity.h"           /* Templates for entity control blocks. */
  10. #include "adl.h"              /* Definitions for attribute list processing. */
  11. #include "sgmlmain.h"         /* Main interface to SGML services. */
  12. #include "lineout.h"
  13. #include "appl.h"
  14.  
  15. static VOID flush_data P((void));
  16. static VOID define_external_entity P((PNE));
  17. static VOID define_entity P((UNCH *));
  18. static VOID handle_attributes P((UNCH *, struct ad *));
  19. static VOID handle_token_list P((UNCH *, struct ad *, int));
  20. static VOID handle_single_token P((UNCH *, struct ad *, int));
  21. static VOID output_notation P((UNCH *, UNCH *, UNCH *));
  22. static VOID output_internal_entity P((UNCH *, int, UNCH *));
  23. static VOID output_external_entity P((UNCH *, int, UNIV, UNCH *, UNCH *,
  24.                       UNCH *));
  25. static VOID output_subdoc P((UNCH *, UNIV, UNCH *, UNCH *));
  26. #ifdef SUPPORT_SUBDOC
  27. static VOID process_subdoc P((UNCH *, UNIV));
  28. #endif /* SUPPORT_SUBDOC */
  29. static VOID output_record_end P((void));
  30. static VOID output_pcdata P((UNS, UNCH *));
  31. static VOID output_cdata P((UNS, UNCH *));
  32. static VOID output_sdata P((UNS, UNCH *));
  33. static VOID output_entity_reference P((UNCH *));
  34. static VOID output_start_tag P((UNCH *));
  35. static VOID output_end_tag P((UNCH *));
  36. static VOID output_processing_instruction P((UNS, UNCH *));
  37. static VOID output_implied_attribute P((UNCH *, UNCH *));
  38. static char *attribute_type_string P((int));
  39. static VOID output_begin_attribute P((UNCH *, UNCH *, int));
  40. static VOID output_attribute_token P((UNS, UNCH *));
  41. static VOID output_end_attribute P((void));
  42. static VOID print_data P((UNS, UNCH *, int));
  43. static VOID print_string P((UNS, UNCH *, int));
  44. static VOID print_id P((UNIV, UNCH *, UNCH *));
  45. static VOID print_filename P((char *));
  46. static VOID output_location P((void));
  47. static VOID output_appinfo P((UNS, UNCH *));
  48.  
  49. static int have_data = 0;
  50. static char *current_filename = 0;
  51. static unsigned long current_lineno = 0;
  52.  
  53. VOID process_document(subdocsw)
  54. int subdocsw;
  55. {
  56.      enum sgmlevent rc;
  57.      struct rcbtag rcbtag;
  58.      struct rcbdata rcbdaf;
  59.  
  60.      while ((rc = sgmlnext(&rcbdaf, &rcbtag)) != SGMLEOD) {
  61. #ifdef SUPPORT_SUBDOC
  62.       if (rc == SGMLDAF && !CONTERSW(rcbdaf) && NDESW(rcbdaf)
  63.           && NEXTYPE(NEPTR(rcbdaf)) == ESNSUB) {
  64.            if (!suppsw && !sgmlment(NEENAME(NEPTR(rcbdaf))))
  65.             define_external_entity(NEPTR(rcbdaf));
  66.            process_subdoc(NEENAME(NEPTR(rcbdaf)) + 1,
  67.                   NEID(NEPTR(rcbdaf)));
  68.            continue;
  69.       }
  70. #endif /* SUPPORT_SUBDOC */
  71.       if (!suppsw)
  72.            switch (rc) {
  73.            case SGMLDAF:
  74.             if (CONTERSW(rcbdaf))
  75.              break;
  76.             if (CDESW(rcbdaf))
  77.              output_cdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  78.             else if (SDESW(rcbdaf))
  79.              output_sdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  80.             else if (NDESW(rcbdaf)) {
  81.              assert(NEXTYPE(NEPTR(rcbdaf)) != ESNSUB);
  82.              if (!sgmlment(NEENAME(NEPTR(rcbdaf))))
  83.                   define_external_entity(NEPTR(rcbdaf));
  84.              output_entity_reference(NEENAME(NEPTR(rcbdaf)) + 1);
  85.             }
  86.             else
  87.              output_pcdata(CDATALEN(rcbdaf), CDATA(rcbdaf));
  88.             break;
  89.            case SGMLSTG:
  90.             if (CONTERSW(rcbtag))
  91.              break;
  92.             if (ALPTR(rcbtag))
  93.              handle_attributes((UNCH *)NULL, ALPTR(rcbtag));
  94.             output_start_tag(CURGI(rcbtag));
  95.             break;
  96.            case SGMLETG:
  97.             if (CONTERSW(rcbtag))
  98.              break;
  99.             output_end_tag(CURGI(rcbtag));
  100.             break;
  101.            case SGMLPIS:
  102.             if (CONTERSW(rcbdaf))
  103.              break;
  104.             output_processing_instruction(PDATALEN(rcbdaf),
  105.                           PDATA(rcbdaf));
  106.             break;
  107.            case SGMLREF:
  108.             if (CONTERSW(rcbdaf))
  109.              break;
  110.             output_record_end();
  111.             break;
  112.            case SGMLAPP:
  113.             if (CONTERSW(rcbdaf))
  114.              break;
  115.             if (!subdocsw)
  116.              output_appinfo(ADATALEN(rcbdaf), ADATA(rcbdaf));
  117.             break;
  118.            default:
  119.             abort();
  120.            }
  121.      }
  122. }
  123.  
  124. /* Output an indication that the document was conforming. */
  125.  
  126. VOID output_conforming()
  127. {
  128.      if (!suppsw)
  129.       printf("%c\n", CONFORMING_CODE);
  130. }
  131.  
  132. static VOID define_external_entity(p)
  133. PNE p;
  134. {
  135.      if (NEXTYPE(p) == ESNSUB)
  136.       output_subdoc(NEENAME(p) + 1, NEID(p), NEPUBID(p), NESYSID(p));
  137.      else {
  138.       if (!NEDCNMARK(p))
  139.            output_notation(NEDCN(p) + 1, NEDCNPUBID(p), NEDCNSYSID(p));
  140.       output_external_entity(NEENAME(p) + 1, NEXTYPE(p), NEID(p),
  141.                  NEPUBID(p), NESYSID(p), NEDCN(p) + 1);
  142.       if (NEAL(p))
  143.            handle_attributes(NEENAME(p) + 1, NEAL(p));
  144.      }
  145. }
  146.  
  147. static VOID define_entity(ename)
  148. UNCH *ename;
  149. {
  150.      int rc;
  151.      PNE np;
  152.      UNCH *tp;
  153.      
  154.      if (sgmlment(ename))        /* already defined it */
  155.       return;
  156.      rc = sgmlgent(ename, &np, &tp);
  157.      switch (rc) {
  158.      case 1:
  159.       define_external_entity(np);
  160.       break;
  161.      case 2:
  162.      case 3:
  163.       output_internal_entity(ename + 1, rc == 3, tp);
  164.       break;
  165.      }
  166. }
  167.  
  168. /* ENT is the name of the entity with which these attributes are associated;
  169. if it's NULL, they're associated with the next start tag. */
  170.  
  171. static VOID handle_attributes(ent, al)
  172. UNCH *ent;
  173. struct ad *al;
  174. {
  175.      int aln;
  176.  
  177.      for (aln = 1; aln <= ADN(al); aln++) {
  178.       if (GET(ADFLAGS(al, aln), AERROR))
  179.            ;
  180.       else if (GET(ADFLAGS(al, aln), AINVALID))
  181.            ;
  182.       else if (ADVAL(al, aln) == NULL)
  183.            output_implied_attribute(ent, ADNAME(al, aln));
  184.       else if (ADTYPE(al, aln) >= ATKNLIST)
  185.            handle_token_list(ent, al, aln);
  186.       else
  187.            handle_single_token(ent, al, aln);
  188.       if (BITON(ADFLAGS(al, aln), AGROUP))
  189.            aln += ADNUM(al, aln);
  190.      }
  191. }
  192.  
  193. static VOID handle_token_list(ent, al, aln)
  194. UNCH *ent;
  195. struct ad *al;
  196. int aln;
  197. {
  198.      UNCH *ptr;
  199.      int i;
  200.      if (ADTYPE(al, aln) == AENTITYS) {
  201.       ptr = ADVAL(al, aln);
  202.       for (i = 0; i < ADNUM(al, aln); i++) {
  203.            /* Temporarily make token look like normal
  204.           name with length and EOS. */
  205.            UNCH c = ptr[*ptr + 1];
  206.            ptr[*ptr + 1] = '\0';
  207.            *ptr += 2;
  208.            define_entity(ptr);
  209.            *ptr -= 2;
  210.            ptr += *ptr + 1;
  211.            *ptr = c;
  212.       }
  213.      }
  214.      output_begin_attribute(ent, ADNAME(al, aln), ADTYPE(al, aln));
  215.      ptr = ADVAL(al, aln);
  216.      for (i = 0; i < ADNUM(al, aln); i++) {
  217.       /* The first byte is a length NOT including the length
  218.          byte; the tokens are not EOS terminated. */
  219.       output_attribute_token(*ptr, ptr + 1);
  220.       ptr += *ptr + 1;
  221.      }
  222.      output_end_attribute();
  223. }
  224.  
  225. static VOID handle_single_token(ent, al, aln)
  226. UNCH *ent;
  227. struct ad *al;
  228. int aln;
  229. {
  230.      if (ADTYPE(al, aln) == ANOTEGRP && !DCNMARK(ADDATA(al, aln).x))
  231.       output_notation(ADVAL(al, aln) + 1,
  232.               ADDATA(al, aln).x->pubid,
  233.               ADDATA(al, aln).x->sysid);
  234.      else if (ADTYPE(al, aln) == AENTITY)
  235.       define_entity(ADVAL(al, aln));
  236.      output_begin_attribute(ent, ADNAME(al, aln), ADTYPE(al, aln));
  237.      if (ADTYPE(al, aln) == ACHARS) {
  238.       putchar(' ');
  239.       print_string(ustrlen(ADVAL(al, aln)), ADVAL(al, aln), 0);
  240.      }
  241.      else
  242.       output_attribute_token(*ADVAL(al, aln) - 2, ADVAL(al, aln) + 1);
  243.      output_end_attribute();
  244. }
  245.  
  246. static VOID output_notation(name, pubid, sysid)
  247. UNCH *name;
  248. UNCH *pubid, *sysid;
  249. {
  250.      flush_data();
  251.      print_id((UNIV)0, pubid, sysid);
  252.      printf("%c%s\n", DEFINE_NOTATION_CODE, name);
  253. }
  254.  
  255. static VOID output_internal_entity(ename, is_sdata, text)
  256. UNCH *ename;
  257. int is_sdata;
  258. UNCH *text;
  259. {
  260.      flush_data();
  261.      printf("%c%s %s ", DEFINE_INTERNAL_ENTITY_CODE, ename,
  262.         is_sdata ? "SDATA" : "CDATA");
  263.      print_string(text ? ustrlen(text) : 0, text, 0);
  264.      putchar('\n');
  265. }
  266.  
  267. static VOID output_subdoc(nm, id, pubid, sysid)
  268. UNCH *nm;
  269. UNIV id;
  270. UNCH *pubid, *sysid;
  271. {
  272.      flush_data();
  273.      print_id(id, pubid, sysid);
  274.      printf("%c%s\n", DEFINE_SUBDOC_ENTITY_CODE, nm);
  275. }
  276.  
  277. #ifdef SUPPORT_SUBDOC
  278.  
  279. static VOID process_subdoc(nm, id)
  280. UNCH *nm;
  281. UNIV id;
  282. {
  283.      if (!suppsw) {
  284.       flush_data();
  285.       output_location();
  286.       printf("%c%s\n", START_SUBDOC_CODE, nm);
  287.       fflush(stdout);
  288.      }
  289.      fflush(stderr);
  290.  
  291.      if (id) {
  292.       char **argv;
  293.       int ret;
  294.  
  295.       argv = make_argv(id);
  296.       ret = run_process(argv);
  297.       if (ret != 0)
  298.            suberr++;
  299.       
  300.       current_filename = 0;
  301.       free(argv);
  302.       if (ret == 0)
  303.            get_subcaps();
  304.      }
  305.      else {
  306.       suberr++;
  307.       appl_error(E_SUBDOC, nm);
  308.      }
  309.  
  310.      if (!suppsw)
  311.       printf("%c%s\n", END_SUBDOC_CODE, nm);
  312. }
  313.  
  314. #endif /* SUPPORT_SUBDOC */
  315.  
  316. static VOID output_external_entity(nm, xtype, id, pubid, sysid, dcn)
  317. UNCH *nm, *dcn;
  318. UNIV id;
  319. UNCH *pubid, *sysid;
  320. int xtype;
  321. {
  322.      char *type;
  323.  
  324.      flush_data();
  325.  
  326.      print_id(id, pubid, sysid);
  327.  
  328.      switch (xtype) {
  329.      case ESNCDATA:
  330.       type = "CDATA";
  331.       break;
  332.      case ESNNDATA:
  333.       type = "NDATA";
  334.       break;
  335.      case ESNSDATA:
  336.       type = "SDATA";
  337.       break;
  338.      default:
  339.       return;
  340.      }
  341.      printf("%c%s %s %s\n", DEFINE_EXTERNAL_ENTITY_CODE, nm, type, dcn);
  342. }
  343.  
  344. static VOID output_record_end()
  345. {
  346.      static UNCH re = RECHAR;
  347.      print_data(1, &re, 0);
  348. }
  349.  
  350. static VOID output_pcdata(n, s)
  351. UNS n;
  352. UNCH *s;
  353. {
  354.      print_data(n, s, 0);
  355. }
  356.  
  357. static VOID output_cdata(n, s)
  358. UNS n;
  359. UNCH *s;
  360. {
  361.      print_data(n, s, 0);
  362. }
  363.  
  364. static VOID output_sdata(n, s)
  365. UNS n;
  366. UNCH *s;
  367. {
  368.      print_data(n, s, 1);
  369. }
  370.  
  371. static VOID output_entity_reference(s)
  372. UNCH *s;
  373. {
  374.      flush_data();
  375.      output_location();
  376.      printf("%c%s\n", REFERENCE_ENTITY_CODE, s);
  377. }
  378.  
  379. static VOID output_start_tag(s)
  380. UNCH *s;
  381. {
  382.      flush_data();
  383.      output_location();
  384.      printf("%c%s\n", START_CODE, s);
  385. }
  386.  
  387. static VOID output_end_tag(s)
  388. UNCH *s;
  389. {
  390.      flush_data();
  391.      printf("%c%s\n", END_CODE, s);
  392. }
  393.  
  394. static VOID output_processing_instruction(n, s)
  395. UNS n;
  396. UNCH *s;
  397. {
  398.      flush_data();
  399.      output_location();
  400.      putchar(PI_CODE);
  401.      print_string(n, s, 0);
  402.      putchar('\n');
  403. }
  404.  
  405. static VOID output_appinfo(n, s)
  406. UNS n;
  407. UNCH *s;
  408. {
  409.      flush_data();
  410.      output_location();
  411.      putchar(APPINFO_CODE);
  412.      print_string(n, s, 0);
  413.      putchar('\n');
  414. }
  415.      
  416.  
  417. static VOID output_implied_attribute(ent, aname)
  418. UNCH *ent, *aname;
  419. {
  420.      flush_data();
  421.      if (ent)
  422.       printf("%c%s %s IMPLIED\n", DATA_ATTRIBUTE_CODE, ent, aname);
  423.      else
  424.       printf("%c%s IMPLIED\n", ATTRIBUTE_CODE, aname);
  425. }
  426.  
  427. static char *attribute_type_string(type)
  428. int type;
  429. {
  430.      switch (type) {
  431.      case ANMTGRP:
  432.      case ANAME:
  433.      case ANMTOKE:
  434.      case ANUTOKE:
  435.      case ANUMBER:
  436.      case ANAMES:
  437.      case ANMTOKES:
  438.      case ANUTOKES:
  439.      case ANUMBERS:
  440.      case AID:
  441.      case AIDREF:
  442.      case AIDREFS:
  443.       return "TOKEN";
  444.      case ANOTEGRP:
  445.       return "NOTATION";
  446.      case ACHARS:
  447.       return "CDATA";
  448.      case AENTITY:
  449.      case AENTITYS:
  450.       return "ENTITY";
  451.      }
  452. #if 0
  453.      fatal("invalid attribute type %d", type);
  454. #endif
  455.      return "INVALID";
  456. }      
  457.  
  458. static VOID output_begin_attribute(ent, aname, type)
  459. UNCH *ent, *aname;
  460. int type;
  461. {
  462.      flush_data();
  463.      if (ent)
  464.       printf("%c%s %s %s", DATA_ATTRIBUTE_CODE, ent, aname,
  465.          attribute_type_string(type));
  466.      else
  467.       printf("%c%s %s", ATTRIBUTE_CODE, aname,
  468.          attribute_type_string(type));
  469.  
  470. }
  471.  
  472. static VOID output_attribute_token(vallen, val)
  473. UNS vallen;
  474. UNCH *val;
  475. {
  476.      putchar(' ');
  477.      for (; vallen > 0; --vallen, ++val)
  478.       putchar(*val);
  479. }
  480.  
  481. static VOID output_end_attribute()
  482. {
  483.      putchar('\n');
  484. }
  485.  
  486. static VOID print_data(n, s, is_sdata)
  487. UNS n;
  488. UNCH *s;
  489. int is_sdata;
  490. {
  491.      if (n > 0 || is_sdata) {
  492.       if (n == 1 && *s == RECHAR)
  493.            current_lineno++;
  494.       else
  495.            output_location();
  496.       if (!have_data)
  497.            putchar(DATA_CODE);
  498.       print_string(n, s, is_sdata);
  499.       have_data = 1;
  500.      }
  501. }
  502.  
  503. static VOID flush_data()
  504. {
  505.      if (have_data) {
  506.       putchar('\n');
  507.       have_data = 0;
  508.      }
  509. }
  510.  
  511. static VOID output_location()
  512. {
  513.      char *filename;
  514.      unsigned long lineno;
  515.      int filename_changed = 0;
  516.  
  517.      if (!locsw)
  518.       return;
  519.      if (!sgmlloc(&lineno, &filename))
  520.       return;
  521.      if (!current_filename || strcmp(filename, current_filename) != 0)
  522.       filename_changed = 1;
  523.      else if (lineno == current_lineno)
  524.       return;
  525.      flush_data();
  526.      printf("%c%lu", LOCATION_CODE, lineno);
  527.      current_lineno = lineno;
  528.      if (filename_changed) {
  529.       putchar(' ');
  530.       print_filename(filename);
  531.       current_filename = filename;
  532.      }
  533.      putchar('\n');
  534. }
  535.  
  536. static VOID print_string(slen, s, is_sdata)
  537. UNS slen;
  538. UNCH *s;
  539. int is_sdata;
  540. {
  541.      if (is_sdata)
  542.       fputs("\\|", stdout);
  543.      while (slen > 0) {
  544.       UNCH ch = *s++;
  545.       slen--;
  546.       if (ch == DELSDATA) {
  547.            if (is_sdata)
  548.             ;        /* I don't think this should happen */
  549.            else
  550.             fputs("\\|", stdout);
  551.            ;
  552.       }
  553.       else if (ch == DELCDATA)
  554.            ;
  555.       else {
  556.            if (ch == DELNONCH) {
  557.             if (!slen)
  558.              break;
  559.             ch = UNSHIFTNON(*s);
  560.             s++;
  561.             slen--;
  562.            }
  563.            switch (ch) {
  564.            case RECHAR:
  565.             fputs("\\n", stdout);
  566.             break;
  567.            case '\\':
  568.             fputs("\\\\", stdout);
  569.             break;
  570.            default:
  571.             if (ISASCII(ch) && isprint(ch))
  572.              putchar(ch);
  573.             else
  574.              printf("\\%03o", ch);
  575.             break;
  576.            }
  577.       }
  578.      }
  579.      if (is_sdata)
  580.       fputs("\\|", stdout);
  581. }
  582.             
  583.  
  584. static VOID print_id(id, pubid, sysid)
  585. UNIV id;
  586. UNCH *pubid;
  587. UNCH *sysid;
  588. {
  589.  
  590.      if (pubid) {
  591.       putchar(PUBID_CODE);
  592.       print_string(ustrlen(pubid), pubid, 0);
  593.       putchar('\n');
  594.      }
  595.  
  596.      if (sysid) {
  597.       putchar(SYSID_CODE);
  598.       print_string(ustrlen(sysid), sysid, 0);
  599.       putchar('\n');
  600.      }
  601.  
  602.      if (id) {
  603.       char *p;
  604.  
  605.       for (p = id; *p != '\0'; p++) {
  606.            putchar(FILE_CODE);
  607.            do {
  608.             switch (*p) {
  609.             case '\\':
  610.              fputs("\\\\", stdout);
  611.              break;
  612.             case '\n':
  613.              fputs("\\n", stdout);
  614.              break;
  615.             default:
  616.              if (ISASCII(*p) && isprint((UNCH)*p))
  617.                   putchar(*p);
  618.              else
  619.                   printf("\\%03o", (UNCH)*p);
  620.              break;
  621.             }
  622.            } while (*++p);
  623.            putchar('\n');
  624.       }
  625.      }
  626. }
  627.  
  628. static VOID print_filename(s)
  629. char *s;
  630. {
  631.      for (; *s; s++)
  632.       switch (*s) {
  633.       case '\\':
  634.            fputs("\\\\", stdout);
  635.            break;
  636.       case '\n':
  637.            fputs("\\n", stdout);
  638.            break;
  639.       default:
  640.            if (ISASCII(*s) && isprint((UNCH)*s))
  641.             putchar(*s);
  642.            else
  643.             printf("\\%03o", (UNCH)*s);
  644.            break;
  645.       }
  646. }
  647.  
  648. /*
  649. Local Variables:
  650. c-indent-level: 5
  651. c-continued-statement-offset: 5
  652. c-brace-offset: -5
  653. c-argdecl-indent: 0
  654. c-label-offset: -5
  655. End:
  656. */
  657.