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