Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / programs / dthelp / parser / pass2 / build / param.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: param.c /main/3 1995/11/08 10:43:22 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 /* Param.c contains procedures related to parameters for program BUILD */
31
32 #include <malloc.h>
33 #include <string.h>
34 #include "build.h"
35 #include "context.h"
36 #include "delim.h"
37
38 /* Add a keyword to the list of possible values of a keyword parameter for
39    the current element
40 */
41 void addkeyword(M_NOPAR)
42 {
43 int length ;
44 PARAMETER *par ;
45 PTYPE *kw ;
46
47 /* Check if duplicate keyword for this parameter */
48 for (kw = newpar->ptypep ; kw ; kw = kw->nextptr)
49     if (w_strcmp(kw->keyword, name) == 0)
50         {
51         warning3("Warning: Repeated keyword %s in parameter %s of %s",
52                  name,
53                  newpar->paramname,
54                  thisrule) ;
55         return ;
56         }
57
58 /* Check if duplicate keyword within parameters of this element */
59 for (par = plist ; par != newpar ; par = par->next)
60     for (kw = par->ptypep ; kw ; kw = kw->nextptr)
61         {
62         if (w_strcmp(kw->keyword, name) == 0)
63             warning4("Keyword %s used in parameters %s and %s of %s",
64                      name,
65                      par->paramname,
66                      newpar->paramname,
67                      thisrule) ;
68         if (! kw->next) break ;
69         }
70    
71 *nextptype = (PTYPE *) m_malloc(sizeof(PTYPE), "ptype") ;
72 if (newpar->kwlist) thisptype->next = ptypelen + 1 ;
73 else
74     {
75     newpar->kwlist = ptypelen + 1 ;
76     newpar->ptypep = *nextptype ;
77     }
78 thisptype = *nextptype ;
79 thisptype->next = M_NULLVAL ;
80 thisptype->nextptr = NULL ;
81 nextptype = &(thisptype->nextptr) ;
82 length = w_strlen(name) + 1 ;
83 thisptype->keyword = (M_WCHAR *) m_malloc(length, "keyword") ;
84 w_strcpy(thisptype->keyword, name) ;
85 kwlen += length ;
86 ptypelen++ ;
87 }
88
89 /* Add a parameter to the current element */
90 void addpar(M_NOPAR)
91 {
92 PARAMETER *paramp, *last ;
93 int length ;
94
95 parcount++ ;
96 pcount++ ;
97 for (paramp = plist ; paramp ; paramp = paramp->next)
98     {
99     if (w_strcmp(name, paramp->paramname) == 0)
100     warning2("Multiple definition of parameter %s for element %s",
101              name,
102              thisrule) ;
103     last = paramp ;
104     }
105 newpar = (PARAMETER *) m_malloc(sizeof(PARAMETER), "parameter") ;
106 if (! plist)
107     plist = newpar ;
108 else
109     last->next = newpar ;
110 *nextpar = newpar ;
111 nextpar = &newpar->nextptr ;
112 *nextpar = NULL ;
113 newpar->next = NULL ;
114 newpar->deftype = NULLDEF ;
115 newpar->defval = M_NULLVAL ;
116 newpar->defstring = NULL ;
117 newpar->kwlist = M_NULLVAL ;
118 length = w_strlen(name) + 1 ;
119 pnamelen += length ;
120 newpar->paramname = (M_WCHAR *) m_malloc(length, "parameter name") ;
121 w_strcpy(newpar->paramname, name) ;
122 newpar->ptypep = NULL ;
123 }
124
125
126 /* Check that specified default value is legal parameter value */
127 #if defined(M_PROTO)
128 LOGICAL checkdefault( const M_WCHAR *string )
129 #else
130 LOGICAL checkdefault(string)
131 M_WCHAR *string ;
132 #endif /* M_PROTO */
133 {
134 const M_WCHAR *p ;
135 int len ;
136 LOGICAL first ;
137
138 if (newpar->type == CDATA) return(TRUE) ;
139 if (m_allwhite(string)) return(FALSE) ;
140
141 first = TRUE ;
142 switch (newpar->type)
143     {
144     case IDREF:
145     case NAMETYPE:
146     case ENTATT:
147     case NMTOKEN:
148     case NUMBER:
149     case NUTOKEN:
150     /* Check length of default */
151     if (w_strlen(string) > M_NAMELEN) return(FALSE) ;
152
153     for (p = string ; *p ; p++)
154         {
155         if (m_cttype(*p) == M_NONNAME) return(FALSE) ;
156         else if (first || newpar->type == NUMBER)
157         switch (newpar->type)
158             {
159             case IDREF:
160             case NAMETYPE:
161             case ENTATT:
162               if (m_cttype(*p) != M_NMSTART) return(FALSE) ;
163               break ;
164             case NUMBER:
165             case NUTOKEN:
166               if (m_cttype(*p) != M_DIGIT) return(FALSE) ;
167               break ;
168             }
169         first = FALSE ;
170         }
171     return(TRUE) ;
172     case IDREFS:
173     case NAMES:
174     case NMTOKENS:
175     case NUMBERS:
176     case NUTOKENS:
177     len = 1 ;
178     for (p = string ; *p ; p++)
179         {
180         if (m_cttype(*p) == M_NONNAME)
181             {
182             if (! m_whitespace(*p)) return(FALSE) ;
183             len = 1 ;
184             }
185         else if (len == 1) 
186           switch (newpar->type)
187               {
188               case IDREFS:
189               case NAMES:
190                 if (m_cttype(*p) != M_NMSTART) return(FALSE) ;
191                 break ;
192               case NUMBERS:
193               case NUTOKENS:
194                 if (m_cttype(*p) != M_DIGIT) return(FALSE) ;
195                 break ;
196               }
197         else if (newpar->type == NUMBERS && 
198                  m_cttype(*p) != M_DIGIT) return(FALSE) ;
199         if (len++ > M_NAMELEN) return(FALSE) ;
200         }
201     break ;
202     }
203 }
204
205 /* Normalize parameter default.  Change tabs and RE's to spaces, capitalize
206    all letters (unless type is CDATA), remove extra space in lists */
207 #if defined(M_PROTO)
208 void normdefault(M_WCHAR *string )
209 #else
210 void normdefault(string)
211 M_WCHAR *string ;
212 #endif /* M_PROTO */
213 {
214 M_WCHAR *p, *q ;
215 int i ;
216
217 switch (newpar->type)
218     {
219     case IDREF:
220     case NAMETYPE:
221     case NMTOKEN:
222     case NUTOKEN:
223     case ENTATT:
224       for ( ; *string ; string++)
225           *string = m_ctupper(*string) ;
226       return ;
227     case IDREFS:
228     case NAMES:
229     case NMTOKENS:
230     case NUTOKENS:
231     case NUMBERS:
232       /* Remove leading spaces */
233       for (p = string; *p ; p++)
234           if (! m_whitespace(*p)) break ;
235       w_strcpy(string, p) ;
236
237       /* Capitalize and normalize white space */
238       for (p = string, i = 0 ; *p ; p++, i++)
239           if (m_whitespace(*p))
240               {
241               mbtowc(p, " ", 1);
242               for (q = p + 1 ; m_whitespace(*q); q++) ;
243               w_strcpy(p + 1, q) ;
244               }
245           else
246               *p = m_ctupper(*p) ;
247
248       if (i && m_whitespace(string[i - 1])) string[i - 1] = M_EOS ;
249       return ;
250
251     default:
252       for ( ; *string ; string++)
253           {
254           char mbyte[32]; /* bigger than the biggest multibyte char */
255           int  length;
256
257           length = wctomb(mbyte, *string);
258           if (length < 0)
259               {
260               m_error("Invalid wide character seen");
261               mbyte[0] = ' ';
262               mbyte[1] = 0;
263               }
264           if ((length == 1) && (*mbyte == '\n' || *mbyte == '\t'))
265             mbtowc(string, " ", 1);
266           }
267       return ;
268     }
269 }
270
271 /* Called at end of parameter attribute list rule */
272 void prulend(M_NOPAR)
273 {
274 LHS *lhsp ;
275 LHS *discard ;
276
277 if (pcount > maxpar) maxpar = pcount ;
278 for (lhsp = lhs ; lhsp ; )
279     {
280     if (lhsp->elt->parptr)
281       m_err1(
282         "Program error: prulend for %s, element with predefined parameters",
283         lhsp->elt->enptr) ;
284     lhsp->elt->parptr = plist ;
285     lhsp->elt->paramcount = pcount ;
286     lhsp->elt->parindex = parcount - pcount + 1 ;
287     discard = lhsp ;
288     lhsp = lhsp->next ;
289     m_free((M_POINTER) discard, "lhs") ;
290     }
291 ruleinit() ;
292 }
293
294 /* Make string the default for the current parameter of the current element */
295 #if defined(M_PROTO)
296 void setdefault(const M_WCHAR *string)
297 #else
298 void setdefault()
299 M_WCHAR *string;
300 #endif /* M_PROTO */
301 {
302 PTYPE *kw ;
303 int keycount ;
304 int length ;
305
306 /* Process default for non-keyword parameter*/
307 if (newpar->type != GRPO)
308     {
309     /* First check it is a legitimate value */
310     if (! checkdefault(string))
311         {
312         m_err2("\"%s\": Not a valid default value for parameter %s",
313                string,
314                newpar->paramname) ;
315         return ;
316         }
317
318     length = w_strlen(string) + 1 ;
319     newpar->defstring = (M_WCHAR *) m_malloc(length, "default") ;
320     w_strcpy(newpar->defstring, string) ;
321     deflen += length ;
322
323     /* Value is valid.  Change tabs and RE's to spaces, if value is not
324        CDATA, put it in all caps, remove extra white space. */
325     normdefault(newpar->defstring) ;
326     }
327 else
328     {
329     /* It is a keyword parameter, store a pointer to the value */
330     for (kw = newpar->ptypep ; kw ; kw = kw->nextptr)
331         {
332         if (! m_wcupstrcmp(string, kw->keyword))
333             {
334             for (keycount = 0 ; kw ; kw = kw->nextptr)
335               keycount += w_strlen(kw->keyword) + 1 ;
336             newpar->defval = kwlen - keycount + 1;
337             return ;
338             }
339         }
340     m_err2("Invalid default: %s not a valid value for %s",
341            string,
342            newpar->paramname) ;
343     }
344 }