dthelp: compiler warning and coverity warning 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 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: 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 fprintf(tex, "\\gobble\001%s\002%%\n", m_signon);
157 fputs("% Generated Cross-Reference Macros (for a particular document)\n", tex);
158 if (! xtree.data) {
159         fclose(tex);
160         return;
161 }
162
163 n = 0;
164 current = xtree.data;
165 while (TRUE)
166     {
167     id[n] = current->symbol;
168     node[n] = current->next;
169     if (! id[n])
170         {
171         /* Process one table entry */
172         defxref(tex, id, (struct xref *) current->data);
173
174         /* Look for the next one */
175         current = current->next;
176         while (! current)
177             {
178             n--;
179             if (n < 0)
180                 {
181                 fclose(tex);
182                 return;
183                 }
184             current = node[n];
185             }
186         }
187     else
188         {
189         current = current->data;
190         n++;
191         }
192     }
193 }
194
195 /* Copies string to end of current cross-reference string */
196 void idstring(string)
197 M_WCHAR *string;
198 {
199 int length;
200
201 length = w_strlen(string);
202 if (xstrlen + length + 1 > (sizeof(xrefstring) / sizeof(M_WCHAR)))
203     {
204     if (! iderr)
205         {
206         m_error(
207     "Internal error. Too many characters in cross-reference expansion.");
208         iderr = TRUE;
209         }
210     return;
211     }
212
213 w_strcpy(&xrefstring[xstrlen],string);
214 xstrlen += length;
215 }
216
217 /* Initializes cross-reference table reading in file output from previous
218    pass through document */
219 void loadxref(M_NOPAR)
220 {
221 M_WCHAR id[M_NAMELEN + 1];
222 char c, d;
223 int nextc;
224 int n;
225 LOGICAL csensitive;
226 LOGICAL inchapter;
227 LOGICAL xrefable;
228 char chapnum[15];
229 char string[15];
230 int braces;
231 M_WCHAR *p, *pStart;
232 static M_WCHAR wbs = 0, wca, wcb, wnl, weof;
233
234 if (! xrf) return;
235
236 if (!wbs)
237     {
238     char mb_eof;
239
240     mbtowc(&wbs, "\\", 1);
241     mbtowc(&wca, "\001", 1); /* ^A */
242     mbtowc(&wcb, "\002", 1); /* ^B */
243     mbtowc(&wnl, "\n", 1);
244     mb_eof = EOF;
245     mbtowc(&weof, &mb_eof, 1);
246     }
247
248 while (TRUE)
249     {
250     if (fscanf(xrf, "%14s ", string) != 1)
251         {
252         fclose(xrf);
253         return;
254         }
255     if (! strcmp(string, "\\undefinedxref"))
256         {
257         for (nextc = mb_getwc(xrf);
258              (nextc != wnl) && (nextc != weof);
259              nextc = mb_getwc(xrf)
260             );
261         continue;
262         }
263     for (n = 0; n <= M_NAMELEN ; n++)
264         {
265         nextc = mb_getwc(xrf); /* use mb_getwc to read multi-byte chars */
266         if (nextc == weof)
267             {
268             m_error("Incomplete cross-reference file.");
269             fclose(xrf);
270             return;
271             }
272         if (nextc == wbs) break;
273         id[n] = nextc;
274         }
275     if (n > M_NAMELEN)
276         {
277         m_error("Error in cross-reference file.");
278         fclose(xrf);
279         return;
280         }
281     pStart = p = MakeWideCharString("\\endxref\001");
282     for (; *p ; p++)
283         {
284         nextc = mb_getwc(xrf);
285         if (nextc != *p)
286             {
287             m_free(pStart,"wide character string");
288             m_error("Error in cross-reference file.");
289             fclose(xrf);
290             return;
291             }
292         }
293     m_free(pStart,"wide character string");
294     id[n] = M_EOS;
295     for (xstrlen = 0, braces = 1;
296          xstrlen < (sizeof(xrefstring) / sizeof(M_WCHAR));
297          xstrlen++)
298         {
299         xrefstring[xstrlen] = mb_getwc(xrf);
300         if (xrefstring[xstrlen] == wca) braces++;
301         else if (xrefstring[xstrlen] == wcb) if (! --braces) break;
302     }
303     if (xstrlen >= (sizeof(xrefstring) / sizeof(M_WCHAR)))
304         {
305         m_error("Error in cross-reference file");
306         fclose(xrf);
307         return;
308         }
309
310     xrefstring[xstrlen] = M_EOS;
311     if ((fscanf(xrf,
312                 "\001%14[^\002]\002\001%c\002\001%8[^\002]\002\001%c\002%%\n",
313                 chapnum, &c, string, &d) != 4)                ||
314             (c != 'Y' && c != 'N') ||  (d != 'Y' && d != 'N') || 
315             (strcmp(string, "\\LOCapp") && strcmp(string, "\\LOCchap"))
316        )
317         {
318         m_error("Error in cross-reference file");
319         fclose(xrf);
320         return;
321         }
322     csensitive = (LOGICAL) (c == 'Y');
323     inchapter = (LOGICAL) (strcmp(string, "\\LOCchap") == FALSE);
324     xrefable = (LOGICAL) (d == 'Y');
325     setid(id,
326           FALSE,
327           csensitive,
328           inchapter,
329           chapnum,
330           NULL,
331           0,
332           xrefable);
333     }
334 /* fclose(xrf);  ** not reachable; left in for future reference */
335 }
336
337
338 /* Save a cross-reference ID and associated expansion */
339 #if defined(M_PROTO)
340 void setid(M_WCHAR *id, LOGICAL where, LOGICAL csensitive, LOGICAL inchapter,
341            char *chapter, M_WCHAR *xrffile, int xrfline, LOGICAL xrefable)
342 #else
343 void setid(id, where, csensitive, inchapter, chapter, xrffile, xrfline, xrefable)
344 M_WCHAR *id;
345 LOGICAL where;
346 LOGICAL csensitive;
347 LOGICAL inchapter;
348 char *chapter;
349 M_WCHAR *xrffile;
350 int xrfline;
351 LOGICAL xrefable;
352 #endif
353 {
354 struct xref *old;
355 struct xref *xref;
356 char *buffer;
357
358 if (!*id)
359     {
360     m_err2("Erroneous cross reference of `%s' for id `%s'",
361     xrefstring,
362     id);
363     return;
364     }
365 xref = (struct xref *) m_malloc(sizeof(struct xref), "xref");
366 if (old = (struct xref *) m_ntrtrie(id, &xtree, (M_TRIE *) xref))
367     {
368     m_free(xref, "xref");
369     xref = old;
370     if (xref->wheredef)
371         {
372         char *mb_id;
373
374         mb_id = MakeMByteString(id);
375         m_err1("Redefinition of ID '%s'", id);
376         buffer = (char *)
377             m_malloc(1 + strlen(firstused) + w_strlen(id) + 6,
378                      "error buffer");
379         sprintf(buffer, firstused, mb_id, xref -> line);
380         m_errline(buffer);
381         m_free(buffer, "error buffer");
382         m_free(mb_id,"multi-byte string");
383         if (xref->file)
384             {
385             char *mb_file;
386
387             mb_file = MakeMByteString(xref->file);
388             buffer = (char *)
389                 m_malloc(1 - 2 + strlen(offile) + strlen(mb_file),
390                          "error message");
391             sprintf(buffer, offile, mb_file);
392             m_errline(buffer);
393             m_free(buffer, "error buffer");
394             m_free(mb_file,"multi-byte string");
395             }
396         m_errline(".\n");
397         return;
398         }
399     if (xref->defined)
400         {
401         if (w_strcmp(xrefstring, xref->textptr) != 0) /* ref has changed */
402             have_forward_xrefs = TRUE;         /* so force a second pass */
403         m_free(xref->chapstring, "xref chapter string");
404         m_free(xref->textptr, "xref text pointer");
405         }
406     }
407 else xref->retrieved = FALSE;
408
409 xref->defined = TRUE;
410 xref->wheredef = where;
411 xref->csensitive = csensitive;
412 xref->inchapter = inchapter;
413 xref->chapstring =
414     (char *) m_malloc(strlen(chapter) + 1, "xref chapter string");
415 xref->textptr = (M_WCHAR *) m_malloc(xstrlen + 1, "xref text pointer");
416 strcpy(xref->chapstring, chapter);
417 w_strcpy(xref->textptr, xrefstring);
418 xref->file = xrffile;
419 xref->line = xrfline;
420 xref->xrefable = xrefable;
421 xstrlen = 0;
422 savid = NULL;
423 }
424
425 /* Generate a cross-reference */
426 void xrefexpand(id)
427 M_WCHAR *id;
428 {
429 struct xref *xref;
430 struct xref *old;
431 #define format "\\<xref %s>"
432 char *texcode;
433 char *csname;
434
435 /* ID is 0 in case of a parameter error which MARKUP will report */
436 if (! id) return;
437
438 /* Write call to generated macro in output file */
439 csname = MakeMByteString(id);
440 texcode = (char *) m_malloc(sizeof(format) + strlen(csname), "texcode");
441 sprintf(texcode, format, csname);
442
443 if (echo)
444     {
445     mb_echohead(m_stago);
446     mb_echohead("XREF ");
447     echohead(id);
448     mb_echohead(m_tagc);
449     }
450
451 if (savhd)
452     mb_shstring(texcode,
453                 &svheadlen,
454                 (sizeof(savehead) / sizeof(M_WCHAR)),
455                 savehead,
456                 "Too many characters in head or caption",
457                 &hderr);
458
459 if (savtc)
460     mb_shstring(texcode,
461                 &svtclen,
462                 (sizeof(savetabcap) / sizeof(M_WCHAR)),
463                 savetabcap,
464                 "Too many characters in table caption",
465                 &hderr);
466
467 if (savid)
468     mb_shstring(texcode,
469                 &xstrlen,
470                 (sizeof(xrefstring) / sizeof(M_WCHAR)),
471                 xrefstring,
472                 "Too many characters in corresponding cross-reference",
473                 &iderr);
474
475 /* Enter id in xref table if it's not already there */
476 xref = (struct xref *) m_malloc(sizeof(struct xref), "xref");
477 if (old = (struct xref *) m_ntrtrie(id, &xtree, (M_TRIE *) xref))
478     {
479     /* non-NULL, we had an old one */
480     m_free(xref, "xref");
481     xref = old;
482     if (! xref->xrefable)
483         {
484         m_error("You can't cross reference to that type of tag");
485         /* but put out the string anyway... */
486
487         /* decrement error counter to treat this as a warning */
488         m_errcnt--;
489         }
490     if (xref->textptr)
491         {
492         /* we have an expansion */
493         char *mb_textptr;
494
495         if (!*xref->textptr)
496             {
497             m_err1("Empty cross reference for id `%s'", id);
498             return;
499             }
500
501         mb_textptr = MakeMByteString(xref->textptr);
502         fprintf(outfile,
503                 "<LINK RID=\"%s\">%s</LINK>",
504                 csname,
505                 mb_textptr);
506         m_free(mb_textptr,"multi-byte string");
507         }
508     else
509         { /* expansion */
510         /* dump out a tag string as a placeholder */
511         fputs(texcode, outfile);
512         /* not really forward, but a null string */
513         have_forward_xrefs = TRUE;
514         /*     xref->defined = FALSE;
515         xref->retrieved = FALSE;
516         xref->textptr = NULL;
517         xref->wheredef = FALSE;*/
518         }
519     }
520 else
521     { /* no old xref */
522     if (rebuild)
523         {
524         m_errline(
525             "Unresolved xrefs. Running HelpTag a second time may help.\n");
526         rebuild = FALSE;  /* one error message will do */
527         }
528     have_forward_xrefs = TRUE;
529     xref->defined = FALSE;
530     xref->retrieved = FALSE;
531     xref->textptr = NULL;
532     xref->wheredef = FALSE;
533
534     /* This is a forward ref.  We assume it is xrefable */
535     /* It will be set correctly if and when the ref is defined */
536     xref->xrefable = TRUE;
537
538     fputs(texcode, outfile);
539     }
540
541 /* Record retrieval status if this is the first reference */
542 if (! xref->retrieved && ! xref->defined)
543     {
544     m_getline(&xref->file, &xref->line);
545     if (xref->file == NULL)
546         {
547         /* set to primary input */
548         xref->file = inputname;
549         }
550     xref->retrieved = TRUE;
551     }
552 m_free(texcode, "texcode buffer");
553 m_free(csname, "csname");
554 }
555