Sun agreed to a change of the license for the RPC code to a BSD-like license.
[platform/upstream/glibc.git] / sunrpc / rpc_util.c
1 /*
2  * From: @(#)rpc_util.c 1.11 89/02/22 (C) 1987 SMI
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
8  *     * Redistributions of source code must retain the above copyright
9  *       notice, this list of conditions and the following disclaimer.
10  *     * Redistributions in binary form must reproduce the above
11  *       copyright notice, this list of conditions and the following
12  *       disclaimer in the documentation and/or other materials
13  *       provided with the distribution.
14  *     * Neither the name of Sun Microsystems, Inc. nor the names of its
15  *       contributors may be used to endorse or promote products derived
16  *       from this software without specific prior written permission.
17  *
18  *   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19  *   "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20  *   LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
21  *   FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
22  *   COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
23  *   INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24  *   DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
25  *   GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26  *   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27  *   WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
28  *   NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29  *   OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 /*
33  * rpc_util.c, Utility routines for the RPC protocol compiler
34  */
35 #include <stdio.h>
36 #include <ctype.h>
37 #include <string.h>
38 #include <unistd.h>
39 #include "rpc_scan.h"
40 #include "rpc_parse.h"
41 #include "rpc_util.h"
42 #include "proto.h"
43
44 #define ARGEXT "argument"
45
46 char curline[MAXLINESIZE];      /* current read line */
47 const char *where = curline;    /* current point in line */
48 int linenum = 0;                /* current line number */
49
50 const char *infilename;         /* input filename */
51
52 #define NFILES 7
53 const char *outfiles[NFILES];   /* output file names */
54 int nfiles;
55
56 FILE *fout;                     /* file pointer of current output */
57 FILE *fin;                      /* file pointer of current input */
58
59 list *defined;                  /* list of defined things */
60
61 static int findit (const definition * def, const char *type);
62 static const char *fixit (const char *type, const char *orig);
63 static int typedefed (const definition * def, const char *type);
64 static const char *toktostr (tok_kind kind);
65 static void printbuf (void);
66 static void printwhere (void);
67
68 /*
69  * Reinitialize the world
70  */
71 void
72 reinitialize (void)
73 {
74   memset (curline, 0, MAXLINESIZE);
75   where = curline;
76   linenum = 0;
77   defined = NULL;
78 }
79
80 /*
81  * string equality
82  */
83 int
84 streq (const char *a, const char *b)
85 {
86   return strcmp (a, b) == 0;
87 }
88
89 /*
90  * find a value in a list
91  */
92 definition *
93 findval (list *lst, const char *val,
94          int (*cmp) (const definition *, const char *))
95 {
96
97   for (; lst != NULL; lst = lst->next)
98     {
99       if (cmp (lst->val, val))
100         {
101           return lst->val;
102         }
103     }
104   return NULL;
105 }
106
107 /*
108  * store a value in a list
109  */
110 void
111 storeval (list **lstp, definition *val)
112 {
113   list **l;
114   list *lst;
115
116
117   for (l = lstp; *l != NULL; l = (list **) & (*l)->next);
118   lst = ALLOC (list);
119   lst->val = val;
120   lst->next = NULL;
121   *l = lst;
122 }
123
124 static int
125 findit (const definition * def, const char *type)
126 {
127   return streq (def->def_name, type);
128 }
129
130 static const char *
131 fixit (const char *type, const char *orig)
132 {
133   definition *def;
134
135   def = findval (defined, type, findit);
136   if (def == NULL || def->def_kind != DEF_TYPEDEF)
137     {
138       return orig;
139     }
140   switch (def->def.ty.rel)
141     {
142     case REL_VECTOR:
143       if (streq (def->def.ty.old_type, "opaque"))
144         return ("char");
145       else
146         return (def->def.ty.old_type);
147     case REL_ALIAS:
148       return (fixit (def->def.ty.old_type, orig));
149     default:
150       return orig;
151     }
152 }
153
154 const char *
155 fixtype (const char *type)
156 {
157   return fixit (type, type);
158 }
159
160 const char *
161 stringfix (const char *type)
162 {
163   if (streq (type, "string"))
164     {
165       return "wrapstring";
166     }
167   else
168     {
169       return type;
170     }
171 }
172
173 void
174 ptype (const char *prefix, const char *type, int follow)
175 {
176   if (prefix != NULL)
177     {
178       if (streq (prefix, "enum"))
179         {
180           f_print (fout, "enum ");
181         }
182       else
183         {
184           f_print (fout, "struct ");
185         }
186     }
187   if (streq (type, "bool"))
188     {
189       f_print (fout, "bool_t ");
190     }
191   else if (streq (type, "string"))
192     {
193       f_print (fout, "char *");
194     }
195   else
196     {
197       f_print (fout, "%s ", follow ? fixtype (type) : type);
198     }
199 }
200
201 static int
202 typedefed (const definition * def, const char *type)
203 {
204   if (def->def_kind != DEF_TYPEDEF || def->def.ty.old_prefix != NULL)
205     {
206       return 0;
207     }
208   else
209     {
210       return streq (def->def_name, type);
211     }
212 }
213
214 int
215 isvectordef (const char *type, relation rel)
216 {
217   definition *def;
218
219   for (;;)
220     {
221       switch (rel)
222         {
223         case REL_VECTOR:
224           return !streq (type, "string");
225         case REL_ARRAY:
226           return 0;
227         case REL_POINTER:
228           return 0;
229         case REL_ALIAS:
230           def = findval (defined, type, typedefed);
231           if (def == NULL)
232             {
233               return 0;
234             }
235           type = def->def.ty.old_type;
236           rel = def->def.ty.rel;
237         }
238     }
239 }
240
241 char *
242 locase (const char *str)
243 {
244   char c;
245   static char buf[100];
246   char *p = buf;
247
248   while ((c = *str++) != 0)
249     {
250       *p++ = (c >= 'A' && c <= 'Z') ? (c - 'A' + 'a') : c;
251     }
252   *p = 0;
253   return buf;
254 }
255
256 void
257 pvname_svc (const char *pname, const char *vnum)
258 {
259   f_print (fout, "%s_%s_svc", locase (pname), vnum);
260 }
261
262 void
263 pvname (const char *pname, const char *vnum)
264 {
265   f_print (fout, "%s_%s", locase (pname), vnum);
266 }
267
268 /*
269  * print a useful (?) error message, and then die
270  */
271 void
272 error (const char *msg)
273 {
274   printwhere ();
275   f_print (stderr, "%s, line %d: ", infilename, linenum);
276   f_print (stderr, "%s\n", msg);
277   crash ();
278 }
279
280 /*
281  * Something went wrong, unlink any files that we may have created and then
282  * die.
283  */
284 void
285 crash (void)
286 {
287   int i;
288
289   for (i = 0; i < nfiles; i++)
290     {
291       unlink (outfiles[i]);
292     }
293   exit (1);
294 }
295
296 void
297 record_open (const char *file)
298 {
299   if (nfiles < NFILES)
300     {
301       outfiles[nfiles++] = file;
302     }
303   else
304     {
305       f_print (stderr, "too many files!\n");
306       crash ();
307     }
308 }
309
310 static char expectbuf[100];
311
312 /*
313  * error, token encountered was not the expected one
314  */
315 void
316 expected1 (tok_kind exp1)
317 {
318   s_print (expectbuf, "expected '%s'",
319            toktostr (exp1));
320   error (expectbuf);
321 }
322
323 /*
324  * error, token encountered was not one of two expected ones
325  */
326 void
327 expected2 (tok_kind exp1, tok_kind exp2)
328 {
329   s_print (expectbuf, "expected '%s' or '%s'",
330            toktostr (exp1),
331            toktostr (exp2));
332   error (expectbuf);
333 }
334
335 /*
336  * error, token encountered was not one of 3 expected ones
337  */
338 void
339 expected3 (tok_kind exp1, tok_kind exp2, tok_kind exp3)
340 {
341   s_print (expectbuf, "expected '%s', '%s' or '%s'",
342            toktostr (exp1),
343            toktostr (exp2),
344            toktostr (exp3));
345   error (expectbuf);
346 }
347
348 void
349 tabify (FILE * f, int tab)
350 {
351   while (tab--)
352     {
353       (void) fputc ('\t', f);
354     }
355 }
356
357
358 static const token tokstrings[] =
359 {
360   {TOK_IDENT, "identifier"},
361   {TOK_CONST, "const"},
362   {TOK_RPAREN, ")"},
363   {TOK_LPAREN, "("},
364   {TOK_RBRACE, "}"},
365   {TOK_LBRACE, "{"},
366   {TOK_LBRACKET, "["},
367   {TOK_RBRACKET, "]"},
368   {TOK_STAR, "*"},
369   {TOK_COMMA, ","},
370   {TOK_EQUAL, "="},
371   {TOK_COLON, ":"},
372   {TOK_SEMICOLON, ";"},
373   {TOK_UNION, "union"},
374   {TOK_STRUCT, "struct"},
375   {TOK_SWITCH, "switch"},
376   {TOK_CASE, "case"},
377   {TOK_DEFAULT, "default"},
378   {TOK_ENUM, "enum"},
379   {TOK_TYPEDEF, "typedef"},
380   {TOK_INT, "int"},
381   {TOK_SHORT, "short"},
382   {TOK_LONG, "long"},
383   {TOK_UNSIGNED, "unsigned"},
384   {TOK_DOUBLE, "double"},
385   {TOK_FLOAT, "float"},
386   {TOK_CHAR, "char"},
387   {TOK_STRING, "string"},
388   {TOK_OPAQUE, "opaque"},
389   {TOK_BOOL, "bool"},
390   {TOK_VOID, "void"},
391   {TOK_PROGRAM, "program"},
392   {TOK_VERSION, "version"},
393   {TOK_EOF, "??????"}
394 };
395
396 static const char *
397 toktostr (tok_kind kind)
398 {
399   const token *sp;
400
401   for (sp = tokstrings; sp->kind != TOK_EOF && sp->kind != kind; sp++);
402   return sp->str;
403 }
404
405 static void
406 printbuf (void)
407 {
408   char c;
409   int i;
410   int cnt;
411
412 #define TABSIZE 4
413
414   for (i = 0; (c = curline[i]) != 0; i++)
415     {
416       if (c == '\t')
417         {
418           cnt = 8 - (i % TABSIZE);
419           c = ' ';
420         }
421       else
422         {
423           cnt = 1;
424         }
425       while (cnt--)
426         {
427           (void) fputc (c, stderr);
428         }
429     }
430 }
431
432 static void
433 printwhere (void)
434 {
435   int i;
436   char c;
437   int cnt;
438
439   printbuf ();
440   for (i = 0; i < where - curline; i++)
441     {
442       c = curline[i];
443       if (c == '\t')
444         {
445           cnt = 8 - (i % TABSIZE);
446         }
447       else
448         {
449           cnt = 1;
450         }
451       while (cnt--)
452         {
453           (void) fputc ('^', stderr);
454         }
455     }
456   (void) fputc ('\n', stderr);
457 }
458
459 char *
460 make_argname (const char *pname, const char *vname)
461 {
462   char *name;
463
464   name = malloc (strlen (pname) + strlen (vname) + strlen (ARGEXT) + 3);
465   if (!name)
466     {
467       fprintf (stderr, "failed in malloc");
468       exit (1);
469     }
470   sprintf (name, "%s_%s_%s", locase (pname), vname, ARGEXT);
471   return name;
472 }
473
474 bas_type *typ_list_h;
475 bas_type *typ_list_t;
476
477 void
478 add_type (int len, const char *type)
479 {
480   bas_type *ptr;
481
482
483   if ((ptr = malloc (sizeof (bas_type))) == NULL)
484     {
485       fprintf (stderr, "failed in malloc");
486       exit (1);
487     }
488
489   ptr->name = type;
490   ptr->length = len;
491   ptr->next = NULL;
492   if (typ_list_t == NULL)
493     {
494
495       typ_list_t = ptr;
496       typ_list_h = ptr;
497     }
498   else
499     {
500
501       typ_list_t->next = ptr;
502       typ_list_t = ptr;
503     }
504
505 }
506
507
508 bas_type *
509 find_type (const char *type)
510 {
511   bas_type *ptr;
512
513   ptr = typ_list_h;
514
515
516   while (ptr != NULL)
517     {
518       if (strcmp (ptr->name, type) == 0)
519         return ptr;
520       else
521         ptr = ptr->next;
522     };
523   return NULL;
524 }