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