dthelp: compiler warning and coverity warning fixes
[oweals/cde.git] / cde / programs / dthelp / parser / pass2 / util / conutil.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: conutil.c /main/3 1995/11/08 11:03:16 rswiston $ */
24 /*
25               Copyright 1986 Tandem Computers Incorporated.
26 This product and information is proprietary of Tandem Computers Incorporated.
27                Copyright (c) 1986, 1987, 1988, 1989 Hewlett-Packard Co.
28 */
29
30 /* Conutil has utility procedures for program CONTEXT. */
31 #include <stdio.h>
32 #include <string.h>
33 #include <stdlib.h>
34 #if defined(MSDOS)
35 #include <process.h>
36 #endif
37 #include "basic.h"
38 #include "trie.h"
39
40 #include "cont.h"
41
42 /* Output declaration of dlmptr */
43 void dumpdlmptr(M_NOPAR)
44   {
45     int n;
46
47     fprintf(delim, "M_DELIMEXTERN M_WCHAR *m_dlmptr[%d];\n", dcount+1);
48     fprintf(delim, "M_DELIMEXTERN char *mb_dlmptr[%d]\n", dcount+1);
49     fprintf(delim, "#if defined(M_DELIMDEF)\n  = {\n");
50     for (n = 0 ; n < dcount ; n++) {
51       if (n) fputs(",\n", delim);
52       fprintf(delim, "  %s", dlmptr[n]);
53       }
54     fprintf(delim, "%s", endif);
55     }
56
57 /* Output the generated data structures */
58 #if defined(M_PROTO)
59 void dumptree(LOGICAL sparse)
60 #else
61 void dumptree(sparse)
62   LOGICAL sparse;
63 #endif
64   {
65     int i, count = 0;
66
67     for (i = 0 ; i < ccount ; i++)
68       if (contree[i])
69         countdown(contree[i], &count);
70     fprintf(delim,
71      "M_DELIMEXTERN M_PTRIE m_delimtrie[%d]\n#if defined(M_DELIMDEF)\n = {\n",
72       count);
73     fprintf(context,
74       "M_CONEXTERN int m_contree[%d]\n#if defined(M_CONDEF)\n = {\n  ",
75       ccount);
76
77     count = 0;
78     for (i = 0 ; i < ccount ; i++) {
79       if (contree[i]) {
80         fprintf(context, "%d", count + 1);
81         dumpnode(&first, delim, contree[i], &count, (void *)printval);
82         }
83       else fprintf(context, "0");
84       if (i < ccount - 1) fprintf(context, ",\n  ");
85       }
86     fprintf(delim, "%s", endif);
87     fprintf(context, "%s", endif);
88     nextcon(sparse);
89     }
90
91 /* Enter a delimiter into the delimiter tree for a particular context */
92 void enterdelim(n)
93   int n;
94 {
95 if (! contree[n])
96     {
97     contree[n] = m_gettrienode();
98     }
99
100 if (m_ntrtrie(dstruct->string,
101               contree[n],
102               (void *) (unsigned long) dstruct->count))
103     {
104     char *mb_dstring, *mb_contexts;
105
106     mb_dstring = MakeMByteString(dstring);
107     mb_contexts = MakeMByteString(contexts[n]);
108     dcount--;
109     warning2("Duplicate assignment to delimiter \"%s\" in context \"%s\"",
110              mb_dstring,
111              mb_contexts);
112     m_free(mb_dstring,"multi-byte string");
113     m_free(mb_contexts,"multi-byte string");
114     }
115 }
116
117 /* Read the code to be executed with a given state transition */
118 void getcode(n)
119 int n;
120 {
121 int c ; /* c is int instead of char for use with ungetc */
122 int nested = 1;
123 LOGICAL comment = FALSE;
124 char *mb_context;
125 M_WCHAR wlb = 0, wcm, wnl, wsl, wst;
126
127
128 if (!wlb)
129     {
130     int
131     ret = mbtowc(&wlb, "{", 1); /* keep the "}" balanced */
132     ret = mbtowc(&wcm, ",", 1);
133     ret = mbtowc(&wnl, "\n", 1);
134     ret = mbtowc(&wsl, "/", 1);
135     ret = mbtowc(&wst, "*", 1);
136     (void) ret;
137     }
138
139 while (m_whitespace((M_WCHAR) (c = readchar(FALSE))));
140 if (c != wlb && c != wcm)
141     {
142     unread(c);
143     return;
144     }
145
146 if (! casestarted)
147     {
148     char *mb_dname;
149
150     mb_dname = MakeMByteString(dname);
151     casestarted = TRUE;
152     fprintf(fcase, "      case %s:\n", mb_dname);
153     fprintf(fcase, "        switch (m_prevcon) {\n") ; /* balance the } */
154     m_free(mb_dname,"multi-byte string");
155     }
156
157 mb_context = MakeMByteString(contexts[n]);
158 fprintf(fcase, "          case %s:\n", mb_context);
159 m_free(mb_context,"multi-byte string");
160
161 if (c == wcm) return;
162
163 fprintf(fcase, "/* line %d \"context.dat\" */\n", m_line);
164
165 while (TRUE)
166     {
167     char mb_c[32]; /* arbitrarily large */
168     int  length;
169
170     c = readchar(FALSE);
171     if (c == EOF)
172         {
173         warning("Unexpected EOF");
174         exit(TRUE);
175         }
176
177     length = wctomb(mb_c, c);
178     mb_c[length] = 0;
179     if (length == 1)
180         {
181         switch (mb_c[0])
182             {
183             case '{':
184                 if (! comment) nested++;
185                 break;
186             case '}': 
187                 if (! comment)
188                 if (! --nested)
189                     {
190                     fprintf(fcase,"\n            break ;\n");
191                     return;
192                     }
193                 break;
194             case '/':
195                 if (! comment)
196                     {
197                     fprintf(fcase, "/");
198                     c = readchar(FALSE);
199                     if (c == wst) comment = TRUE;
200                     length = wctomb(mb_c, c);
201                     mb_c[length] = 0;
202                     }
203                 break;
204             case '*':
205                 if (comment)
206                     {
207                     fprintf(fcase, "*");
208                     c = readchar(FALSE);
209                     if (c == wsl) comment = FALSE;
210                     length = wctomb(mb_c, c);
211                     mb_c[length] = 0;
212                     }
213             } /* End case */
214         }
215     fprintf(fcase, "%s", mb_c);
216 #if 0
217     if (c == wnl)
218         fprintf(fcase, "#line %d \"context.dat\"\n", m_line);
219 #endif
220     } /* End while */
221 } /* End proc getcode() */
222
223 /* Read the colon separating the two states in a transition pair */
224 void getcolon(M_NOPAR)
225 {
226 int c ; /* c is int instead of char for use with ungetc */
227 M_WCHAR wcl;
228 char unexp[32]; /* arbitraily large */
229 int  length;
230
231 int ret = mbtowc(&wcl, ":", 1);
232 (void) ret;
233
234 while (TRUE)
235     {
236     c = readchar(FALSE);
237     if (! m_whitespace((M_WCHAR) c)) break;
238     }
239 if (c != wcl)
240     {
241     length = wctomb(unexp, (M_WCHAR) c);
242     unexp[length] = 0;
243     warning1("Expecting : instead of '%s'\n", unexp);
244     }
245 }
246
247 /* Read a context name from an input line */
248 int getContext(M_NOPAR)
249 {
250 M_WCHAR name[CNAMELEN + 1];
251 int c ; /* c is int instead of char for use with ungetc */
252 int i = 0;
253 M_WCHAR wsm = 0, wcl, wcm;
254 char *mb_name;
255
256 if (!wsm)
257     {
258     int
259     ret = mbtowc(&wsm, ";", 1);
260     ret = mbtowc(&wcl, ":", 1);
261     ret = mbtowc(&wcm, ",", 1);
262     (void) ret;
263     }
264
265 while (TRUE)
266     {
267     c = readchar(TRUE);
268     if (c == EOF) return(NOMORE);
269     *name = (M_WCHAR) c;
270     if (*name == wsm) return(NOMORE);
271     if (! m_whitespace(*name)) break;
272     }
273
274 while (TRUE)
275     {
276     i++;
277     if (i >= CNAMELEN)
278         {
279         while (! m_whitespace((M_WCHAR) (c = readchar(TRUE)))
280         && c != wcl
281         && c != wcm
282         && c != EOF
283         && c != wsm);
284         unread(c);
285         break;
286         }
287     c = readchar(TRUE);
288     if (m_whitespace((M_WCHAR) c) ||
289     c == wsm ||
290     c == wcl ||
291     c == wcm ||
292     c == EOF)
293         {
294         unread(c);
295         break;
296         }
297     name[i] = (M_WCHAR) c;
298     }
299 name[i] = M_EOS;
300
301 for (i = 0 ; i < ccount ; i++)
302     if (! w_strcmp(name, contexts[i])) return(i);
303
304 inccon() ;
305 i = w_strlen(name) + 1;
306 contexts[ccount - 1] = (M_WCHAR *) m_malloc(i, "context name");
307 memcpy(contexts[ccount - 1], name, i * sizeof(M_WCHAR));
308
309 mb_name = MakeMByteString(name);
310 fprintf(context, "#define %s %d\n", mb_name, ccount);
311 m_free(mb_name,"multi-byte string");
312
313 return(ccount - 1);
314 }
315
316 /* Read a delimiter name from the input line */
317 LOGICAL getdname(M_NOPAR)
318 {
319 int c;
320 M_WCHAR *p;
321
322 /* Skip leading blanks */
323 while (TRUE)
324     {
325     c = readchar(TRUE);
326     if (c == EOF) return(FALSE);
327     if (! m_whitespace((M_WCHAR) c)) break;
328     }
329 for (p = dname;
330 ! m_whitespace((M_WCHAR) c) && c != EOF;
331 c = readchar(TRUE))
332     {
333     if (p - dname >= DNAMELEN)
334         {
335         while (! m_whitespace((M_WCHAR) c) && c != EOF) c = readchar(TRUE);
336         break;
337         }
338     *p++ = (M_WCHAR) c;
339     }
340 *p = M_EOS;
341 if ((dstruct = (struct dstruct *) m_lookfortrie(dname, &delimtrie)))
342     {
343     withdelim = TRUE;
344     curdelim = dstruct->count - 1;
345     }
346 else
347     {
348     char *mb_dname;
349
350     curdelim = dcount;
351     incdelim();
352     withdelim = FALSE;
353     mb_dname = MakeMByteString(dname);
354     fprintf(delim, "#define %s %d\n", mb_dname, dcount);
355     m_free(mb_dname,"multi-byte string");
356     }
357 return(TRUE);
358 }
359
360 /* Out of context space.  Increase. */
361 void inccon(M_NOPAR)
362   {
363     M_TRIE **newtrie = NULL;
364     int *newtransit = NULL;
365     M_WCHAR **newcontexts = NULL;
366     int trysize;
367     int i, j;
368
369     if (ccount < NUMCON) {
370       ccount++;
371       return;
372       }
373     trysize = m_plus10p(NUMCON);
374     newtrie = (M_TRIE **) calloc(trysize, sizeof(M_TRIE *));
375     newtransit = (int *) calloc(trysize * NUMDELIM, sizeof(int));
376     newcontexts = (M_WCHAR **) calloc(trysize, sizeof(M_WCHAR *));
377     if (! newtrie || ! newtransit || ! newcontexts) {
378       trysize = NUMCON + 1;
379       if (newtrie) free((M_POINTER) newtrie);
380       if (newtransit) free((M_POINTER) newtransit);
381       if (newcontexts) free((M_POINTER) newcontexts);
382       newtrie = (M_TRIE **) calloc(trysize, sizeof(M_TRIE *));
383       newtransit = (int *) calloc(trysize * NUMDELIM, sizeof(int));
384       newcontexts = (M_WCHAR **) calloc(trysize, sizeof(M_WCHAR *));
385       }
386     if (! newtrie || ! newtransit || ! newcontexts) {
387       m_error("Out of memory for contexts");
388       exit(TRUE);
389       }
390     for (i = 0 ; i < ccount ; i++) 
391       for (j = 0 ; j < dcount ; j++)
392         newtransit[i * NUMDELIM + j] = transit(i, j);
393     NUMCON = trysize;
394     free((M_POINTER) xtransit);
395     xtransit = newtransit;
396     memcpy((M_POINTER) newtrie, (M_POINTER) contree,
397            ccount * sizeof(M_TRIE **));
398     memcpy((M_POINTER) newcontexts, (M_POINTER) contexts,
399            ccount * sizeof(M_WCHAR **));
400     free((M_POINTER) contree);
401     free((M_POINTER) contexts);
402     contree = newtrie;
403     contexts = newcontexts;
404     ccount++;
405     }
406
407 /* Increase delimiter space. */
408 void incdelim(M_NOPAR)
409 {
410 int *newtransit = NULL;
411 char **newdlm = NULL;
412 int trysize;
413 int i, j;
414
415 if (dcount < NUMDELIM)
416     {
417     dcount++;
418     return;
419     }
420
421 trysize = m_plus10p(NUMDELIM);
422 newtransit = (int *) calloc(NUMCON * trysize, sizeof(int));
423 if (loading) newdlm = (char **) calloc(trysize, sizeof(M_WCHAR *));
424 if (! newtransit || (loading && ! newdlm))
425     {
426     trysize = NUMDELIM + 1;
427     free(newtransit);
428     newtransit = (int *) calloc(NUMCON * trysize, sizeof(int));
429     if (loading) {
430       free(newdlm);
431       newdlm = (char **) calloc(trysize, sizeof(M_WCHAR *));
432     }
433     }
434 if (! newtransit || (loading && ! newdlm))
435     {
436     m_error("Out of memory for delimiters");
437     exit(TRUE);
438     }
439 for (i = 0 ; i < ccount ; i++) 
440 for (j = 0 ; j < dcount ; j++)
441 newtransit[i * trysize + j] = transit(i, j);
442 free((M_POINTER) xtransit);
443 if (loading)
444     {
445     memcpy((M_POINTER) newdlm, (M_POINTER) dlmptr, dcount * sizeof(M_TRIE **));
446     free((M_POINTER) dlmptr);
447     dlmptr = newdlm;
448     }
449 NUMDELIM = trysize;
450 xtransit = newtransit;
451 dcount++;
452 }
453
454 /* Read delimiter definitions from delim.dat */
455 void loaddelim(M_NOPAR)
456 {
457 int c;
458 M_WCHAR *p;
459 int i;
460 M_WCHAR wnl;
461 char *mb_dname, *mb_dstring;
462
463 int ret = mbtowc(&wnl, "\n", 1);
464 (void) ret;
465
466 loading = TRUE;
467 while ((c = getc(ddat)) != EOF)
468     {
469     /* Skip leading white space */
470     if (c == wnl) continue;
471     if (m_whitespace((M_WCHAR) c))
472         {
473         while ((c = getc(ddat)) != wnl)
474         if (c == EOF) return;
475         continue;
476         }
477     /* Delimiter name into dname */
478     for (p = dname ; ! m_whitespace((M_WCHAR) c) ; c = getc(ddat))
479         {
480         if (c == EOF)
481             {
482             warning("Unexpected EOF");
483             exit(TRUE);
484             }
485         if (p - dname >= DNAMELEN)
486             {
487             while (! m_whitespace((M_WCHAR) c) && c != EOF) c = getc(ddat);
488             if (c == EOF)
489                 {
490                 warning("Unexpected EOF");
491                 exit(TRUE);
492                 }
493             break;
494             }
495         *p++ = m_upper(c);
496         }
497     *p = M_EOS;
498     /* Skip intervening white space */
499     while (m_whitespace((M_WCHAR) c) && c != EOF) c = getc(ddat);
500     if (c == EOF)
501         {
502         warning("Unexpected EOF");
503         exit(TRUE);
504         }
505     /* Delimiter string into dstring */
506     for (p = dstring;
507     ! m_whitespace((M_WCHAR) c) && c != EOF;
508     c = getc(ddat))
509         {
510         if (p - dstring >= DELIMLEN)
511             {
512             m_error("Delimiter string too long");
513             exit(TRUE);
514             }
515         *p++ = c;
516         }
517     *p = M_EOS;
518     if (w_strlen(dstring) > maxd) maxd = w_strlen(dstring);
519     /* Write definitions to output file.  Save data for later. */
520     incdelim();
521     dstruct = (struct dstruct *)
522         m_malloc(sizeof(struct dstruct), "delimiter structure");
523     dstruct->string = (M_WCHAR *) m_malloc(w_strlen(dstring) + 1, "delimiter");
524     w_strcpy(dstruct->string, dstring);
525     dstruct->count = dcount;
526
527     mb_dname = MakeMByteString(dname);
528     fprintf(delim, "#define %s %d\n", mb_dname, dcount);
529     m_free(mb_dname,"multi-byte string");
530
531     for (i = 0 ; dname[i] ; i++)
532         dname[i] = m_lower(dname[i]);
533     mb_dname = MakeMByteString(dname);
534
535     mb_dstring = MakeMByteString(dstring);
536     fprintf(delim,
537             "M_DELIMEXTERN char %s[%d] M_DELIMINIT(\"",
538             mb_dname,
539             (int)strlen(mb_dstring) + 1);
540
541     for (p = dstring ; *p ; p++)
542         {
543         char *pc;
544         char mb_p[32]; /* arbitrarily large */
545         int  length;
546
547         length = wctomb(mb_p, *p);
548         mb_p[length] = 0;
549
550         pc = mb_p;
551         while (*pc)
552             {
553             if (*pc == '"' || *pc == '\\') putc('\\', delim);
554             putc(*pc, delim);
555             pc++;
556             }
557         }
558     fputs("\") ;\n", delim);
559
560     dlmptr[dcount - 1] = MakeMByteString(dname);
561     if (m_ntrtrie(dname, &delimtrie, dstruct)) 
562         m_err1("Duplicate definition of %s", mb_dname);
563     while (c != wnl)
564         {
565         if (c == EOF) break;
566         c = getc(ddat);
567         }
568     m_free(mb_dname,"multi-byte string");
569     m_free(mb_dstring,"multi-byte string");
570     }
571 dumpdlmptr();
572 loading = FALSE;
573 }
574
575 /* Output transition matrix */
576 #if defined(M_PROTO)
577 void nextcon(LOGICAL sparse)
578 #else
579 void nextcon(sparse)
580   LOGICAL sparse;
581 #endif
582   {
583     int i, j;
584     int firstinrow;
585
586     if (sparse) {
587       for (i = 0 ; i < ccount ; i++) {
588         for (j = 0 ; j < dcount ; j++)
589           if (transit(i, j)) nonzero++;
590         nonzero++;
591         }
592       fprintf(delim,
593         "M_DELIMEXTERN struct {\n  %s context ;\n  %s nextcon ;\n",
594           contype, contype);
595       fprintf(delim, "  } m_trnsit [%d]\n", nonzero);
596
597       nonzero = 0;
598       fprintf(delim, "#if defined(M_DELIMDEF)\n  = {\n");
599       fprintf(context, "M_CONEXTERN int m_trnsptr[%d]\n", ccount);
600       fprintf(context, "#if defined(M_CONDEF)\n  = {\n");
601       for (i = 0 ; i < ccount ; i++) {
602         firstinrow = 0;
603         for (j = 0 ; j < dcount ; j++) {
604           if (! transit(i, j)) continue;
605           prtctxt(j, transit(i, j));
606           if (! firstinrow) firstinrow = nonzero;
607           }
608         prtctxt(0, 0);
609         if (i > 0) fprintf(context, ",\n");
610         fprintf(context, "  %d", firstinrow);
611         }
612       fprintf(delim, "%s", endif);
613       fprintf(context, "%s", endif);
614       }
615     else {
616       fprintf(context,
617         "M_CONEXTERN %s m_nextcon[%d][%d]\n#if defined(M_CONDEF)\n  = {\n",
618         contype, ccount, dcount);
619       for (i = 0 ; i < ccount ; i++) {
620         fprintf(context, "  {\n");
621         for (j = 0 ; j < dcount ; j++) {
622           fprintf(context, "    %d", transit(i, j));
623           if (j < dcount - 1) fprintf(context, ",\n");
624           }
625         fprintf(context, "}");
626         if (i < ccount - 1) fprintf(context, ",");
627         fprintf(context, "\n");
628         }
629       fprintf(context, "%s", endif);
630       }
631     }
632   
633 /* If sparse matrix output option, generate a single element of transit
634    array */
635 void prtctxt(column, value)
636   int column, value;
637   {
638     static LOGICAL first = TRUE;
639
640     if (! first) fprintf(delim, ",\n");
641     first = FALSE;
642     fprintf(delim, "  {%d, %d}", column, value);
643     nonzero++;
644     }
645
646
647 /* Read the next input character */
648 #if defined(M_PROTO)
649 int readchar(LOGICAL cap)
650 #else
651 int readchar(cap)
652   LOGICAL cap;
653 #endif
654 {
655 int c;
656 M_WCHAR wnl;
657
658 int ret = mbtowc(&wnl, "\n", 1);
659 (void) ret;
660
661 c = mb_getwc(cdat); /* use mb_getwc so we read multi-byte chars */
662 if (cap && c != EOF) c = m_upper(c);
663
664 if (c == wnl) m_line++;
665
666 return(c);
667 }
668
669 /* Called by utility procedure m_error() -- has content in other programs
670    that use m_error() */
671 void skiptoend(M_NOPAR)
672 {
673 }
674
675 /* Return a character to the input stream for re-reading */
676 void unread(c)
677 int c;
678 {
679 M_WCHAR wnl;
680
681 int ret = mbtowc(&wnl, "\n", 1);
682 (void) ret;
683
684 ungetc(c, cdat);
685 if (c == wnl) m_line--;
686 }