Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dthelp / parser / pass1 / eltdef / eltutil.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: eltutil.c /main/3 1995/11/08 10:04:56 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 /* Eltutil.c contains procedures for program ELTDEF */
31
32 #include <stdio.h>
33 #include <string.h>
34 #include <malloc.h>
35 #if defined(MSDOS)
36 #include <process.h>
37 #endif
38 #include "basic.h"
39 #include "trie.h"
40
41 #include "dtdext.h"
42
43 #include "eltdef.h"
44 #include "delim.h"
45 #include "context.h"
46
47 #include "entext.h"
48     
49 #include "version.h"
50
51 /* Output indicated action pointer array to if.h */
52 void actptrout(array, name)
53   ACTION **array;
54   char *name;
55   {
56     int i;
57
58     fprintf(ifh, "M_IFEXTERN int %s[%d]\n#if defined(M_IFDEF)\n  = {\n",
59       name, m_elcount);
60     for (i = 0 ; i < m_elcount ; i++) {
61       if (i > 0) fprintf(ifh, ",\n");
62       fprintf(ifh, "  %d", array[i] ? array[i]->count : M_NULLVAL);
63       }
64     fprintf(ifh, "}\n#endif\n  ;\n");
65     }
66
67
68 /* Close a code file and write jump table at the end */
69 #if defined(M_PROTO)
70 void closeiffile(LOGICAL flag, FILE *file, int count, char *table, char *proto)
71 #else
72 void closeiffile(flag, file, count, table, proto)
73   LOGICAL flag;
74   FILE *file;
75   int count;
76   char *table;
77   char *proto;
78 #endif
79   {
80     int i;
81
82     endcode(flag, file);
83     if (count) {
84       fprintf(file,
85         "void (*m_%stable[])(\n#if defined(M_PROTO)\n  %s\n#endif\n  ) = {\n",
86         table, proto);
87       fprintf(file, "  m_%s1, /* Place holder for 1-based indexing */\n",
88                     table);
89       for (i = 1 ; i <= count ; i++) {
90         fprintf(file, "  m_%s%d", table, i);
91         if (i != count) fputs(",\n", file);
92         }
93       fputs("} ;\n", file);
94       }
95     else
96       fprintf(file,
97         "void (*m_%stable[1])(\n#if defined(M_PROTO)\n  %s\n#endif\n  ) ;\n",
98         table, proto);
99     fclose(file);
100     }
101
102 /* Called when the C identifier to be #define'd to a parameter value is
103    scanned */
104 void cvalue(M_NOPAR)
105   {
106     PARVAL *new;
107
108     new = (PARVAL *) m_malloc(sizeof(PARVAL), "parameter value");
109     if (pval = (PARVAL *) m_ntrtrie(name, &parval, (M_TRIE *) new))
110       m_free(new, "parameter value");
111     else {
112       new->line = 0;
113       new->value = NULL;
114       new->cname = (M_WCHAR *) m_malloc(w_strlen(name) + 1, "C name");
115       w_strcpy(new->cname, name);
116       pval = new;
117       }
118     }
119
120
121 /* Called after last input character is read to place closing punctuation
122    at end of output files and close them */
123 void done(M_NOPAR)
124   {
125     M_ENTITY *ent;
126     ACTION *actp;
127     LOGICAL first;
128     int i;
129
130     closeiffile(inent, entfile, codeent, "c", nopar);
131     closeiffile(intext, tfile, tactions, "t", tproto);
132     closeiffile(inpc, pfile, pactions, "p", pproto);
133     closeiffile(insc, sfile, sactions, "s", nopar);
134     closeiffile(inec, efile, eactions, "e", nopar);
135     closeiffile(instc, stfile, stactions, "st", stproto);
136
137     endstring();
138     fclose(string);
139
140     /* Write if.h (which was opened for sign-on message) */
141     fprintf(ifh, "M_IFEXTERN int m_gss M_IFINIT(%d) ;\n", gss);
142     fprintf(ifh, "M_IFEXTERN int m_ges M_IFINIT(%d) ;\n", ges);
143     fputs("M_IFEXTERN struct {\n", ifh);
144     fputs("  int data ;\n", ifh);
145     fputs("  M_ELEMENT element ;\n", ifh);
146     fputs("  int son ;\n", ifh);
147     fputs("  int next ;\n", ifh);
148     if (actlen) {
149       fprintf(ifh,
150               "  } m_action[%d]\n#if defined(M_IFDEF)\n  = {\n",
151               actlen);
152
153       first = TRUE;
154       for (actp = firstact ; actp ; actp = actp->nextact) {
155         if (first) first = FALSE;
156         else fprintf(ifh, ",\n");
157         fprintf(ifh, "  %d, %d, %d, %d",
158                 actp->data, actp->element,
159                 actp->son ? actp->son->count : M_NULLVAL,
160                 actp->next ? actp->next->count : M_NULLVAL);
161         }
162       fprintf(ifh, "}\n#endif\n  ;\n");
163       }
164     else fputs("  } m_action[1] ;\n", ifh);
165
166     actptrout(starray, "m_starray");
167     actptrout(etarray, "m_etarray");
168     actptrout(scarray, "m_scarray");
169     actptrout(ecarray, "m_ecarray");
170     actptrout(tcarray, "m_tcarray");
171     actptrout(pcarray, "m_pcarray");
172     actptrout(stcarray, "m_stcarray");
173
174     outstring();
175     m_openchk(&pvalh, "pval.h", "w");
176     fputs("/* Parameter values specified in the interface */\n", pvalh);
177     if (parval.data) outpval(parval.data);
178
179     fclose(ifh);
180
181     /* Report any elements and entities left undefined */
182     for (i = 0 ; i < m_elcount ; i++)
183       if (! processed[i])
184         warning1("Warning: No specification for element %s",
185           &m_ename[m_element[i].enptr]);
186
187     for (ent = firstent ; ent ; ent = ent->next)
188       if (! ent->wheredef)
189         warning1("Warning: Entity %s undefined", ent->name);
190     entout("entity2");
191
192     exit(errexit);
193     }
194
195 /* Called when finished reading a section of code from the input file */
196 #if defined(M_PROTO)
197 void endcode(LOGICAL flag, FILE *file)
198 #else
199 void endcode(flag, file)
200   LOGICAL flag;
201   FILE *file;
202 #endif
203   {
204     if (flag) fprintf(file, "}}\n\n");
205     }
206
207 /* Called at the end of all initial fields in the interface definition */
208 void endini(M_NOPAR)
209   {
210     if (finitext) 
211       fputs("    putc(m_textchar, m_outfile);\n", tfile);
212     if (finipi) 
213       fputs("    fputs(m_pi, m_outfile) ;\n", pfile);
214     if (finistc)
215       {
216       fputs("    {\n", stfile);
217       fputs("    char *mb_string;\n", stfile);
218       fputs("    mb_string = MakeMByteString(m_string);\n", stfile);
219       fputs("    fputs(mb_string, m_outfile) ;\n", stfile);
220       fputs("    m_free(mb_string,\"multi-byte string\");;\n", stfile);
221       fputs("    }\n", stfile);
222       }
223     }
224
225 /* End the sign-on message */
226 #include <time.h>
227 void endsignon(M_NOPAR)
228   {
229     time_t storetime;
230     char *p;
231     char *timeofday;
232     static char signon1[] = "Interface generated from ";
233     static char signon2[] = " on ";
234     int i;
235     int len;
236     FILE *sgfile;
237
238     signonend = TRUE;
239     /* Discard a trailing carriage return in the sign-on message */
240     if (socr) sochar--;
241
242     time(&storetime);
243     timeofday = ctime(&storetime);
244
245     len =
246       sochar+strlen(signon1)+strlen(signon2)+strlen(iffile)+strlen(timeofday)
247         /* a byte for end of string marker */
248         + 1
249         /* a byte for a carriage return after any user-supplied message */
250         + (sochar ? 1 : 0);
251     m_openchk(&sgfile, "signonx.h", "w");
252     fprintf(sgfile, "extern char m_signon[%d] ;\n", len);
253     fclose(sgfile);
254     m_openchk(&sgfile, "signon.h", "w");
255     fprintf(sgfile, "char m_signon[%d] = {\n", len);
256
257     for (i = 0 ; i <sochar ; i++) 
258       fprintf(sgfile, "  %d,\n", signonmsg[i]);
259     if (sochar) fputs("  10,\n", sgfile);
260     for (p = signon1 ; *p ; p++)
261       fprintf(sgfile, "  %d,\n", *p);
262     for (p = iffile ; *p ; p++)
263       fprintf(sgfile, "  %d,\n", *p);
264     for (p = signon2 ; *p ; p++)
265       fprintf(sgfile, "  %d,\n", *p);
266     for (p = timeofday ; *p ; p++)
267       fprintf(sgfile, "  %d,\n", *p);
268     fputs("  0} ;\n", sgfile);
269     fclose(sgfile);
270     }
271
272 /* Closes a start-string or end-string */
273 void endstring(M_NOPAR)
274   {
275     if (instring) {
276       if (stringstart) stringstart = FALSE;
277       else fprintf(string, ",\n");
278       stringcnt++;
279       instring = FALSE;
280       fprintf(string, "  0");
281       }
282     /* If called after ENDFILE, ensure at least one character in output file*/
283     else if (stringstart) fprintf(string, "  0");
284     }
285
286 /* Set the type of an entity and check if different than declaration in
287    BUILD */
288 void enttype(type)
289   int type;
290   {
291     if ((entity->type == M_PI && type == M_CODEPI) ||
292         (entity->type == M_SDATA && type == M_CODESDATA));
293     else if (entity->type != M_GENERAL &&
294         entity->type != (unsigned char) type)
295       warning1("Redefining type of entity %s", name);
296     entity->type = (unsigned char) type;
297     }
298
299 /* Free storage used for a context-specification chain */
300 void freechain(M_NOPAR)
301   {
302     CHAIN *chainp, *dchainp;
303
304     for (chainp = firstchain ; chainp ;) {
305       dchainp = chainp;
306       chainp = chainp->next;
307       m_free(dchainp, "chain");
308       }
309     firstchain = NULL;
310     nextchain = &firstchain;
311     }     
312
313 /* Returns pointer to data field in action node for current chain of
314    elements */
315 int *getaction(array)
316   ACTION **array;
317   {
318     ACTION *start, *node;
319     CHAIN *chainp;
320
321     if (! array[openelt - 1]) {
322       array[openelt - 1] = getactstruct();
323       array[openelt - 1]->element = openelt + 1;
324       }
325     start = array[openelt - 1];
326     for (chainp = firstchain ; chainp ; chainp = chainp->next) {
327       if (! start->son) {
328         for ( ; chainp ; chainp = chainp->next) {
329           start->son = getactstruct();
330           start->son->element = chainp->elt;
331           start = start->son;
332           }
333         freechain();
334         return(&start->data);
335         }
336       for (node = start->son ; node ; start = node, node = node->next)
337         if (node->element == chainp->elt) break;
338       if (! node) {
339         start->next = getactstruct();
340         start->next->element = chainp->elt;
341         start = start->next;
342         }
343       else start = node;
344       }
345     if (start->data) m_error("Duplicate specification");
346     freechain();
347     return(&start->data);
348     }
349
350 /* Allocate new action structure */
351 ACTION *getactstruct(M_NOPAR)
352   {
353     ACTION *new;
354
355     new = (ACTION *) m_malloc(sizeof(ACTION), "action");
356     new->count = ++actlen;
357     new->data = M_NULLVAL;
358     new->son = new->next = new->nextact = NULL;
359     *nextact = new;
360     nextact = &new->nextact;
361     return(new);
362     }
363
364 /* Program initialization */
365 void initialize(M_NOPAR)
366 {
367 char    **mb_delims;
368 M_WCHAR **wc_delims;
369
370 fprintf(stderr, "MARKUP System - ELTDEF %s\n", M_VERSION);
371 fprintf(stderr, "Copyright (c) 1986, 1987, 1988, 1989 Hewlett-Packard Co.\n");
372
373 m_openchk(&ifh, "if.h", "w");
374 m_openchk(&globdef, "globdef.h", "w");
375 m_openchk(&globdec, "globdec.h", "w");
376 m_openchk(&pfile, "pfile.c", "w");
377 /* ELTDEF opens too many files for use with CodeView debugger.  If
378 this option is set, all code segments are written to one file */
379 if (debug)
380     {
381     tfile =
382     sfile =
383     efile =
384     stfile =
385     entfile =
386     pfile;
387     }
388 else
389     {
390     m_openchk(&tfile, "tfile.c", "w");
391     m_openchk(&sfile, "sfile.c", "w");
392     m_openchk(&efile, "efile.c", "w");
393     m_openchk(&stfile, "stfile.c", "w");
394     m_openchk(&entfile, "entfile.c", "w");
395     }
396 m_openchk(&string, "estring.h", "w");
397 m_openchk(&m_errfile, "error", "w");
398 m_openchk(&ifile, iffile, "r");
399
400 mb_delims = mb_dlmptr;
401 wc_delims = m_dlmptr;
402
403 while (*mb_delims)
404     {
405     *wc_delims++ = MakeWideCharString(*mb_delims);
406     mb_delims++;
407     }
408 *wc_delims = 0;
409
410 /* Start array for sign-on message on globals.h.  Also,
411 make sure there is at least one line in globals.h, because
412 DOS copy does not copy an empty file */
413
414 fputs("/* Global definitions specified by interface designer*/\n",
415 globdef);
416 fputs("/* Global declarations specified by interface designer*/\n",
417 globdec);
418
419 fputs("#if defined(M_IFDEF)\n", ifh);
420 fputs("#define M_IFEXTERN\n", ifh);
421 fputs("#define M_IFINIT(a) = a\n", ifh);
422 fputs("#else\n", ifh);
423 fputs("#define M_IFEXTERN extern\n", ifh);
424 fputs("#define M_IFINIT(a)\n", ifh);
425 fputs("#endif\n", ifh);
426
427 startcode(pactions, &inpc, pfile, "p", pproto, pformal, pftype);
428 startcode(tactions, &intext, tfile, "t", tproto, tformal, tftype);
429 startcode(sactions, &insc, sfile, "s", nopar, nopar, "");
430 startcode(eactions, &inec, efile, "e", nopar, nopar, "");
431 startcode(stactions, &instc, stfile, "st", stproto, stformal, stft);
432 }
433
434 /* Output definitions for strings */
435 void outstring(M_NOPAR)
436   {
437     int c;
438
439     m_openchk(&string, "estring.h", "r");
440     fprintf(ifh, "M_IFEXTERN char m_string[%d]\n",
441             stringcnt > 1 ? stringcnt - 1 : 1);
442     if (stringcnt - 1) {
443       fputs("#if defined(M_IFDEF)\n  = {\n", ifh);
444       while ((c = getc(string)) != EOF) putc(c, ifh);
445       fputs("}\n#endif\n", ifh);
446       }
447     fputs("  ;\n", ifh);
448     fclose(string);
449     }
450
451 /* Output #define's for parameter values */
452 void outpval(p)
453 M_TRIE *p;
454 {
455 M_WCHAR *q;
456
457 for ( ; p ; p = p->next)
458     if (p->symbol) outpval(p->data);
459     else
460         {
461         char *mb_cname;
462
463         mb_cname = MakeMByteString(((PARVAL *) p->data)->cname);
464         fprintf(pvalh,
465                 "/* line %d \"%s\" */\n",
466                 ((PARVAL *) p->data)->line,
467                 iffile);
468         fprintf(pvalh, "#define %s \"", mb_cname);
469         m_free(mb_cname,"multi-byte string");
470         if (q = ((PARVAL *) p->data)->value)
471             for ( ; *q ; q++)
472                 {
473                 char mbq[32]; /* larger than largest possible mbyte char */
474                 int  length;
475
476                 length = wctomb(mbq, *q);
477                 if (length == 1)
478                     switch (*mbq)
479                         {
480                         case '\n':
481                             fputs("\\n", pvalh);
482                             break;
483                         case '"':
484                             fputs("\\\"", pvalh);
485                             break;
486                         default:
487                             putc(*mbq, pvalh);
488                             break;
489                         }
490                 else
491                     fputs(mbq, pvalh);
492                 }
493         fputs("\"\n", pvalh);
494         }
495 }
496
497 /* Skip rest of statement after an error */
498 void skiptoend(M_NOPAR)
499   {
500     int i;
501     static errlev = 0;
502     CVARSTRUCT *cvarp, *dvarp;
503
504     for (cvarp = cvarlist ; cvarp ;) {
505       dvarp = cvarp;
506       m_free(cvarp->cvarptr, "C variable name");
507       cvarp = cvarp->next;
508       m_free(dvarp, "C variable");
509       }
510     cvarlist = NULL;
511     freechain();
512     if (! errlev++) {
513       curcon = ERROR;
514       while (TRUE) {
515         i = scan();
516         if (i == ENDFILE) break;
517         else if (i == ELT) {
518           if (restart <= RSIGNON) endsignon();
519           restart = RELEMENT;
520           curcon = NEEDN;
521           break;
522           }
523         else if (i == GDEF && restart < RGLOBDEF) {
524           if (restart <= RSIGNON) endsignon();
525           restart = RGLOBDEF;
526           curcon = GLOBDEF;
527           break;
528           }
529         else if (i == GDEC && restart < RGLOBDEC) {
530           if (restart <= RSIGNON) endsignon();
531           restart = RGLOBDEC;
532           curcon = GLOBDEC;
533           break;
534           }
535         else if (i == SIGNON && restart < RSIGNON) {
536           curcon = INSIGNON;
537           restart = RSIGNON;
538           break;
539           }
540         else if (i == ENTSTART && restart == RENTITY) {
541           curcon = ENTDEC;
542           break;
543           }
544         curcon = ERROR;
545         } /* end while */
546       } /* end if ! errlev */
547     errlev--;
548   }
549
550 /* Starts processing a code segment from the input file */
551 void startcode(caseno, flag, file, prefix, proto, formal, formtype)
552 int caseno;
553 LOGICAL *flag;
554 FILE *file;
555 char *prefix;
556 char *proto;
557 char *formal;
558 char *formtype;
559 {
560 CVARSTRUCT *cvarp;
561
562 endcode(*flag, file);
563 *flag = TRUE;
564 /* protoype */
565 fprintf(file,
566         "void m_%s%d(\n#if defined(M_PROTO)\n  %s\n#endif\n  ) ;\n",
567         prefix,
568         caseno,
569         proto);
570
571 /* ANSI defines */
572 fputs("#if defined(M_PROTO)\n", file);
573 fprintf(file, "void m_%s%d(%s)\n", prefix, caseno, proto);
574 fputs("#else\n", file);
575 fprintf(file,
576         "void m_%s%d(%s)\n%s\n#endif\n  {\n", /* balance the "}" */
577         prefix,
578         caseno,
579         formal,
580         formtype);
581
582 for (cvarp = cvarlist ; cvarp ; cvarp = cvarp->next)
583     {
584     char *mb_cvarptr;
585
586     mb_cvarptr = MakeMByteString(cvarp->cvarptr);
587     fprintf(file, "    M_WCHAR *%s ;\n", mb_cvarptr);
588     m_free(mb_cvarptr,"multi-byte string");
589     }
590
591 for (cvarp = cvarlist ; cvarp ; cvarp = cvarp->next)
592     {
593     char *mb_cvarptr;
594
595     mb_cvarptr = MakeMByteString(cvarp->cvarptr);
596     fprintf(file,
597             "    m_setparam(&%s, %d) ;\n",
598             mb_cvarptr,
599             cvarp->param);
600     m_free(mb_cvarptr,"multi-byte string");
601     }
602 fprintf(file, "{\n/* line %d \"%s\" */\n", m_line, iffile); /* balance "}" */
603 }
604
605 /* Begins processing a new element */
606 void startelement(M_NOPAR)
607   {
608     CVARSTRUCT *cvarp;
609     CVARSTRUCT *discard;
610
611     for (cvarp = cvarlist ; cvarp ; ) {
612       discard = cvarp;
613       m_free(cvarp->cvarptr, "C variable name");
614       cvarp = cvarp->next;
615       m_free(discard, "C variable");
616       }
617     cvarlist = NULL;
618     if (openelt = m_packedlook(m_entree, name)) {
619       if (processed[openelt - 1])
620         warning1("Warning: Element %s already processed", name);
621       processed[openelt - 1] = TRUE;
622       }
623     else m_err1("Undefined element: %s", name);
624     }
625
626 /* Stores the name of a C variable read from the input file */
627 void storecvar(M_NOPAR)
628   {
629     CVARSTRUCT *new;
630
631     new = (CVARSTRUCT *) m_malloc(sizeof(CVARSTRUCT), "C variable");
632     new->cvarptr = (M_WCHAR *) m_malloc(w_strlen(name) + 1,
633                                      "C variable name");
634     w_strcpy(new->cvarptr, name);
635     new->next = cvarlist;
636     cvarlist = new;
637     }
638
639 /* Compares the parameter name associated with a C variable in the input
640    file with the names of all parameters of the current element.  Stores
641    result for later output with code segments */
642 void storepname(M_NOPAR)
643   {
644     int i, par;
645
646     for (i = 0, par = m_element[openelt - 1].parptr;
647          i < m_element[openelt - 1].parcount;
648          i++, par++)
649       if (! w_strcmp(&m_pname[m_parameter[par - 1].paramname], name))
650           break;
651     if (i >= m_element[openelt - 1].parcount) {
652       m_err2("%s: No such parameter for element %s", name,
653         &m_ename[m_element[openelt - 1].enptr]);
654       return;
655       }
656     cvarlist->param = i;
657     }
658
659 /* Called when a possible parameter value to be defined is encountered */
660 void value(p)
661 M_WCHAR *p;
662 {
663 char buffer[5];
664
665 if (m_partype(cvarlist->param + m_element[openelt - 1].parptr, p))
666     {
667     if (pval->line)
668         {
669         if (w_strcmp(pval->value, p))
670             {
671             M_WCHAR *w_buffer;
672
673             sprintf(buffer, "%d", pval->line);
674             w_buffer = MakeWideCharString(buffer);
675             m_err5("Can't #define %s to %s. %s #define'd to %s on line %s",
676                    pval->cname,
677                    p,
678                    pval->cname,
679                    pval->value,
680                    w_buffer);
681             m_free(w_buffer, "wide character string");
682             }
683         }
684     else {
685       pval->value = (M_WCHAR *) m_malloc(w_strlen(p) + 1, "pval value");
686       w_strcpy(pval->value, p);
687       pval->line = m_line;
688       }
689     }
690 else m_err3("\"%s\" illegal value for parameter %s of %s",
691             p,
692             &m_pname[m_parameter[cvarlist->param +
693                        m_element[openelt - 1].parptr - 1].paramname],
694             &m_ename[m_element[openelt-1].enptr]);
695 }
696
697 #include "paramu.c"