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