Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dthelp / parser / canon1 / parser / actutil.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: actutil.c /main/3 1995/11/08 09:34:00 rswiston $ */
24 /*
25               Copyright 1986 Tandem Computers Incorporated.
26 This product and information is proprietary of Tandem Computers Incorporated.
27                    Copyright 1986, 1987, 1988, 1989 Hewlett-Packard Co.
28 */
29
30 /* Actutil.c contains utility procedures for processing actions specified
31 in the interface definition.*/
32
33 #include <stdio.h>
34 #include <malloc.h>
35 #if defined(MSDOS)
36 #include <process.h>
37 #endif
38 #include <string.h>
39 #include "basic.h"
40 #include "trie.h"
41 #include "dtdext.h"
42 #include "parser.h"
43 #define M_IFDEF
44 #include "if.h"
45 #include "delim.h"
46 #include "context.h"
47 #include "signon.h"
48
49 /* When an explicit or implied end-tag occurs */
50 void m_endaction(m_elt)
51   M_ELEMENT m_elt;
52   {
53     M_ELEMENT m_action;
54     char buffer[2*MAXD+M_NAMELEN+1];
55
56     if (m_tagtrace) {
57       if (m_element[m_elt - 1].content != M_NONE) {
58         if (m_toptstat == M_OTHER) {
59           strcpy(buffer, "\n");
60           m_trace(buffer);
61           }
62         sprintf(buffer,
63                 "%s%s%s",
64                 m_etago,
65                 m_nameofelt(m_elt),
66                 m_tagc);
67         m_trace(buffer);
68         }
69       m_toptstat = M_OTHER;
70       }
71     if (m_action = m_findact(m_elt, m_ecarray)) {
72       m_stackpar = m_stacktop;
73       m_endcase(m_action);
74       }
75     if (m_action = m_findact(m_elt, m_etarray)) {
76       m_stackpar = m_stacktop->stparam;
77       m_textout(&m_string[m_action - 1], FALSE, TRUE);
78       }
79     }
80
81 /* Find appropriate action according to current stack */
82 int m_findact(elt, array)
83   M_ELEMENT elt;
84   int *array;
85   {
86     int chainlen = 0;
87     int index;
88
89     if (! array[elt - 1]) return(FALSE);
90     if (m_stacktop->element != elt) {
91       m_error("Program error in findact");
92       m_exit(TRUE);
93       }
94     /* There is an action for this element with no context specification */
95     if (m_action[array[elt - 1] - 1].data) {
96       chainlen = 1;
97       index = array[elt - 1];
98       }
99     /* Only actions for this element have context specified */
100     else {
101       chainlen = 0;
102       index = 0;
103       }
104     m_findchain(m_stacktop->oldtop, array[elt - 1], chainlen, &chainlen,
105                 &index, FALSE);
106     return(index ? m_action[index - 1].data : FALSE);
107     }
108
109 /* Recursive procedure called by findact() to search m_action */
110 #if defined(M_PROTO)
111 void m_findchain(M_PARSE *stackptr, int start, int chainin, int *chainout, int *index, LOGICAL wild)
112 #else
113 void m_findchain(stackptr, start, chainin, chainout, index, wild)
114   M_PARSE *stackptr;
115   int start;
116   int chainin;
117   int *chainout;
118   int *index;
119   LOGICAL wild;
120 #endif
121 {
122     int node;
123     M_PARSE *stackp;
124
125     for (node = m_action[start - 1].son ; node;
126          node = m_action[node - 1].next) {
127       if (m_action[node - 1].element == 1) 
128         m_findchain(stackptr, node, chainin, chainout, index, TRUE);
129       else for (stackp = stackptr;
130                 stackp->oldtop;
131                 stackp = stackp->oldtop) {
132         if (stackp->element == m_action[node - 1].element - 1) {
133           if (m_action[node - 1].data) 
134             if (chainin + 1 > *chainout ||
135                 (chainin + 1 == *chainout && node < *index)) {
136               *chainout = chainin + 1;
137               *index = node;
138               }
139           m_findchain(stackp->oldtop, node, chainin + 1, chainout,
140                       index, FALSE);
141           }
142         if (! wild) break;
143         }
144       }
145     }
146
147 /* Process global end string.  In separate procedure to keep all references
148    to if.h in one source file and minimize recompilation if interface
149    changes. */
150 void m_globes(M_NOPAR)
151 {
152 M_WCHAR *wc_string;
153
154 wc_string = MakeWideCharString(&m_string[m_ges]);
155 if (m_ges) m_stcaction(wc_string, FALSE, TRUE);
156 m_free(wc_string,"wide character string");
157 }    
158
159 /* Process global start string.  In separate procedure to keep all references
160    to if.h in one source file and minimize recompilation if interface
161    changes. */
162 void m_globss(M_NOPAR)
163 {
164 M_WCHAR *wc_string;
165
166 wc_string = MakeWideCharString(&m_string[m_gss]);
167 if (m_gss) m_stcaction(wc_string, TRUE, FALSE);
168 m_free(wc_string,"wide character string");
169 }    
170
171 /* When an explicit or implied start-tag occurs */
172 void m_strtaction(m_elt)
173   M_ELEMENT m_elt;
174   {
175     int m_par, m_i;
176     M_WCHAR *m_p;
177     M_ELEMENT m_action;
178     static char newpar[] = "\n   ";
179     static char quote[] = " = \"";
180     char buffer[M_NAMELEN + 1 +
181       (sizeof(quote) + sizeof(newpar) - 2 > MAXD ?
182          sizeof(quote) + sizeof(newpar) - 2 : 
183          MAXD)
184       ];
185
186     m_start = TRUE;
187     m_getline(&m_stacktop->file, &m_stacktop->line);
188     if (m_tagtrace) {
189       sprintf(buffer, "%s%s", m_stago, m_nameofelt(m_elt));
190       m_trace(buffer);
191       for (m_i = 0, m_par = m_element[m_elt - 1].parptr;
192            m_i < m_element[m_elt - 1].parcount;
193            m_i++, m_par++)
194         if (m_stacktop->param[m_i]) {
195           sprintf(buffer, "%s%s%s",
196                   newpar, &m_pname[m_parameter[m_par - 1].paramname], quote);
197           m_trace(buffer);
198           buffer[1] = M_EOS;
199           for (m_p = m_stacktop->param[m_i] ; *m_p ; m_p++)
200             if (*m_p != '"') {
201               buffer[0] = *m_p;
202               m_trace(buffer);
203               }
204             else {
205               sprintf(buffer, "%s%d", m_cro, '"');
206               m_trace(buffer);
207               buffer[1] = M_EOS;
208               }
209           buffer[0] = '"';
210           m_trace(buffer);
211           }
212       if (m_element[m_elt - 1].parcount) {
213         buffer[0] = '\n';
214         buffer[1] = M_EOS;
215         m_trace(buffer);
216         }
217       sprintf(buffer, "%s\n", m_tagc);
218       m_trace(buffer);
219       m_toptstat = M_TOPTSTARTTAG;
220       }
221     if (m_action = m_findact(m_elt, m_scarray)) {
222       m_stackpar = m_stacktop;
223       m_strtcase(m_action);
224       }
225     if (m_action = m_findact(m_elt, m_stcarray)) {
226       m_stacktop->stccase = m_action;
227       m_stacktop->stparam = m_stacktop;
228       }
229     if (m_action = m_findact(m_elt, m_starray)) {
230       m_stackpar = m_stacktop->stparam;
231       m_textout(&m_string[m_action - 1], TRUE, FALSE);
232       }
233     if (m_action = m_findact(m_elt, m_tcarray)) {
234       m_stacktop->cdcase = m_action;
235       m_stacktop->cdparam = m_stacktop;
236       }
237     if (m_action = m_findact(m_elt, m_pcarray)) {
238       m_stacktop->picase = m_action;
239       m_stacktop->piparam = m_stacktop;
240       }
241     }
242
243 /* Output a start-string or end-string */
244 #if defined(M_PROTO)
245 void m_textout(char *format, LOGICAL start, LOGICAL end)
246 #else
247 void m_textout(format, start, end)
248   char *format;
249   LOGICAL start;
250   LOGICAL end;
251 #endif
252 {
253 M_WCHAR name[M_NAMELEN + 1];
254 int i, par;
255 LOGICAL found;
256 M_WCHAR *string;
257 M_WCHAR *p;
258 M_WCHAR *q;
259 M_WCHAR *r;
260 M_WCHAR *s;
261 M_WCHAR *new;
262 int stringlen;
263 int changelen;
264 int unused;
265
266 stringlen = strlen(format) + 1;
267 unused = 0;
268 string = (M_WCHAR *) m_malloc(stringlen, "string space");
269 for (p = string ; *format ; )
270     {
271     if (*format == M_ESCAPECHAR)
272         {
273         for (i = 0, format++ ; i < M_NAMELEN ; i++, format++)
274             {
275             mbtowc(&name[i], format, 1);
276             if (m_cttype(name[i]) == M_NONNAME ||
277                 (m_cttype(name[i]) != M_NMSTART && i == 0)
278                ) break;
279             }
280         if (! i)
281             {
282             char mb;
283
284             mb = M_ESCAPECHAR;
285             mbtowc(p, &mb, 1);
286             p++;
287             /* Double escape character used to insert a single escape character
288                in the output string */
289             if (*format == M_ESCAPECHAR) format++;
290             continue;
291             }
292         name[i] = M_EOS;
293         for (found = FALSE, i = 0,
294                  par = m_element[m_stacktop->element - 1].parptr;
295                  i < m_element[m_stacktop->element - 1].parcount;
296                  i++, par++)
297             if (! m_wcupstrcmp(&m_pname[m_parameter[par - 1].paramname], name))
298                 {
299                 q = m_stacktop->param[i];
300                 if (! q)
301                     {
302                     found = TRUE;
303                     unused += w_strlen(name) + 1;
304                     break;
305                     }
306                 changelen = w_strlen(q) - w_strlen(name) - 1 - unused;
307                 if (changelen > 0)
308                     {
309                     new = (M_WCHAR *) m_malloc(stringlen + changelen,
310                                                "string space");
311                     for (r = string, s = new ; r < p ; ) *s++ = *r++;
312                     m_free(string, "string space");
313                     string = new;
314                     stringlen = stringlen + changelen;
315                     p = s;
316                     unused = 0;
317                     }
318                 else if (changelen < 0) unused = -changelen;
319                 found = TRUE;
320                 break;
321                 }
322         if (! found)
323             {
324             char mb;
325
326             mb = M_ESCAPECHAR;
327             mbtowc(p, &mb, 1);
328             p++;
329             q = name;
330             }
331         if (q) while (*q) *p++ = *q++;
332         }
333     else *p++ = *format++;
334     }
335 *p = M_EOS;
336 m_stcaction(string, start, end);
337 m_free(string, "string space");
338 }