dthelp: Further coverity fixes
[oweals/cde.git] / cde / programs / dthelp / parser / pass1 / helptag / xref.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 libraries 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: xref.c /main/3 1995/11/08 10:13:50 rswiston $ */
24 /*
25 Copyright 1988, 1989 Hewlett-Packard Co.
26 */
27
28 /* HP Tag to TeX cross-reference processing */
29
30 #include "userinc.h"
31 #include "globdec.h"
32
33 /* Chk for duplicate xref id's, called in TEST, S1, S2, S3, S4, and rsect. */
34 M_WCHAR *checkid(id)
35 M_WCHAR *id;
36 {
37 struct xref *xref;
38 char *buffer;
39 char *mb_id;
40
41 if (!id) return(NULL);
42
43 m_getline(&xrffile, &xrfline);
44 if (xrffile == NULL)
45     {
46     /* set to primary input */
47     xrffile = inputname;
48     }
49
50 xref = (struct xref*) m_lookfortrie(id, &xtree);
51 if (!xref) return(id);  /* not in trie, so not previously defined */
52
53 if (!(xref->wheredef))  /* defined only in previous pass */
54     return(id);
55
56 /* else, we have a duplicate definition of id */
57 m_err1("Redefinition of ID '%s'", id);
58 mb_id = MakeMByteString(id);
59 buffer = (char *) m_malloc(1 + strlen(firstused) + strlen(mb_id) + 6,
60                            "error buffer");
61 sprintf(buffer, firstused, mb_id, xref->line);
62 m_errline(buffer);
63 m_free(buffer, "error buffer");
64 m_free(mb_id,"multi-byte string");
65
66 if (xref->file)
67     {
68     char *mb_file;
69
70     mb_file = MakeMByteString(xref->file);
71     buffer = (char *) m_malloc(1 - 2 + strlen(offile) + strlen(mb_file),
72                                "error buffer");
73     sprintf(buffer, offile, mb_file);
74     m_errline(buffer);
75     m_free(buffer, "error buffer");
76     m_free(mb_file,"multi-byte string");
77     }
78 m_errline(".\n");
79 return(NULL);
80 }
81
82 /* Write a single cross-reference macro definition */
83 static void defxref(xfile, id, xref)
84 FILE *xfile;
85 M_WCHAR *id;
86 struct xref *xref;
87 {
88 char *csname;
89 char *p;
90 char *buffer;
91
92 csname = MakeMByteString(id);
93 if (xref->defined)
94     {
95     char *mb_text;
96
97     mb_text = MakeMByteString(xref->textptr);
98     fprintf(xfile,
99             "\\definexref %s\\\\endxref\001%s\002\001%s",
100             csname,
101             mb_text,
102             xref->chapstring);
103     fprintf(xfile,
104             "\002\001%c\002\001%s\002\001%c\002%%\n",
105             xref->csensitive ? 'Y' : 'N',
106             xref->inchapter ? "\\LOCchap" : "\\LOCapp",
107             xref->xrefable ? 'Y' : 'N');
108     m_free(mb_text,"multi-byte string");
109     }
110 else
111     {
112     fprintf(xfile, "\\undefinedxref %s\\\\endxref\001", csname);
113     for (p = csname; *p ; p++)
114         outchar(*p, xfile);
115     fputs("\002%\n", xfile);
116     m_eprefix();  /* correctly delimit error in error file */
117     buffer = (char *) m_malloc(1 - 2 + strlen(undef) + w_strlen(id),
118                                "error buffer");
119     sprintf(buffer, undef, csname);
120     m_errline(buffer);
121     m_free(buffer, "error buffer");
122     if (xref->file)
123         {
124         char *mb_file;
125
126         mb_file = MakeMByteString(xref->file);
127         buffer = (char *) m_malloc(1 - 2 + strlen(infile) +
128                                    strlen(mb_file),
129                                    "error buffer");
130         sprintf(buffer, infile, mb_file);
131         m_errline(buffer);
132         m_free(buffer, "error buffer");
133         m_free(mb_file,"multi-byte string");
134         }
135     buffer = (char *) m_malloc(1 - 2 + strlen(online) + 10,
136                                "error buffer");
137     sprintf(buffer, online, xref->line);
138     m_errline(buffer);
139     m_free(buffer, "error buffer");
140     }
141 m_free(csname, "csname");
142 }
143
144 /* Write cross-reference file for next time document is processed
145    and TeX macro file for post-processing this pass */
146 void dumpxref(M_NOPAR)
147 {
148 int n;
149 M_WCHAR id[M_NAMELEN + 1];
150 M_TRIE *node[M_NAMELEN + 1];
151 M_TRIE *current;
152 FILE *tex;
153
154 strcpy(helpext, ".xrh");
155 tex = fopen(helpbase, "w");
156 if (! tex) {
157         return;
158 }
159 fprintf(tex, "\\gobble\001%s\002%%\n", m_signon);
160 fputs("% Generated Cross-Reference Macros (for a particular document)\n", tex);
161 if (! xtree.data) {
162         fclose(tex);
163         return;
164 }
165
166 n = 0;
167 current = xtree.data;
168 while (TRUE)
169     {
170     id[n] = current->symbol;
171     node[n] = current->next;
172     if (! id[n])
173         {
174         /* Process one table entry */
175         defxref(tex, id, (struct xref *) current->data);
176
177         /* Look for the next one */
178         current = current->next;
179         while (! current)
180             {
181             n--;
182             if (n < 0)
183                 {
184                 fclose(tex);
185                 return;
186                 }
187             current = node[n];
188             }
189         }
190     else
191         {
192         current = current->data;
193         n++;
194         }
195     }
196 }
197
198 /* Copies string to end of current cross-reference string */
199 void idstring(string)
200 M_WCHAR *string;
201 {
202 int length;
203
204 length = w_strlen(string);
205 if (xstrlen + length + 1 > (sizeof(xrefstring) / sizeof(M_WCHAR)))
206     {
207     if (! iderr)
208         {
209         m_error(
210     "Internal error. Too many characters in cross-reference expansion.");
211         iderr = TRUE;
212         }
213     return;
214     }
215
216 w_strcpy(&xrefstring[xstrlen],string);
217 xstrlen += length;
218 }
219
220 /* Initializes cross-reference table reading in file output from previous
221    pass through document */
222 void loadxref(M_NOPAR)
223 {
224 M_WCHAR id[M_NAMELEN + 1];
225 char c, d;
226 int nextc;
227 int n;
228 LOGICAL csensitive;
229 LOGICAL inchapter;
230 LOGICAL xrefable;
231 char chapnum[15];
232 char string[15];
233 int braces;
234 M_WCHAR *p, *pStart;
235 static M_WCHAR wbs = 0, wca, wcb, wnl, weof;
236
237 if (! xrf) return;
238
239 if (!wbs)
240     {
241     char mb_eof;
242
243     mbtowc(&wbs, "\\", 1);
244     mbtowc(&wca, "\001", 1); /* ^A */
245     mbtowc(&wcb, "\002", 1); /* ^B */
246     mbtowc(&wnl, "\n", 1);
247     mb_eof = EOF;
248     mbtowc(&weof, &mb_eof, 1);
249     }
250
251 while (TRUE)
252     {
253     if (fscanf(xrf, "%14s ", string) != 1)
254         {
255         fclose(xrf);
256         return;
257         }
258     if (! strcmp(string, "\\undefinedxref"))
259         {
260         for (nextc = mb_getwc(xrf);
261              (nextc != wnl) && (nextc != weof);
262              nextc = mb_getwc(xrf)
263             );
264         continue;
265         }
266     for (n = 0; n <= M_NAMELEN ; n++)
267         {
268         nextc = mb_getwc(xrf); /* use mb_getwc to read multi-byte chars */
269         if (nextc == weof)
270             {
271             m_error("Incomplete cross-reference file.");
272             fclose(xrf);
273             return;
274             }
275         if (nextc == wbs) break;
276         id[n] = nextc;
277         }
278     if (n > M_NAMELEN)
279         {
280         m_error("Error in cross-reference file.");
281         fclose(xrf);
282         return;
283         }
284     pStart = p = MakeWideCharString("\\endxref\001");
285     for (; *p ; p++)
286         {
287         nextc = mb_getwc(xrf);
288         if (nextc != *p)
289             {
290             m_free(pStart,"wide character string");
291             m_error("Error in cross-reference file.");
292             fclose(xrf);
293             return;
294             }
295         }
296     m_free(pStart,"wide character string");
297     id[n] = M_EOS;
298     for (xstrlen = 0, braces = 1;
299          xstrlen < (sizeof(xrefstring) / sizeof(M_WCHAR));
300          xstrlen++)
301         {
302         xrefstring[xstrlen] = mb_getwc(xrf);
303         if (xrefstring[xstrlen] == wca) braces++;
304         else if (xrefstring[xstrlen] == wcb) if (! --braces) break;
305     }
306     if (xstrlen >= (sizeof(xrefstring) / sizeof(M_WCHAR)))
307         {
308         m_error("Error in cross-reference file");
309         fclose(xrf);
310         return;
311         }
312
313     xrefstring[xstrlen] = M_EOS;
314     if ((fscanf(xrf,
315                 "\001%14[^\002]\002\001%c\002\001%8[^\002]\002\001%c\002%%\n",
316                 chapnum, &c, string, &d) != 4)                ||
317             (c != 'Y' && c != 'N') ||  (d != 'Y' && d != 'N') || 
318             (strcmp(string, "\\LOCapp") && strcmp(string, "\\LOCchap"))
319        )
320         {
321         m_error("Error in cross-reference file");
322         fclose(xrf);
323         return;
324         }
325     csensitive = (LOGICAL) (c == 'Y');
326     inchapter = (LOGICAL) (strcmp(string, "\\LOCchap") == FALSE);
327     xrefable = (LOGICAL) (d == 'Y');
328     setid(id,
329           FALSE,
330           csensitive,
331           inchapter,
332           chapnum,
333           NULL,
334           0,
335           xrefable);
336     }
337 /* fclose(xrf);  ** not reachable; left in for future reference */
338 }
339
340
341 /* Save a cross-reference ID and associated expansion */
342 #if defined(M_PROTO)
343 void setid(M_WCHAR *id, LOGICAL where, LOGICAL csensitive, LOGICAL inchapter,
344            char *chapter, M_WCHAR *xrffile, int xrfline, LOGICAL xrefable)
345 #else
346 void setid(id, where, csensitive, inchapter, chapter, xrffile, xrfline, xrefable)
347 M_WCHAR *id;
348 LOGICAL where;
349 LOGICAL csensitive;
350 LOGICAL inchapter;
351 char *chapter;
352 M_WCHAR *xrffile;
353 int xrfline;
354 LOGICAL xrefable;
355 #endif
356 {
357 struct xref *old;
358 struct xref *xref;
359 char *buffer;
360
361 if (!*id)
362     {
363     m_err2("Erroneous cross reference of `%s' for id `%s'",
364     xrefstring,
365     id);
366     return;
367     }
368 xref = (struct xref *) m_malloc(sizeof(struct xref), "xref");
369 if (old = (struct xref *) m_ntrtrie(id, &xtree, (M_TRIE *) xref))
370     {
371     m_free(xref, "xref");
372     xref = old;
373     if (xref->wheredef)
374         {
375         char *mb_id;
376
377         mb_id = MakeMByteString(id);
378         m_err1("Redefinition of ID '%s'", id);
379         buffer = (char *)
380             m_malloc(1 + strlen(firstused) + w_strlen(id) + 6,
381                      "error buffer");
382         sprintf(buffer, firstused, mb_id, xref -> line);
383         m_errline(buffer);
384         m_free(buffer, "error buffer");
385         m_free(mb_id,"multi-byte string");
386         if (xref->file)
387             {
388             char *mb_file;
389
390             mb_file = MakeMByteString(xref->file);
391             buffer = (char *)
392                 m_malloc(1 - 2 + strlen(offile) + strlen(mb_file),
393                          "error message");
394             sprintf(buffer, offile, mb_file);
395             m_errline(buffer);
396             m_free(buffer, "error buffer");
397             m_free(mb_file,"multi-byte string");
398             }
399         m_errline(".\n");
400         return;
401         }
402     if (xref->defined)
403         {
404         if (w_strcmp(xrefstring, xref->textptr) != 0) /* ref has changed */
405             have_forward_xrefs = TRUE;         /* so force a second pass */
406         m_free(xref->chapstring, "xref chapter string");
407         m_free(xref->textptr, "xref text pointer");
408         }
409     }
410 else xref->retrieved = FALSE;
411
412 xref->defined = TRUE;
413 xref->wheredef = where;
414 xref->csensitive = csensitive;
415 xref->inchapter = inchapter;
416 xref->chapstring =
417     (char *) m_malloc(strlen(chapter) + 1, "xref chapter string");
418 xref->textptr = (M_WCHAR *) m_malloc(xstrlen + 1, "xref text pointer");
419 strcpy(xref->chapstring, chapter);
420 w_strcpy(xref->textptr, xrefstring);
421 xref->file = xrffile;
422 xref->line = xrfline;
423 xref->xrefable = xrefable;
424 xstrlen = 0;
425 savid = NULL;
426 }
427
428 /* Generate a cross-reference */
429 void xrefexpand(id)
430 M_WCHAR *id;
431 {
432 struct xref *xref;
433 struct xref *old;
434 #define format "\\<xref %s>"
435 char *texcode;
436 char *csname;
437
438 /* ID is 0 in case of a parameter error which MARKUP will report */
439 if (! id) return;
440
441 /* Write call to generated macro in output file */
442 csname = MakeMByteString(id);
443 texcode = (char *) m_malloc(sizeof(format) + strlen(csname), "texcode");
444 sprintf(texcode, format, csname);
445
446 if (echo)
447     {
448     mb_echohead(m_stago);
449     mb_echohead("XREF ");
450     echohead(id);
451     mb_echohead(m_tagc);
452     }
453
454 if (savhd)
455     mb_shstring(texcode,
456                 &svheadlen,
457                 (sizeof(savehead) / sizeof(M_WCHAR)),
458                 savehead,
459                 "Too many characters in head or caption",
460                 &hderr);
461
462 if (savtc)
463     mb_shstring(texcode,
464                 &svtclen,
465                 (sizeof(savetabcap) / sizeof(M_WCHAR)),
466                 savetabcap,
467                 "Too many characters in table caption",
468                 &hderr);
469
470 if (savid)
471     mb_shstring(texcode,
472                 &xstrlen,
473                 (sizeof(xrefstring) / sizeof(M_WCHAR)),
474                 xrefstring,
475                 "Too many characters in corresponding cross-reference",
476                 &iderr);
477
478 /* Enter id in xref table if it's not already there */
479 xref = (struct xref *) m_malloc(sizeof(struct xref), "xref");
480 if (old = (struct xref *) m_ntrtrie(id, &xtree, (M_TRIE *) xref))
481     {
482     /* non-NULL, we had an old one */
483     m_free(xref, "xref");
484     xref = old;
485     if (! xref->xrefable)
486         {
487         m_error("You can't cross reference to that type of tag");
488         /* but put out the string anyway... */
489
490         /* decrement error counter to treat this as a warning */
491         m_errcnt--;
492         }
493     if (xref->textptr)
494         {
495         /* we have an expansion */
496         char *mb_textptr;
497
498         if (!*xref->textptr)
499             {
500             m_err1("Empty cross reference for id `%s'", id);
501             return;
502             }
503
504         mb_textptr = MakeMByteString(xref->textptr);
505         fprintf(outfile,
506                 "<LINK RID=\"%s\">%s</LINK>",
507                 csname,
508                 mb_textptr);
509         m_free(mb_textptr,"multi-byte string");
510         }
511     else
512         { /* expansion */
513         /* dump out a tag string as a placeholder */
514         fputs(texcode, outfile);
515         /* not really forward, but a null string */
516         have_forward_xrefs = TRUE;
517         /*     xref->defined = FALSE;
518         xref->retrieved = FALSE;
519         xref->textptr = NULL;
520         xref->wheredef = FALSE;*/
521         }
522     }
523 else
524     { /* no old xref */
525     if (rebuild)
526         {
527         m_errline(
528             "Unresolved xrefs. Running HelpTag a second time may help.\n");
529         rebuild = FALSE;  /* one error message will do */
530         }
531     have_forward_xrefs = TRUE;
532     xref->defined = FALSE;
533     xref->retrieved = FALSE;
534     xref->textptr = NULL;
535     xref->wheredef = FALSE;
536
537     /* This is a forward ref.  We assume it is xrefable */
538     /* It will be set correctly if and when the ref is defined */
539     xref->xrefable = TRUE;
540
541     fputs(texcode, outfile);
542     }
543
544 /* Record retrieval status if this is the first reference */
545 if (! xref->retrieved && ! xref->defined)
546     {
547     m_getline(&xref->file, &xref->line);
548     if (xref->file == NULL)
549         {
550         /* set to primary input */
551         xref->file = inputname;
552         }
553     xref->retrieved = TRUE;
554     }
555 m_free(texcode, "texcode buffer");
556 m_free(csname, "csname");
557 }
558