OpenIndiana and Solaris port
[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 <stdlib.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 = NULL ;
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     return(FALSE);
204 }
205
206 /* Normalize parameter default.  Change tabs and RE's to spaces, capitalize
207    all letters (unless type is CDATA), remove extra space in lists */
208 #if defined(M_PROTO)
209 void normdefault(M_WCHAR *string )
210 #else
211 void normdefault(string)
212 M_WCHAR *string ;
213 #endif /* M_PROTO */
214 {
215 M_WCHAR *p, *q ;
216 int i, ret ;
217
218 switch (newpar->type)
219     {
220     case IDREF:
221     case NAMETYPE:
222     case NMTOKEN:
223     case NUTOKEN:
224     case ENTATT:
225       for ( ; *string ; string++)
226           *string = m_ctupper(*string) ;
227       return ;
228     case IDREFS:
229     case NAMES:
230     case NMTOKENS:
231     case NUTOKENS:
232     case NUMBERS:
233       /* Remove leading spaces */
234       for (p = string; *p ; p++)
235           if (! m_whitespace(*p)) break ;
236       w_strcpy(string, p) ;
237
238       /* Capitalize and normalize white space */
239       for (p = string, i = 0 ; *p ; p++, i++)
240           if (m_whitespace(*p))
241               {
242               ret = mbtowc(p, " ", 1);
243               for (q = p + 1 ; m_whitespace(*q); q++) ;
244               w_strcpy(p + 1, q) ;
245               }
246           else
247               *p = m_ctupper(*p) ;
248
249       if (i && m_whitespace(string[i - 1])) string[i - 1] = M_EOS ;
250       return ;
251
252     default:
253       for ( ; *string ; string++)
254           {
255           char mbyte[32]; /* bigger than the biggest multibyte char */
256           int  length;
257
258           length = wctomb(mbyte, *string);
259           if (length < 0)
260               {
261               m_error("Invalid wide character seen");
262               mbyte[0] = ' ';
263               mbyte[1] = 0;
264               }
265           if ((length == 1) && (*mbyte == '\n' || *mbyte == '\t'))
266               {
267               ret = mbtowc(string, " ", 1);
268               }
269           }
270     }
271     (void) ret;
272     return;
273 }
274
275 /* Called at end of parameter attribute list rule */
276 void prulend(M_NOPAR)
277 {
278 LHS *lhsp ;
279 LHS *discard ;
280
281 if (pcount > maxpar) maxpar = pcount ;
282 for (lhsp = lhs ; lhsp ; )
283     {
284     if (lhsp->elt->parptr)
285       m_err1(
286         "Program error: prulend for %s, element with predefined parameters",
287         lhsp->elt->enptr) ;
288     lhsp->elt->parptr = plist ;
289     lhsp->elt->paramcount = pcount ;
290     lhsp->elt->parindex = parcount - pcount + 1 ;
291     discard = lhsp ;
292     lhsp = lhsp->next ;
293     m_free((M_POINTER) discard, "lhs") ;
294     }
295 ruleinit() ;
296 }
297
298 /* Make string the default for the current parameter of the current element */
299 #if defined(M_PROTO)
300 void setdefault(const M_WCHAR *string)
301 #else
302 void setdefault()
303 M_WCHAR *string;
304 #endif /* M_PROTO */
305 {
306 PTYPE *kw ;
307 int keycount ;
308 int length ;
309
310 /* Process default for non-keyword parameter*/
311 if (newpar->type != GRPO)
312     {
313     /* First check it is a legitimate value */
314     if (! checkdefault(string))
315         {
316         m_err2("\"%s\": Not a valid default value for parameter %s",
317                string,
318                newpar->paramname) ;
319         return ;
320         }
321
322     length = w_strlen(string) + 1 ;
323     newpar->defstring = (M_WCHAR *) m_malloc(length, "default") ;
324     w_strcpy(newpar->defstring, string) ;
325     deflen += length ;
326
327     /* Value is valid.  Change tabs and RE's to spaces, if value is not
328        CDATA, put it in all caps, remove extra white space. */
329     normdefault(newpar->defstring) ;
330     }
331 else
332     {
333     /* It is a keyword parameter, store a pointer to the value */
334     for (kw = newpar->ptypep ; kw ; kw = kw->nextptr)
335         {
336         if (! m_wcupstrcmp(string, kw->keyword))
337             {
338             for (keycount = 0 ; kw ; kw = kw->nextptr)
339               keycount += w_strlen(kw->keyword) + 1 ;
340             newpar->defval = kwlen - keycount + 1;
341             return ;
342             }
343         }
344     m_err2("Invalid default: %s not a valid value for %s",
345            string,
346            newpar->paramname) ;
347     }
348 }