reindent-20030715
[openafs.git] / src / rx / test / generator.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /*
11  * generator.c -- phase 2 of the generator.
12  *
13  * takes a file, which has a list of signature as input,
14  * and outputs the client, server, .xg, and makefiles
15  * This file is normally created by running tableGen.c,
16  * but theoretically could be generated by a human.
17  *
18  * Format of the signatures : no_of_args list_of_arg_signs
19  *  arg_sign : (dir type)
20  *
21  *
22  * This program is used to generate client/server pairs that
23  * make and verify random rpcs.  It can be used to generate
24  * both pthread and lwp versions of the client and server.
25  * It was designed to verify that the new pthread rx library
26  * was functioning correctly.
27  *
28  * The key to understanding how this program works is to realize
29  * that all the data necessary to generate the client/server
30  * code is generated first, in char string format.
31  * For example, if you are generating 10 rpc's, the input and
32  * output values of all the parameters are generated - and
33  * stored as strings.  This allows you to write out the values
34  * as the client and server are created without having to worry
35  * about data type conversion.
36  *
37  * In addition, these strings (along with other information) are
38  * stored in a structure that is iterated over many times during
39  * the construction of the client and server.
40  *
41  * Often this iteration takes the form of:
42  *     for (i=0; i < argsP->argCount; i++)
43  *
44  * It may be possible to eliminate some of these iterations for
45  * efficiency sake, but this was not done - allowing an easier
46  * implementation.
47  *
48  * The bulk of this code was lifted from the delight project.
49  *
50  */
51
52 #include <afsconfig.h>
53 #include <afs/param.h>
54
55 RCSID
56     ("$Header$");
57
58 #include <stdio.h>
59 #include <string.h>
60 #include <stdlib.h>
61 #include <limits.h>
62 #include <float.h>
63 #include <malloc.h>
64 #include <assert.h>
65 #include "generator.h"
66
67 static char *unix_symbols[] = {
68     "make -f",
69     "include ../../../config/Makefile.$(SYS_NAME)\n",
70     "o",
71     "$(CC) $(CFLAGS) -c",
72     "#include <netdb.h>\n",
73     "",
74
75 /* all one string */
76     "LIBS = $(DESTDIR)lib/libafsrpc.so \\\n"
77         "\t$(DESTDIR)lib/afs/libcmd.a \\\n"
78         "\t$(DESTDIR)lib/afs/libcom_err.a \\\n"
79         "\t$(DESTDIR)lib/afs/util.a \n",
80
81 /* all one string */
82     "LIBS = $(DESTDIR)lib/librxkad.a \\\n" "\t$(DESTDIR)lib/libdes.a \\\n"
83         "\t$(DESTDIR)lib/librx.a \\\n" "\t$(DESTDIR)lib/liblwp.a \\\n"
84         "\t$(DESTDIR)lib/afs/libcmd.a \\\n"
85         "\t$(DESTDIR)lib/afs/libcom_err.a \\\n"
86         "\t$(DESTDIR)lib/afs/util.a \\\n" "\t/usr/ucblib/libucb.a \n",
87
88 /* all one string */
89     "\t@if [ ! -r DEST ] ; \\\n" "\tthen \\\n"
90         "\t\techo \"Must create DEST link by hand before building tests\"; \\\n"
91         "\t\texit 1; \\\n" "\tfi\n"
92 };
93
94 static char *nt_symbols[] = {
95     "nmake /f",
96     "!INCLUDE ../../../config/NTMakefile.$(SYS_NAME)\n",
97     "obj",
98     "$(C2OBJ)",
99     "#include <windows.h>\n",
100     "all",
101
102 /* all one string */
103     "LIBS = $(DESTDIR)/lib/afsrpc.lib \\\n"
104         "\t$(DESTDIR)/lib/afs/afscmd.lib \\\n"
105         "\t$(DESTDIR)/lib/afs/afscom_err.lib \\\n"
106         "\t$(DESTDIR)/lib/afs/afsutil.lib \\\n"
107         "\t$(DESTDIR)/lib/pthread.lib \\\n" "\t$(DESTDIR)/lib/afsreg.lib \\\n"
108         "\t$(XLIBS)\n",
109
110 /* all one string */
111     "LIBS = $(DESTDIR)/lib/afsrxkad.lib \\\n"
112         "\t$(DESTDIR)/lib/afsdes.lib \\\n" "\t$(DESTDIR)/lib/afsrx.lib \\\n"
113         "\t$(DESTDIR)/lib/afslwp.lib \\\n"
114         "\t$(DESTDIR)/lib/afs/afscmd.lib \\\n"
115         "\t$(DESTDIR)/lib/afs/afscom_err.lib \\\n"
116         "\t$(DESTDIR)/lib/afs/afsutil.lib \\\n"
117         "\t$(DESTDIR)/lib/afsreg.lib \n",
118
119 /* all one string */
120     "!\tIF (!EXIST(DEST))\n"
121         "!\t\tERROR Must create DEST link by hand before building tests\n"
122         "!\tENDIF\n",
123 };
124
125 static char **platform = nt_symbols;
126
127 #if defined(WIN32)
128 #define strdup(x)               _strdup(x)
129 #endif /* WIN32 */
130
131 /*
132  * 31 bit random number generator, we don't really care how random
133  * these numbers are, it is more important that identical rx files
134  * are generated no matter what platform the generator runs on
135  */
136 static unsigned long randVal = 0x330E16;
137
138 typedef enum {
139     PTHREADS,
140     LWPS
141 } threadModel_t;
142
143 static threadModel_t threadModel = PTHREADS;
144
145 PRIVATE double
146 drand32(void)
147 {
148     randVal = ((randVal * 0xEECE66D) + 0xB) & 0xFFFFFFFF;
149     return ((double)(randVal) / 4294967296.0);
150 }
151
152 /*
153  * GetDescription writes a one line comment describing the parameters
154  * used in an rpc in the client program
155  */
156 PRIVATE char *
157 GetDescription(rpcArgs * argsP)
158 {
159     char *bufP2;
160     int i;
161
162     bufP2 =
163         (char *)calloc((MAX_TYP_STR + MAX_DIR_STR + ATTRIB_LEN * ATTRIB_NO)
164                        * argsP->argCount + 3, sizeof(char));
165     MEM_CHK(bufP2, "GetDescription: out of mem bufP2\n");
166
167     for (i = 0; i < argsP->argCount; i++) {
168         strcat(bufP2, argsP->argDescr[i].direction);
169         strcat(bufP2, argsP->argDescr[i].type);
170     }
171     return (bufP2);
172 }
173
174 /*
175  * GetName -- get the name of the current server/instance
176  */
177 PRIVATE char *
178 GetName(char *serverName, int sign_no)
179 {
180     /* itl file name 8.3 format */
181     char *bufP;
182
183     bufP = (char *)malloc(32 * sizeof(char));
184     MEM_CHK(bufP, "GetName: bufP out of mem\n");
185
186     sprintf(bufP, "%s%d", serverName, sign_no);
187     return bufP;
188 }
189
190 /*
191  * OpenOutFile -- open a file in the output directory
192  */
193 PRIVATE FILE *
194 OpenOutFile(char *outDir, char *fileName, char *tailStr)
195 {
196     char *bufP;
197     FILE *fP;
198
199     if (outDir) {
200         bufP =
201             (char *)malloc(sizeof(char) *
202                            (strlen(fileName) + strlen(tailStr) +
203                             strlen(outDir) + 2));
204         MEM_CHK(bufP, "OpenOutFile : Out of mem -- bufP\n");
205         sprintf(bufP, "%s/%s%s", outDir, fileName, tailStr);
206     } else {
207         bufP =
208             (char *)malloc(sizeof(char) *
209                            (strlen(fileName) + strlen(tailStr) + 1));
210         MEM_CHK(bufP, "OpenOutFile : Out of mem -- bufP\n");
211         sprintf(bufP, "%s%s", fileName, tailStr);
212     }
213     fP = fopen(bufP, "w");
214     MEM_CHK(fP, "main: Unable to open output file\n");
215     free(bufP);
216     return (fP);
217 }
218
219 /*
220  * WriteXGDecl -- write the declaration for a parameter
221  */
222 PRIVATE void
223 WriteXGDecl(arg_tuple * arg, FILE * xg_h, int i, int structFlag, int lastFlag)
224 {
225     if (structFlag) {
226         if (!strcmp(arg->type, "varString")) {
227             fprintf(xg_h, "\tchar a%d[STR_MAX];\n", i);
228         } else {
229             fprintf(xg_h, "\tdrpc_%s_t a%d;\n", arg->type, i);
230         }
231     } else {
232         if (!strncmp(arg->type, "ar_", 2)) {
233             fprintf(xg_h, "\t%s drpc_out_%s_t *a%d", arg->direction,
234                     arg->type, i);
235         } else if (!strcmp(arg->type, "varString")) {
236             fprintf(xg_h, "\t%s string a%d<STR_MAX>", arg->direction, i);
237         } else if (!strcmp(arg->direction, "IN")) {
238             fprintf(xg_h, "\t%s drpc_%s_t a%d", arg->direction, arg->type, i);
239         } else {
240             fprintf(xg_h, "\t%s drpc_%s_t *a%d", arg->direction, arg->type,
241                     i);
242         }
243         if (lastFlag) {
244             fputs(");\n", xg_h);
245         } else {
246             fputs(",\n", xg_h);
247         }
248     }
249 }
250
251 /*
252  * WriteXG -- write the body of the xg interface
253  */
254 PRIVATE void
255 WriteXG(rpcArgs * argsP, FILE * xg_h, char *serverName, int sign_no)
256 {
257     int i;
258     char *name = GetName(serverName, sign_no);
259
260     /*
261      * CASE 1: all arguments passed as parameters
262      */
263
264     fprintf(xg_h, "\nproc %s(\n", name);
265
266     /* declare each arg */
267     for (i = 0; i < argsP->argCount; i++) {
268         WriteXGDecl(&argsP->argDescr[i], xg_h, i, FALSE,
269                     (i == argsP->argCount - 1));
270     }
271
272     /* Now pass the paramaters inside a structure */
273     fprintf(xg_h, "\nstruct %s_t {\n", name);
274     for (i = 0; i < argsP->argCount; i++) {
275         WriteXGDecl(&argsP->argDescr[i], xg_h, i, TRUE,
276                     (i == argsP->argCount - 1));
277     }
278     fprintf(xg_h, "} ;\n");
279     fprintf(xg_h, "\nproc %s_s(\n", name);
280     fprintf(xg_h, "\tINOUT struct %s_t *s);\n", name);
281
282     free(name);
283 }
284
285 /*
286  * GetRandStr -- get a random string
287  */
288 PRIVATE void
289 GetRandStr(int strLen, char **ret, int *rP)
290 {
291     int i, randI;
292     char buf[5];
293
294     strcpy(*ret, "\"");
295     i = 0;
296     while (i < strLen) {
297         randI = 'A' + ('Z' - 'A') * drand32();
298         sprintf(buf, "%c", randI);
299         strcat(*ret, buf);
300         i++;
301     }
302     strcat(*ret, "\"");
303     *rP = randI;
304 }
305
306 /*
307  * GetRandP -- sets a string to a random value of the data type
308  * inthe case of a char type, ret holds "%c" and ret2 holds '%c'
309  */
310 PRIVATE void
311 GetRandP(char *typ, char **ret, char **ret2)
312 {
313     int randI, strLen;
314     float f;
315     double d, d1;
316     short shI;
317
318     *ret = (char *)calloc(MAX_RAND_LENGTH + 1, sizeof(char));
319     *ret2 = (char *)calloc(MAX_RAND_LENGTH + 1, sizeof(char));
320
321     if (strstr(typ, "char")) {
322         GetRandStr(1, ret2, &randI);
323         if (randI == '\\')
324             strcpy(*ret2, "'\\\\'");
325         else if (randI == '\'')
326             strcpy(*ret2, "'\\''");
327         else
328             sprintf(*ret, "'%c'", randI);
329         return;
330     } else if (strstr(typ, "short")) {
331         shI = SHRT_MIN + (SHRT_MAX - SHRT_MIN) * drand32();
332         sprintf(*ret, "%d", shI);
333         strcpy(*ret2, *ret);
334     } else if (strstr(typ, "afs_int32")) {
335         randI = INT_MIN + UINT_MAX * drand32();
336         if (randI < INT_MIN || randI > INT_MAX) {
337             fprintf(stderr, "GetRandP: afs_int32 %d out of bounds\n", randI);
338             exit(1);
339         }
340         sprintf(*ret, "%d", randI);
341         strcpy(*ret2, *ret);
342     } else if (strstr(typ, "float")) {
343         d = drand32();
344         f = d;
345         sprintf(*ret, "%2.8e", f);
346         strcpy(*ret2, *ret);
347
348     } else if (strstr(typ, "double")) {
349         d1 = drand32();
350         sprintf(*ret, "%2.16e", d1);
351         strcpy(*ret2, *ret);
352
353     } else if (strstr(typ, "String")) {
354         strLen = (MAX_RAND_LENGTH - 2) * drand32();
355         GetRandStr(strLen, ret, &randI);
356         strcpy(*ret2, *ret);
357     }
358 }
359
360
361 /*
362  * GenParamValues -- generate the parameter values for an rpc
363  */
364 PRIVATE void
365 GenParamValues(rpcArgs * argsP)
366 {
367     char *typ;
368     int i, j;
369
370     /* generate random values for each argument */
371     for (i = 0; i < argsP->argCount; i++) {
372
373         argsP->argDescr[i].vc_low = 0;
374         argsP->argDescr[i].vc_max = IDL_FIX_ARRAY_SIZE - 1;
375         argsP->argDescr[i].vc_high = IDL_FIX_ARRAY_SIZE - 1;
376         argsP->argDescr[i].ovc_low = 0;
377         argsP->argDescr[i].ovc_high = IDL_FIX_ARRAY_SIZE - 1;
378
379         if (!strncmp(argsP->argDescr[i].type, "ar_", 3)) {
380             typ = argsP->argDescr[i].type + 3;
381             for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++) {
382                 GetRandP(typ, &argsP->argDescr[i].inValue[j],
383                          &argsP->argDescr[i].inValue2[j]);
384                 GetRandP(typ, &argsP->argDescr[i].outValue[j],
385                          &argsP->argDescr[i].outValue2[j]);
386             }
387         } else {
388             GetRandP(argsP->argDescr[i].type, &argsP->argDescr[i].inValue[0],
389                      &argsP->argDescr[i].inValue2[0]);
390             GetRandP(argsP->argDescr[i].type, &argsP->argDescr[i].outValue[0],
391                      &argsP->argDescr[i].outValue2[0]);
392         }
393     }
394 }
395
396 /*
397  * WriteServC -- write the rpcs in the server file
398  */
399 PRIVATE void
400 WriteServC(rpcArgs * argsP, FILE * srv_h, char *serverName, int sign_no)
401 {
402     char *name, *typ;
403     int i, j;
404
405     name = GetName(serverName, sign_no);
406     fprintf(srv_h, "\nint A%s(struct rx_call *c,\n", name);
407
408     /* declare each arg */
409     for (i = 0; i < argsP->argCount; i++) {
410
411         if (!strcmp(argsP->argDescr[i].type, "varString")) {
412             if (!strcmp(argsP->argDescr[i].direction, "IN")) {
413                 fprintf(srv_h, "\tchar *a%d", i);
414             } else {
415                 fprintf(srv_h, "\tchar **a%d", i);
416             }
417         } else if (strncmp(argsP->argDescr[i].type, "ar_", 3)
418                    && (!strcmp(argsP->argDescr[i].direction, "IN"))) {
419             fprintf(srv_h, "\tdrpc_%s_t a%d", argsP->argDescr[i].type, i);
420         } else {
421             if (!strncmp(argsP->argDescr[i].type, "ar_", 3)) {
422                 fprintf(srv_h, "\tdrpc_out_%s_t *a%d",
423                         argsP->argDescr[i].type, i);
424             } else {
425                 fprintf(srv_h, "\tdrpc_%s_t *a%d", argsP->argDescr[i].type,
426                         i);
427             }
428         }
429         if (i < (argsP->argCount - 1)) {
430             fprintf(srv_h, ",\n");
431         }
432     }
433     fputs(")\n{\n", srv_h);     /* balance the } */
434     fputs("\tint errFlag = 0;", srv_h);
435
436     /*
437      * check the in and inout parameters
438      */
439     for (i = 0; i < argsP->argCount; i++) {
440
441         if (!strcmp(argsP->argDescr[i].direction, "IN")
442             || (!strcmp(argsP->argDescr[i].direction, "INOUT")
443                 && !strcmp(argsP->argDescr[i].type, "varString"))) {
444
445             typ = argsP->argDescr[i].type;
446
447             if (strstr(typ, "String")) {
448                 if (!strcmp(argsP->argDescr[i].direction, "INOUT")) {
449                     fprintf(srv_h, "\n\tCHECK%s((char *)*a%d, %s, \"%s\");",
450                             typ, i, argsP->argDescr[i].inValue[0], name);
451                 } else {
452                     fprintf(srv_h, "\n\tCHECK%s((char *)a%d, %s, \"%s\");",
453                             typ, i, argsP->argDescr[i].inValue[0], name);
454                 }
455             } else if (!strcmp(typ, "afs_int32")) {
456                 fprintf(srv_h, "\n\tCHECK%s(a%d, %sL, \"%s\");", typ, i,
457                         argsP->argDescr[i].inValue[0], name);
458             } else {
459                 if (!strncmp(typ, "ar_", 3)) {
460                     for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++)
461                         fprintf(srv_h,
462                                 "\n\tCHECK%s(a%d->drpc_out_%s_t_val[%d], %s, \"%s\");",
463                                 (typ + 3), i, typ, j,
464                                 argsP->argDescr[i].inValue[j], name);
465                 } else {
466                     fprintf(srv_h, "\n\tCHECK%s(a%d, %s, \"%s\");", typ, i,
467                             argsP->argDescr[i].inValue[0], name);
468                 }
469             }
470         } else if (!strcmp(argsP->argDescr[i].direction, "INOUT")) {
471
472             typ = argsP->argDescr[i].type;
473
474             if (strstr(typ, "String")) {
475                 fprintf(srv_h, "\n\tCHECK%s((char *)*a%d, %s, \"%s\");", typ,
476                         i, argsP->argDescr[i].inValue[0], name);
477             } else if (!strcmp(typ, "afs_int32")) {
478                 fprintf(srv_h, "\n\tCHECK%s(*a%d, %sL, \"%s\");", typ, i,
479                         argsP->argDescr[i].inValue[0], name);
480             } else {
481                 if (!strncmp(typ, "ar_", 3)) {
482                     for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++)
483                         fprintf(srv_h,
484                                 "\n\tCHECK%s(a%d->drpc_out_%s_t_val[%d], %s, \"%s\");",
485                                 (typ + 3), i, typ, j,
486                                 argsP->argDescr[i].inValue[j], name);
487                 } else {
488                     fprintf(srv_h, "\n\tCHECK%s(*a%d, %s, \"%s\");", typ, i,
489                             argsP->argDescr[i].inValue[0], name);
490                 }
491             }
492         }
493     }
494
495     /*
496      * free up memory for dynamic input args
497      */
498     for (i = 0; i < argsP->argCount; i++) {
499         if (!strncmp(argsP->argDescr[i].type, "ar_", 3)) {
500             typ = argsP->argDescr[i].type;
501             if (!strcmp(argsP->argDescr[i].direction, "INOUT")) {
502                 fprintf(srv_h,
503                         "\n\tif (a%d->drpc_out_%s_t_val) "
504                         "free(a%d->drpc_out_%s_t_val);", i, typ, i, typ);
505             }
506             if (!strcmp(argsP->argDescr[i].direction, "INOUT")
507                 || !strcmp(argsP->argDescr[i].direction, "OUT")) {
508                 fprintf(srv_h,
509                         "\n\ta%d->drpc_out_%s_t_val = (%s *) "
510                         "malloc(FIX_ARRAY_SIZE * sizeof(%s));", i, typ,
511                         (typ + 3), (typ + 3));
512                 fprintf(srv_h, "\n\ta%d->drpc_out_%s_t_len = FIX_ARRAY_SIZE;",
513                         i, typ);
514             }
515         }
516     }
517
518     /*
519      * set the inout and out parameters
520      */
521     for (i = 0; i < argsP->argCount; i++) {
522
523         if (!strcmp(argsP->argDescr[i].direction, "INOUT")
524             || !strcmp(argsP->argDescr[i].direction, "OUT")) {
525
526             typ = argsP->argDescr[i].type;
527
528             if (!strncmp(typ, "ar_", 3)) {
529                 for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++)
530                     fprintf(srv_h, "\n\ta%d->drpc_out_%s_t_val[%d] = %s;", i,
531                             typ, j, argsP->argDescr[i].outValue[j]);
532             } else if (!strcmp(typ, "afs_int32")) {
533                 fprintf(srv_h, "\n\t*a%d = %sL;", i,
534                         argsP->argDescr[i].outValue[0]);
535             } else if (!strcmp(typ, "varString")) {
536                 if (!strcmp(argsP->argDescr[i].direction, "OUT")) {
537                     fprintf(srv_h, "\n\t*a%d = (char *) malloc(STR_MAX);", i);
538                 }
539                 fprintf(srv_h, "\n\tstrcpy((char *)*a%d, %s);", i,
540                         argsP->argDescr[i].outValue[0]);
541             } else if (strstr(typ, "String")) {
542                 fprintf(srv_h, "\n\t*a%d = (drpc_%s_t)rpc_ss_allocate(%d);",
543                         i, typ, strlen(argsP->argDescr[i].outValue[0]) - 1);
544                 fprintf(srv_h, "\n\tstrcpy((char *)*a%d, %s);", i,
545                         argsP->argDescr[i].outValue[0]);
546             } else {
547                 fprintf(srv_h, "\n\t*a%d = %s;", i,
548                         argsP->argDescr[i].outValue[0]);
549             }
550         }
551     }
552
553     fprintf(srv_h,
554             "\n\tif (errFlag) {" "\n\t\tprintf(\"%s: failed\\n\");"
555             "\n\t\tfflush(stdout);" "\n\t}" "\n\treturn errFlag;\n}\n", name);
556
557     /*
558      * second routine with arguments inside a structure
559      */
560     fprintf(srv_h,
561             "\nint A%s_s(struct rx_call *c,\n\t%s_t *s)\n{"
562             "\n\tint errFlag = 0;", name, name);
563
564     /*
565      * check the in and inout parameters
566      */
567     for (i = 0; i < argsP->argCount; i++) {
568
569         if (!strcmp(argsP->argDescr[i].direction, "IN")
570             || (!strstr(argsP->argDescr[i].type, "String")
571                 && !strcmp(argsP->argDescr[i].direction, "INOUT"))) {
572
573             typ = argsP->argDescr[i].type;
574
575             if (!strncmp(typ, "ar_", 3)) {
576                 for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++)
577                     fprintf(srv_h, "\n\tCHECK%s(s->a%d[%d], %s, \"%s_s\");",
578                             (typ + 3), i, j, argsP->argDescr[i].inValue[j],
579                             name);
580             } else if (strstr(typ, "String")) {
581                 fprintf(srv_h, "\n\tCHECK%s((char *)s->a%d, %s, \"%s_s\");",
582                         typ, i, argsP->argDescr[i].inValue[0], name);
583             } else if (!strcmp(typ, "afs_int32")) {
584                 fprintf(srv_h, "\n\tCHECK%s(s->a%d, %sL, \"%s_s\");", typ, i,
585                         argsP->argDescr[i].inValue[0], name);
586             } else {
587                 fprintf(srv_h, "\n\tCHECK%s(s->a%d, %s, \"%s_s\");", typ, i,
588                         argsP->argDescr[i].inValue[0], name);
589             }
590         }
591     }
592
593     /*
594      * set the inout and out parameters
595      */
596     for (i = 0; i < argsP->argCount; i++) {
597
598         if (!strcmp(argsP->argDescr[i].direction, "INOUT")
599             || !strcmp(argsP->argDescr[i].direction, "OUT")) {
600
601             typ = argsP->argDescr[i].type;
602
603             if (!strncmp(typ, "ar_", 3)) {
604                 for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++)
605                     fprintf(srv_h, "\n\ts->a%d[%d]= %s;", i, j,
606                             argsP->argDescr[i].outValue[j]);
607             } else if (!strcmp(typ, "afs_int32")) {
608                 fprintf(srv_h, "\n\ts->a%d = %sL;", i,
609                         argsP->argDescr[i].outValue[0]);
610             } else if (!strcmp(typ, "varString")) {
611                 fprintf(srv_h, "\n\tstrcpy((char *)s->a%d, %s);", i,
612                         argsP->argDescr[i].outValue[0]);
613             } else if (strstr(typ, "String")) {
614                 fprintf(srv_h, "\n\ts->a%d = rpc_ss_allocate(%d);", i,
615                         strlen(argsP->argDescr[i].outValue[0]) - 1);
616                 fprintf(srv_h, "\n\tstrcpy((char *)s->a%d, %s);", i,
617                         argsP->argDescr[i].outValue[0]);
618             } else {
619                 fprintf(srv_h, "\n\ts->a%d = %s;", i,
620                         argsP->argDescr[i].outValue[0]);
621             }
622         }
623     }
624
625     fprintf(srv_h,
626             "\n\tif (errFlag) {" "\n\t\tprintf(\"%s_s: failed\\n\");" "\n\t}"
627             "\n\tfflush(stdout);" "\n\treturn errFlag;\n}\n", name);
628
629
630     free(name);
631 }
632
633 /*
634  * WriteMake - write the makefile for a particular client/server pair
635  */
636 PRIVATE void
637 WriteMake(char *serverName, int srv_no, FILE * mak_h)
638 {
639     char p[1024];
640     char *obj = platform[2];
641
642     sprintf(p, "%s%d", serverName, srv_no);
643     fprintf(mak_h, "%s", platform[1]);
644     if (threadModel == PTHREADS) {
645         fprintf(mak_h, "CFLAGS = -KPIC -g -mt -I$(DESTDIR)include\n" "%s",
646                 platform[6]
647             );
648     } else {
649         fprintf(mak_h, "CFLAGS = -g -I$(DESTDIR)include\n" "%s", platform[7]
650             );
651     }
652     fprintf(mak_h,
653             "\n\ntest: all\ntests: all\nall: %sClt %sSrv\n\n"
654             "%sClt: %s.cs.%s %s.xdr.%s %sClt.%s $(LIBS)\n", p, p, p, p, obj,
655             p, obj, p, obj);
656     if (platform == nt_symbols) {
657         fprintf(mak_h, "\t$(EXECONLINK)\n\n");
658     } else {
659         fprintf(mak_h,
660                 "\t$(CC) $(CFLAGS) -o $@ %sClt.%s %s.cs.%s %s.xdr.%s "
661                 "$(LIBS) $(XLIBS)\n\n", p, obj, p, obj, p, obj);
662     }
663     fprintf(mak_h,
664             "%s.xdr.c: %s.xg\n\n" "%s.h %s.cs.c %s.ss.c: %s.xg\n"
665             "\t$(RXGEN) %s.xg\n" "\t%s %s.cs.c\n" "\t%s %s.ss.c\n\n", p, p, p,
666             p, p, p, p, platform[3], p, platform[3], p);
667     fprintf(mak_h, "%sSrv: %s.ss.%s %s.xdr.%s %sSrv.%s $(LIBS)\n", p, p, obj,
668             p, obj, p, obj);
669
670     if (platform == nt_symbols) {
671         fprintf(mak_h, "\t$(EXECONLINK)\n\n");
672     } else {
673         fprintf(mak_h,
674                 "\t$(CC) $(CFLAGS) -o $@ %sSrv.o %s.ss.o %s.xdr.o "
675                 "$(LIBS) $(XLIBS)\n\n", p, p, p);
676     }
677
678     if (platform == unix_symbols) {
679         fprintf(mak_h,
680                 "clean:\n" "\t/bin/rm -f %sClt %s.h %s.cs.c %s.ss.c core "
681                 "%sSrv %sSrv.o \\\n"
682                 "\t%sClt.o %s.cs.o %s.ss.o %s.xdr.c %s.xdr.o\n", p, p, p, p,
683                 p, p, p, p, p, p, p);
684     }
685
686 }
687
688 /*
689  * WriteCltTrailer - finish writing client source
690  */
691 PRIVATE void
692 WriteCltTrailer(char *serverName, int first, int last, FILE * itl_h)
693 {
694     int i = 0;
695
696     /*
697      * Write out 1 function that calls all the manager functions
698      */
699     if (threadModel == PTHREADS) {
700         fprintf(itl_h, "\n\nvoid *threadFunc(void *arg) {\n");
701     } else {
702         fprintf(itl_h, "\n\nint threadFunc(int *arg) {\n");
703     }
704
705     fprintf(itl_h,
706             "\tstruct rx_connection *conn;\n" "\tint error=0;\n\n"
707             "\tint i = (int) arg;\n\n");
708
709     fprintf(itl_h,
710             "\tconn = rx_GetCachedConnection(serverAddr,serverPort,4,secClass,secIndex);\n");
711
712     fprintf(itl_h, "\twhile(i--) {\n");
713
714     if (first == 0)
715         first = 1;
716     for (i = first; i < last; i++) {
717         fprintf(itl_h, "\t\tC_%s%d(conn);\n", serverName, i);
718         fprintf(itl_h, "\t\tC_%s%d_s(conn);\n", serverName, i);
719     }
720     fprintf(itl_h, "\t}\n");
721
722     fprintf(itl_h, "\trx_ReleaseCachedConnection(conn);\n");
723
724     if (threadModel == PTHREADS) {
725         fprintf(itl_h, "\treturn (void *) 0;\n");
726     } else {
727         fprintf(itl_h,
728                 "\tLWP_CALL(LWP_SignalProcess,(&done));\n" "\treturn 0;\n");
729     }
730
731     fprintf(itl_h, "}\n");
732
733     fprintf(itl_h,
734             "\n\nstatic void DoRun(struct cmd_syndesc *as, char *arock) {\n");
735
736     if (threadModel == PTHREADS) {
737         fprintf(itl_h, "\tpthread_t *tid;\n");
738     } else {
739         fprintf(itl_h, "\tPROCESS *tid;\n");
740     }
741
742     fprintf(itl_h,
743             "\tint i,j;\n" "\tunsigned int numThreads=0,numIterations=0;\n"
744             "\tint errflg=0;\n" "\tstruct hostent *host=NULL;\n\n"
745             "\tnumThreads = atoi(as->parms[0].items->data);\n"
746             "\tnumIterations = atoi(as->parms[1].items->data);\n"
747             "\tsecType = atoi(as->parms[2].items->data);\n"
748             "\tencLevel = atoi(as->parms[3].items->data);\n"
749             "\tserverPort = htons(atoi(as->parms[4].items->data));\n"
750             "\tif ((host = hostutil_GetHostByName(as->parms[5].items->data))==0) {\n"
751             "\t\terrflg++;\n" "\t}\n" "\telse {\n"
752             "\t\tmemcpy((void *) &serverAddr, (const void *)host->h_addr, sizeof(serverAddr));\n"
753             "\t}\n" "\tif ((secType<1) || (secType>2)) errflg++;\n"
754             "\tif ((encLevel<0) || (encLevel>2)) errflg++;\n"
755             "\tif ((serverPort == 0) ||(numThreads == 0) ||(numIterations == 0)) errflg++;\n"
756             "\tif (errflg) {\n" "\t\tprintf(\"invalid argument\\n\");\n"
757             "\t\texit(1);\n" "\t}\n\n" "\tif(rx_Init(htons(0)) < 0) {\n"
758             "\t\texit(1);\n" "\t}\n\n" "\tswitch(secType) {\n" "\t\tcase 1:\n"
759             "\t\t\tsecIndex = 0;\n"
760             "\t\t\tsecClass = rxnull_NewClientSecurityObject();\n"
761             "\t\t\tbreak;\n" "\t\tcase 2:\n"
762             "\t\t\tif (GetTicket (&kvno, &Ksession, &ticketLen, ticket) == 0) {\n"
763             "\t\t\t\tsecIndex = 2;\n"
764             "\t\t\t\tsecClass = rxkad_NewClientSecurityObject(encLevel,\n"
765             "\t\t\t\t&Ksession, kvno, ticketLen, ticket);\n" "\t\t\t}\n"
766             "\t\t\tbreak;\n" "\t\tdefault:\n" "\t\t\tbreak;\n" "\t}\n"
767             "\tassert(secClass);\n\n");
768     if (threadModel == PTHREADS) {
769         fprintf(itl_h,
770                 "#if defined sun\n" "\tthr_setconcurrency(numThreads);\n"
771                 "#endif\n" "\ttid = (pthread_t *) "
772                 "malloc(numThreads*(sizeof(pthread_t)));\n");
773     } else {
774         fprintf(itl_h,
775                 "\ttid = (PROCESS *) malloc(numThreads*(sizeof(PROCESS *)));\n");
776     }
777
778     fprintf(itl_h, "\tassert(tid);\n" "\tfor(j=0;j<numThreads;j++) {\n");
779     if (threadModel == PTHREADS) {
780         fprintf(itl_h,
781                 "\t\ti = pthread_create(&tid[j], (const pthread_attr_t *) 0,\n"
782                 "\t\tthreadFunc, (void *) numIterations);\n"
783                 "\t\tassert(i==0);\n");
784     } else {
785         fprintf(itl_h,
786                 "\t\tLWP_CALL(LWP_CreateProcess,(threadFunc, 10*4096, LWP_NORMAL_PRIORITY, numIterations, \"foo\", &tid[j]));\n");
787     }
788
789     fprintf(itl_h, "\t}\n" "\tfor(j=0;j<numThreads;j++) {\n");
790     if (threadModel == PTHREADS) {
791         fprintf(itl_h,
792                 "\t\ti = pthread_join(tid[j], (void **) 0);\n"
793                 "\t\tassert(i==0);\n");
794     } else {
795         fprintf(itl_h, "\t\tLWP_CALL(LWP_WaitProcess,(&done));\n");
796     }
797     fprintf(itl_h, "\t}\n" "\trx_Finalize();\n" "\tfree(tid);\n" "}\n");
798
799     /*
800      * Write command syntax function
801      */
802
803     fprintf(itl_h,
804             "static void SetupRunCmd(void) {\n" "\tstruct cmd_syndesc *ts;\n"
805             "\tts = cmd_CreateSyntax(NULL,DoRun, 0, \"run the test client program\");\n"
806             "\tcmd_AddParm(ts, \"-threadCount\", CMD_SINGLE, CMD_REQUIRED, \"number of threads to spawn\");\n"
807             "\tcmd_AddParm(ts, \"-iterationCount\", CMD_SINGLE, CMD_REQUIRED, \"number of iterations to make over entire interface for each thread\");\n"
808             "\tcmd_AddParm(ts, \"-secType\", CMD_SINGLE, CMD_REQUIRED, \"security level to use (1 -> unauthenticated, 2 -> authenticated)\");\n"
809             "\tcmd_AddParm(ts, \"-encLevel\", CMD_SINGLE, CMD_REQUIRED, \"encryption level to use, (0-> rxkad_clear, 1 -> rxkad_auth, 2 -> rxkad_crypt)\");\n"
810             "\tcmd_AddParm(ts, \"-serverPort\", CMD_SINGLE, CMD_REQUIRED, \"port that server is using\");\n"
811             "\tcmd_AddParm(ts, \"-serverHost\", CMD_SINGLE, CMD_REQUIRED, \"host where server is running\");\n"
812             "}\n");
813
814     /*
815      * Write client main
816      */
817
818     fprintf(itl_h,
819             "int main (int argc, char *argv[]) {\n" "\tint code;\n\n"
820             "\tinitialize_CMD_error_table();\n" "\tSetupRunCmd();\n"
821             "\tcode = cmd_Dispatch(argc, argv);\n\n" "\treturn(code);\n"
822             "\t}\n");
823
824 }
825
826 /*
827  * Create macros useful for checking input/output parameters
828  */
829
830 PRIVATE void
831 WriteTestMacros(FILE * f)
832 {
833     fprintf(f,
834             "\n#define CHECKchar(x,y,z) if ((x)!=(y)) { printf(\"%%s: Got '%%c',"
835             "expected '%%c'\\n\", z, (char)x, (char)(y)); fflush(stdout); "
836             "errFlag = 1; } " "\n#define CHECKshort(x,y,z) if ((x)!=(y)) "
837             "{ printf(\"%%s: Got 0x%%04x, "
838             "expected 0x%%04x\\n\", z, x, y); fflush(stdout); "
839             "errFlag = 1; } " "\n#define CHECKint32(x,y,z) if ((x)!=(y)) "
840             "{ printf(\"%%s: Got 0x%%08x, "
841             "expected 0x%%08x\\n\", z, x, y); fflush(stdout); "
842             "errFlag = 1; } "
843             "\n#define CHECKfloat(x,y,z) if (((x)/(y)<.999999) "
844             "|| ((x)/(y)>1.000001)) "
845             "{ printf(\"%%s: Got %%2.8e, expected %%2.8e\\n\", z, x, y); "
846             "fflush(stdout); " "errFlag = 1; } "
847             "\n#define CHECKdouble(x,y,z) if (((x)/(y)<.999999999999999) || "
848             "((x)/(y)>1.000000000000001)) { printf(\"%%s: Got %%2.16e, "
849             "expected %%2.16e\\n\", z, x, y); fflush(stdout); errFlag = 1; }"
850             "\n#define CHECKvarString(x,y,z) if (strcmp((x),(y))) { printf(\"%%s: "
851             "Got \\\"%%s\\\", expected \\\"%%s\\\"\\n\", z, x, y); fflush(stdout); "
852             "errFlag = 1; } \n");
853 }
854
855 /*
856  * WriteCltHeader - write the begining of the client code.
857  */
858 PRIVATE void
859 WriteCltHeader(char *serverName, int srv_no, FILE * itl_h)
860 {
861     fprintf(itl_h, "#include <stdio.h>\n");
862     if (threadModel == PTHREADS) {
863         fprintf(itl_h, "#include <pthread.h>\n");
864     }
865     fprintf(itl_h,
866             "%s" "#include <assert.h>\n" "#include <rx/rx.h>\n"
867             "#include <rx/rx_null.h>\n" "#include <rx/rxkad.h>\n"
868             "#include <afs/cmd.h>\n" "#include \"%s%d.h\"\n", platform[4],
869             serverName, srv_no);
870     if (threadModel == LWPS) {
871         fprintf(itl_h,
872                 "\n\n#define LWP_CALL(fnName, params) \\\n" "{ \\\n"
873                 "\tint rc; \\\n" "\trc = fnName params; \\\n"
874                 "\tif (rc != LWP_SUCCESS) { \\\n"
875                 "\t\tprintf(\"call to %%s failed with %%d\\n\", # fnName, rc); \\\n"
876                 "\t\texit(1); \\\n" "\t} \\\n" "};\n\n" "char done;\n\n");
877     }
878
879     fprintf(itl_h,
880             "struct ktc_encryptionKey serviceKey =\n"
881             "\t{0x45, 0xe3, 0x3d, 0x16, 0x29, 0x64, 0x8a, 0x8f};\n"
882             "long serviceKeyVersion = 7;\n"
883             "\nextern struct hostent *hostutil_GetHostByName();\n\n"
884             "static long GetTicket (long *versionP,\n"
885             "\tstruct ktc_encryptionKey *session,\n"
886             "\tint * ticketLenP, char *ticket)\n" "{\n" "\tlong code;\n"
887             "\tdes_init_random_number_generator (&serviceKey);\n"
888             "\tcode = des_random_key (session);\n"
889             "\tif (code) return code;\n" "\t*ticketLenP = 0;\n"
890             "\tcode = tkt_MakeTicket(ticket, ticketLenP, &serviceKey,\n"
891             "\t\t\"tclnt\", \"\", \"\",\n" "\t\t0, 0xffffffff, session, 0,\n"
892             "\t\t\"tsrvr\", \"\");\n" "\tif (code) return code;\n"
893             "\t*versionP = serviceKeyVersion;\n" "\treturn 0;\n" "}\n\n"
894             "static int secType,encLevel,serverPort,serverAddr;\n"
895             "struct rx_securityClass *secClass;\n" "int secIndex;\n"
896             "long kvno;\n" "char ticket[MAXKTCTICKETLEN];\n"
897             "int ticketLen;\n" "struct ktc_encryptionKey Ksession;\n\n");
898     WriteTestMacros(itl_h);
899
900 }
901
902 /*
903  * WriteCltInit -- write the initialization for each param
904  */
905 PRIVATE void
906 WriteCltInit(arg_tuple * arg, FILE * itl_h, int i, int structFlag)
907 {
908     int j;
909     char *s = (structFlag) ? "s." : "";
910
911     if ((!strncmp(arg->direction, "IN", 2) || structFlag)) {
912         if (!strncmp(arg->type, "varString", 9)) {
913             fprintf(itl_h, "\tstrcpy(%sa%d, %s);\n", s, i, arg->inValue[0]);
914         } else if (!strncmp(arg->type, "ar_", 3)) {
915             if (!structFlag) {
916                 fprintf(itl_h,
917                         "\t%sa%d.drpc_out_%s_t_len = FIX_ARRAY_SIZE;\n", s, i,
918                         arg->type);
919                 fprintf(itl_h,
920                         "\t%sa%d.drpc_out_%s_t_val = "
921                         "(%s *) malloc(FIX_ARRAY_SIZE * sizeof(%s));\n", s, i,
922                         arg->type, (arg->type + 3), (arg->type + 3));
923             }
924             for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++) {
925                 if (structFlag) {
926                     fprintf(itl_h, "\t%sa%d[%d] = %s;\n", s, i, j,
927                             arg->inValue[j]);
928                 } else {
929                     fprintf(itl_h, "\t%sa%d.drpc_out_%s_t_val[%d] = %s;\n", s,
930                             i, arg->type, j, arg->inValue[j]);
931                 }
932             }
933         } else {
934             fprintf(itl_h, "\t%sa%d = %s;\n", s, i, arg->inValue[0]);
935         }
936     }
937 }
938
939 /*
940  * WriteCltCall -- write each parameter for a call
941  */
942 PRIVATE void
943 WriteCltCall(arg_tuple * arg, FILE * itl_h, int i)
944 {
945
946     if (!strncmp(arg->type, "varString", 9)) {
947         if ((!strncmp(arg->direction, "OUT", 3))
948             || (!strncmp(arg->direction, "INOUT", 5))) {
949             fprintf(itl_h, "&a%d_p", i);
950         } else {
951             fprintf(itl_h, "a%d_p", i);
952         }
953     } else {
954         if ((!strncmp(arg->direction, "OUT", 3))
955             || (!strncmp(arg->direction, "INOUT", 5))
956             || (!strncmp(arg->type, "ar_", 3))) {
957             fprintf(itl_h, "&a%d", i);
958         } else {
959             fprintf(itl_h, "a%d", i);
960         }
961     }
962 }
963
964 /*
965  * WriteCltDecl -- write the declaration for a parameter
966  */
967 PRIVATE void
968 WriteCltDecl(arg_tuple * arg, FILE * itl_h, int i)
969 {
970
971     if (!strncmp(arg->type, "ar_", 3)) {
972         if (!strncmp(arg->direction, "OUT", 3)) {
973             fprintf(itl_h, "\tdrpc_out_%s_t a%d = {0,0};\n", arg->type, i);
974         } else {
975             fprintf(itl_h, "\tdrpc_out_%s_t a%d;\n", arg->type, i);
976         }
977     } else if (!strncmp(arg->type, "varString", 9)) {
978         fprintf(itl_h, "\tchar a%d[STR_MAX];\n", i);
979         fprintf(itl_h, "\tchar *a%d_p = a%d;\n", i, i);
980     } else {
981         fprintf(itl_h, "\t%s a%d;\n", arg->type, i);
982     }
983 }
984
985
986 /*
987  * WriteClt -- write the rpcs in the client
988  */
989 PRIVATE void
990 WriteClt(rpcArgs * argsP, char *serverName, int sign_no, FILE * itl_h)
991 {
992     char *name, *name2, *typ;
993     int i, j;
994
995     name = GetName(serverName, sign_no);
996     name2 = GetDescription(argsP);
997
998     fprintf(itl_h, "\n/* %s */\n\n", name2);
999
1000     fprintf(itl_h, "\nvoid C_%s(struct rx_connection *conn) {\n", name);
1001
1002     /* declare each arg */
1003     for (i = 0; i < argsP->argCount; i++) {
1004         WriteCltDecl(&argsP->argDescr[i], itl_h, i);
1005     }
1006     fprintf(itl_h, "\tint error;\n\tint errFlag;\n\n");
1007
1008     /* initialize IN/INOUT args */
1009     for (i = 0; i < argsP->argCount; i++) {
1010         WriteCltInit(&argsP->argDescr[i], itl_h, i, FALSE);
1011     }
1012
1013     /* call the server */
1014     fprintf(itl_h, "\terror = A%s(conn, ", name);
1015
1016     /* pass each arg */
1017     for (i = 0; i < argsP->argCount; i++) {
1018         WriteCltCall(&argsP->argDescr[i], itl_h, i);
1019         fprintf(itl_h, ((i < (argsP->argCount - 1))) ? "," : ");\n");
1020     }
1021
1022     fprintf(itl_h,
1023             "\tif (error != 0) {\n"
1024             "\t\tprintf(\"C_%s failed %%d\\n\", error);\n"
1025             "\t\tfflush(stdout);\n" "\t\treturn;\n" "\t}\n", name);
1026
1027     /*
1028      * check the in and inout parameters
1029      */
1030     for (i = 0; i < argsP->argCount; i++) {
1031
1032         if ((!strcmp(argsP->argDescr[i].direction, "OUT"))
1033             || (!strcmp(argsP->argDescr[i].direction, "INOUT"))) {
1034
1035             typ = argsP->argDescr[i].type;
1036
1037             if (!strncmp(typ, "ar_", 3)) {
1038                 for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++)
1039                     fprintf(itl_h,
1040                             "\n\tCHECK%s(a%d.drpc_out_%s_t_val[%d], %s, \"C_%s_s\");",
1041                             (typ + 3), i, typ, j,
1042                             argsP->argDescr[i].outValue[j], name);
1043             } else if (strstr(typ, "String")) {
1044                 fprintf(itl_h, "\n\tCHECK%s((char *)a%d, %s, \"C_%s_s\");",
1045                         typ, i, argsP->argDescr[i].outValue[0], name);
1046             } else if (!strcmp(typ, "afs_int32")) {
1047                 fprintf(itl_h, "\n\tCHECK%s(a%d, %sL, \"C_%s_s\");", typ, i,
1048                         argsP->argDescr[i].outValue[0], name);
1049             } else {
1050                 fprintf(itl_h, "\n\tCHECK%s(a%d, %s, \"C_%s_s\");", typ, i,
1051                         argsP->argDescr[i].outValue[0], name);
1052             }
1053         }
1054     }
1055
1056     /*
1057      * free up memory for dynamic input args
1058      */
1059     for (i = 0; i < argsP->argCount; i++) {
1060         if (!strncmp(argsP->argDescr[i].type, "ar_", 3)) {
1061             typ = argsP->argDescr[i].type;
1062             fprintf(itl_h,
1063                     "\n\tif (a%d.drpc_out_%s_t_val) "
1064                     "free(a%d.drpc_out_%s_t_val);", i, typ, i, typ);
1065         }
1066     }
1067
1068
1069     fprintf(itl_h, "\n}\n");
1070
1071     /*
1072      * Call the structure oriented rpc interface
1073      */
1074
1075     fprintf(itl_h, "\nvoid C_%s_s(struct rx_connection *conn) {\n", name);
1076     fprintf(itl_h, "\tstruct %s_t s;\n", name);
1077     fprintf(itl_h, "\tint error;\n\tint errFlag;\n\n");
1078
1079     /* initialize IN/INOUT args */
1080     for (i = 0; i < argsP->argCount; i++) {
1081         WriteCltInit(&argsP->argDescr[i], itl_h, i, TRUE);
1082     }
1083
1084     /* call the server */
1085     fprintf(itl_h, "\terror = A%s_s(conn, &s);\n", name);
1086
1087     fprintf(itl_h,
1088             "\tif (error != 0) {\n"
1089             "\t\tprintf(\"C_%s_s failed %%d\\n\", error);\n"
1090             "\t\tfflush(stdout);\n" "\t\treturn;\n" "\t}\n", name);
1091
1092     /*
1093      * check the in and inout parameters
1094      */
1095     for (i = 0; i < argsP->argCount; i++) {
1096
1097         if ((!strcmp(argsP->argDescr[i].direction, "OUT"))
1098             || (!strcmp(argsP->argDescr[i].direction, "INOUT"))) {
1099
1100             typ = argsP->argDescr[i].type;
1101
1102             if (!strncmp(typ, "ar_", 3)) {
1103                 for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++)
1104                     fprintf(itl_h, "\n\tCHECK%s(s.a%d[%d], %s, \"C_%s_s\");",
1105                             (typ + 3), i, j, argsP->argDescr[i].outValue[j],
1106                             name);
1107             } else if (strstr(typ, "String")) {
1108                 fprintf(itl_h, "\n\tCHECK%s((char *)s.a%d, %s, \"C_%s_s\");",
1109                         typ, i, argsP->argDescr[i].outValue[0], name);
1110             } else if (!strcmp(typ, "afs_int32")) {
1111                 fprintf(itl_h, "\n\tCHECK%s(s.a%d, %sL, \"C_%s_s\");", typ, i,
1112                         argsP->argDescr[i].outValue[0], name);
1113             } else {
1114                 fprintf(itl_h, "\n\tCHECK%s(s.a%d, %s, \"C_%s_s\");", typ, i,
1115                         argsP->argDescr[i].outValue[0], name);
1116             }
1117         }
1118     }
1119
1120
1121     fprintf(itl_h, "\n}\n");
1122
1123     free(name);
1124     free(name2);
1125 }
1126
1127 /*
1128  * WriteXGHeader -- fill in Header info in the xg file
1129  */
1130 PRIVATE void
1131 WriteXGHeader(char *serverName, FILE * xg_h, int srv_no)
1132 {
1133
1134     /* create the interface header */
1135
1136     fprintf(xg_h,
1137             "\n/* Do not edit this file -- it was created by a generator */\n"
1138             "\npackage A\n\n" "const STR_MAX = %d; \n"
1139             "const FIX_ARRAY_SIZE = %d; \n" "typedef char drpc_char_t; \n"
1140             "typedef short drpc_short_t; \n" "typedef long drpc_int32_t; \n"
1141             "typedef string drpc_varString_t<STR_MAX>; \n"
1142             "typedef drpc_char_t drpc_ar_char_t[FIX_ARRAY_SIZE]; \n"
1143             "typedef drpc_char_t drpc_out_ar_char_t<FIX_ARRAY_SIZE>; \n"
1144             "typedef drpc_short_t drpc_ar_short_t[FIX_ARRAY_SIZE]; \n"
1145             "typedef drpc_short_t drpc_out_ar_short_t<FIX_ARRAY_SIZE>; \n"
1146             "typedef drpc_int32_t drpc_ar_int32_t[FIX_ARRAY_SIZE]; \n"
1147             "typedef drpc_int32_t drpc_out_ar_int32_t<FIX_ARRAY_SIZE>; \n",
1148             IDL_STR_MAX, IDL_FIX_ARRAY_SIZE);
1149 }
1150
1151 /*
1152  * WriteServHeader -- fill in the Header info in the server file
1153  */
1154 PRIVATE void
1155 WriteServHeader(FILE * srv_h, char *serverName, int srv_no)
1156 {
1157     char *name;
1158
1159     name = GetName(serverName, srv_no);
1160
1161     fprintf(srv_h,
1162             "\n/* Do not edit this file -- it's been created by a generator */\n\n"
1163             "%s\n" "#include <stdio.h>\n" "#include <string.h>\n"
1164             "#include <stdlib.h>\n" "#include <rx/rx.h>\n"
1165             "#include <rx/rx_null.h>\n" "#include <rx/rxkad.h>\n"
1166             "#include <afs/cmd.h>\n" "#include \"%s.h\"\n\n"
1167             "struct ktc_encryptionKey serviceKey =\n"
1168             "\t{0x45, 0xe3, 0x3d, 0x16, 0x29, 0x64, 0x8a, 0x8f};\n"
1169             "long serviceKeyVersion = 7;\n\n"
1170             "extern int AExecuteRequest();\n" "extern char *optarg;\n"
1171             "extern int optind, opterr, optopt;\n\n"
1172             "#define VERIFY(x,y) if (!(x)) { printf y ; exit(1); }\n"
1173             "#define CHECK(x) ASSERT(x)\n", platform[4], name);
1174
1175     WriteTestMacros(srv_h);
1176     free(name);
1177 }
1178
1179 /*
1180  * WriteServTrailer -- finish up the server file
1181  */
1182 PRIVATE void
1183 WriteServTrailer(FILE * srv_h)
1184 {
1185
1186     fprintf(srv_h,
1187             "\nstatic long GetKey (char *rock, long kvno, struct ktc_encryptionKey *key) {\n"
1188             "\tmemcpy ((void *) key, (void *) &serviceKey, sizeof(*key));\n"
1189             "\treturn 0;\n" "}\n\n"
1190             "static void DoRun(struct cmd_syndesc *as, char *arock) {\n"
1191             "\tstruct rx_service *serv;\n"
1192             "\tstruct rx_securityClass *sc[3];\n\n"
1193             "\tint port=0, errflg=0;\n" "\tint lowThreads=4, highThreads=8;\n"
1194             "\tlowThreads = atoi(as->parms[0].items->data);\n"
1195             "\thighThreads = atoi(as->parms[1].items->data);\n"
1196             "\tport = atoi(as->parms[2].items->data);\n"
1197             "\tif (port == 0) errflg++;\n" "\tif (errflg) {\n"
1198             "\t\tprintf(\"invalid argument\\n\");\n" "\t\texit(1);\n" "\t}\n"
1199             "\trx_Init(htons(port));\n"
1200             "\tsc[0] = rxnull_NewServerSecurityObject();\n" "\tsc[1] = 0;\n"
1201             "\tsc[2] = rxkad_NewServerSecurityObject (rxkad_clear, 0, GetKey, 0);\n"
1202             "\tif (serv = rx_NewService(0,4,\"foo\",sc,3,AExecuteRequest)) {\n"
1203             "\t\trx_SetMinProcs(serv,lowThreads);\n"
1204             "\t\trx_SetMaxProcs(serv,highThreads);\n"
1205             "\t\trx_StartServer(1);\n" "\t}\n" "\texit(0);\n" "}\n\n"
1206             "static void SetupRunCmd(void) {\n" "\tstruct cmd_syndesc *ts;\n"
1207             "\tts = cmd_CreateSyntax(NULL,DoRun, 0, \"run the test server program\");\n"
1208             "\tcmd_AddParm(ts, \"-lowThreadCount\", CMD_SINGLE, CMD_REQUIRED, \"minimum number of threads to spawn\");\n"
1209             "\tcmd_AddParm(ts, \"-highThreadCount\", CMD_SINGLE, CMD_REQUIRED, \"maximum number of threads to spawn\");\n"
1210             "\tcmd_AddParm(ts, \"-serverPort\", CMD_SINGLE, CMD_REQUIRED, \"port that server is using\");\n"
1211             "}\n" "int main(int argc, char **argv) {\n" "\tint code;\n"
1212             "\tinitialize_CMD_error_table();\n" "\tSetupRunCmd();\n"
1213             "\tcode = cmd_Dispatch(argc, argv);\n" "\treturn(code);\n" "}\n");
1214 }
1215
1216 /*
1217  * ProcessCmdLine -- processes the command line args
1218  */
1219 PRIVATE void
1220 ProcessCmdLine(int argc, char **argv, char **serverName, char **ipFileName,
1221                char **outputDir)
1222 {
1223     if (argc == 1) {
1224         PrintShortUsage;
1225         exit(1);
1226     }
1227     /* command line processing */
1228     while (--argc > 0) {
1229         if ((*++argv)[0] == '-') {
1230             switch ((*argv)[1]) {
1231
1232             case 'f':
1233             case 'F':           /* input table file */
1234                 *ipFileName = *++argv;
1235                 --argc;
1236                 break;
1237             case 'h':           /* display help */
1238             case 'H':
1239                 PrintLongUsage;
1240                 exit(0);
1241                 break;
1242             case 'l':
1243             case 'L':           /* use LWP threads */
1244                 threadModel = LWPS;
1245                 break;
1246             case 's':
1247             case 'S':           /* serverName */
1248                 *serverName = *++argv;
1249                 /* need 8 char file name, and so truncate the server name */
1250                 if ((int)strlen(*serverName) > MAX_SERV_NAME)
1251                     *(*serverName + MAX_SERV_NAME) = '\0';
1252                 --argc;
1253                 break;
1254             case 'o':
1255             case 'O':
1256                 *outputDir = *++argv;
1257                 --argc;
1258                 break;
1259             case 'p':
1260             case 'P':
1261                 if (strcmp(*++argv, "NT"))
1262                     platform = unix_symbols;
1263                 --argc;
1264                 break;
1265             default:
1266                 PrintLongUsage;
1267                 exit(1);
1268                 break;
1269             }
1270         } else {
1271             PrintShortUsage;
1272             exit(1);
1273         }
1274     }
1275     if (!*serverName)
1276         FATAL("Please set server name using -s switch\n");
1277 }
1278
1279
1280 void
1281 main(int argc, char **argv)
1282 {
1283     FILE *table_h, *srv_h, *xg_h, *clt_h, *mak_h;
1284     int i, j;
1285     rpcArgs args;
1286     char *name, *ifName;
1287     char *serverName = NULL;
1288     char *ipFileName = NULL;
1289     char *outputDir = NULL;
1290     int sign_no = 0, start_no, srv_no;
1291
1292     ProcessCmdLine(argc, argv, &serverName, &ipFileName, &outputDir);
1293
1294     /* open input file */
1295     table_h = fopen(ipFileName, "r");
1296     MEM_CHK(table_h, "main: Unable to open input file\n");
1297
1298     srv_no = 1;
1299     start_no = sign_no;
1300
1301     /*
1302      * open the first set of output files
1303      */
1304
1305     name = GetName(serverName, srv_no);
1306
1307     srv_h = OpenOutFile(outputDir, name, "Srv.c");
1308     xg_h = OpenOutFile(outputDir, name, ".xg");
1309     clt_h = OpenOutFile(outputDir, name, "Clt.c");
1310     mak_h = OpenOutFile(outputDir, name, ".mak");
1311
1312     WriteXGHeader(serverName, xg_h, srv_no);
1313     WriteServHeader(srv_h, serverName, srv_no);
1314     WriteCltHeader(serverName, srv_no, clt_h);
1315     WriteMake(serverName, srv_no, mak_h);
1316
1317     ifName = name;
1318
1319     /* read the table */
1320     while (fscanf(table_h, "%d", &(args.argCount)) != EOF) {
1321
1322         /* increment signature number 8.3 format-- only 10^7 dif sign */
1323         sign_no++;
1324         if (sign_no > 1.0e+7)
1325             FATAL("Max no: of signatures overflow\n");
1326
1327         /* allocate for the arg struct */
1328         args.argDescr =
1329             (arg_tuple *) calloc(args.argCount, sizeof(arg_tuple));
1330         MEM_CHK(args.argDescr, "main: Out of memory -- args.argDescr\n");
1331
1332         /* pick out the dirs and the types */
1333         for (i = 0; i < args.argCount; i++) {
1334             if (!fscanf
1335                 (table_h, " ( %s %s )", args.argDescr[i].direction,
1336                  args.argDescr[i].type)) {
1337                 FATAL("main: Incorrect input file format\n");
1338             }
1339         }
1340
1341         /*
1342          * switch files when we hit TESTS_PER_FILE
1343          */
1344         if (sign_no - start_no >= TESTS_PER_FILE) {
1345             /*
1346              * Finish up the current files
1347              */
1348             WriteServTrailer(srv_h);
1349             WriteCltTrailer(serverName, start_no, sign_no, clt_h);
1350             fclose(xg_h);
1351             fclose(srv_h);
1352             fclose(clt_h);
1353             fclose(mak_h);
1354
1355             /*
1356              * Open the next set of output files
1357              */
1358
1359             srv_no++;
1360             free(ifName);
1361             name = GetName(serverName, srv_no);
1362
1363             srv_h = OpenOutFile(outputDir, name, "Srv.c");
1364             xg_h = OpenOutFile(outputDir, name, ".xg");
1365             clt_h = OpenOutFile(outputDir, name, "Clt.c");
1366             mak_h = OpenOutFile(outputDir, name, ".mak");
1367             WriteXGHeader(serverName, xg_h, srv_no);
1368             WriteServHeader(srv_h, serverName, srv_no);
1369             WriteCltHeader(serverName, srv_no, clt_h);
1370             WriteMake(serverName, srv_no, mak_h);
1371
1372             start_no = sign_no;
1373             ifName = name;
1374         }
1375
1376         /* initialize parameter values */
1377         for (i = 0; i < args.argCount; i++) {
1378             for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++) {
1379                 args.argDescr[i].inValue[j] = NULL;
1380                 args.argDescr[i].inValue2[j] = NULL;
1381                 args.argDescr[i].outValue[j] = NULL;
1382                 args.argDescr[i].outValue2[j] = NULL;
1383             }
1384         }
1385         GenParamValues(&args);
1386
1387         /* write rpc desc into body of the interface */
1388         WriteXG(&args, xg_h, serverName, sign_no);
1389
1390         /* write the rpc into the manager file */
1391         WriteServC(&args, srv_h, serverName, sign_no);
1392
1393         /* write out ITL test */
1394         WriteClt(&args, serverName, sign_no, clt_h);
1395
1396         /* free saved values */
1397         for (i = 0; i < args.argCount; i++) {
1398             for (j = 0; j < IDL_FIX_ARRAY_SIZE; j++) {
1399                 if (args.argDescr[i].inValue[j])
1400                     free(args.argDescr[i].inValue[j]);
1401                 if (args.argDescr[i].inValue2[j])
1402                     free(args.argDescr[i].inValue2[j]);
1403                 if (args.argDescr[i].outValue[j])
1404                     free(args.argDescr[i].outValue[j]);
1405                 if (args.argDescr[i].outValue2[j])
1406                     free(args.argDescr[i].outValue2[j]);
1407             }
1408         }
1409         free(args.argDescr);
1410     }
1411
1412     WriteServTrailer(srv_h);
1413     WriteCltTrailer(serverName, start_no, (sign_no + 1), clt_h);
1414
1415     fclose(clt_h);
1416
1417     fclose(table_h);
1418     fclose(xg_h);
1419     fclose(srv_h);
1420     fclose(mak_h);
1421
1422     /*
1423      * create 1 makefile that drives all the rest
1424      */
1425
1426     mak_h = OpenOutFile(outputDir, "Makefile", "");
1427     fprintf(mak_h, "\ntest:all\ntests:all\nall:\n");
1428     fprintf(mak_h, "%s", platform[8]);
1429     for (i = 1; i <= srv_no; i++)
1430         fprintf(mak_h, "\t%s %s%d.mak %s\n", platform[0], serverName, i,
1431                 platform[5]);
1432     fprintf(mak_h, "\nclean:\n");
1433     for (i = 1; i <= srv_no; i++)
1434         fprintf(mak_h, "\t%s %s%d.mak clean\n", platform[0], serverName, i);
1435     fclose(mak_h);
1436
1437     exit(0);
1438 }