1 /* spu -- A program to make lots of random C/C++ code.
2 Copyright (C) 1993, 1994, 2000 Free Software Foundation, Inc.
3 Contributed by Cygnus Support. Written by Stan Shebs.
5 This file is part of SPU.
7 SPU is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2, or (at your option)
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; see the file COPYING. If not, write to
19 the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */
21 /* This is a random program generator. */
28 char *version_string = "0.3";
30 /* These values are the builtin defaults, mainly useful for testing
31 purposes, or if the user is uninterested in setting a value. */
33 #define DEFAULT_NUM_FILES 5
35 #define DEFAULT_NUM_HEADER_FILES 1
37 #define DEFAULT_NUM_MACROS 10
39 #define DEFAULT_NUM_LIB_MACROS 30
41 #define DEFAULT_MAX_MACRO_ARGS 5
43 #define DEFAULT_NUM_ENUMS 10
45 #define DEFAULT_NUM_LIB_ENUMS 30
47 #define DEFAULT_NUM_ENUMERATORS 10
49 #define DEFAULT_NUM_STRUCTS 10
51 #define DEFAULT_NUM_LIB_STRUCTS 30
53 #define DEFAULT_NUM_FIELDS 20
55 #define DEFAULT_NUM_FUNCTIONS 100
57 #define DEFAULT_NUM_LIB_FUNCTIONS 300
59 #define DEFAULT_MAX_FUNCTION_ARGS 8
61 #define DEFAULT_FUNCTION_LENGTH 20
63 #define DEFAULT_FUNCTION_DEPTH 3
65 #define DEFAULT_LIB_PERCENT 10
67 /* Generic hash table. */
72 struct hash_entry *next;
77 struct hash_entry *entries[253];
89 struct enumerator_desc
98 struct enumerator_desc *enumerators;
112 struct field_desc *fields;
116 /* (should add unions as type of struct) */
133 struct arg_desc *args;
142 /* Function declarations. */
144 void display_usage (void);
146 int hash_string (char *str);
148 struct hash_entry *get_hash_entry (void);
150 char *add_to_hash_table (char *buf, struct hash_table *table);
152 char *get_from_hash_table (char *buf, struct hash_table *table);
154 void init_xrandom (int seed);
158 int probability (int prob);
160 char *copy_string (char *str);
162 char *xmalloc (int n);
164 char *gen_unique_global_name (char *root, int upcase);
166 void gen_random_global_name (char *root, char *namebuf);
168 char *gen_random_local_name (int n, char **others);
170 void create_macros (void);
172 void create_macro (struct macro_desc *macrodesc);
174 char *gen_new_macro_name (void);
176 void create_enums (void);
178 void create_enum (struct enum_desc *enumdesc);
180 char *gen_random_enumerator_name (void);
182 void create_structs (void);
184 void create_struct (struct struct_desc *structdesc);
186 char *gen_random_field_name (int n);
188 void create_functions (void);
190 void create_function (struct function_desc *fndesc);
192 void write_header_file (int n);
194 void write_lib_header_file (void);
196 void write_source_file (int n);
198 void write_macro (FILE *fp, struct macro_desc *macrodesc);
200 void write_enum (FILE *fp, struct enum_desc *enumdesc);
202 void write_struct (FILE *fp, struct struct_desc *structdesc);
204 void write_function_decl (FILE *fp, struct function_desc *functiondesc);
206 void write_function (FILE *fp, int n);
208 void write_lib_function (FILE *fp, int n);
210 void write_statement (FILE *fp, int depth, int max_depth);
212 void write_expression (FILE *fp, int depth, int max_depth);
214 void write_makefile (void);
216 /* Global variables. */
218 /* The possible languages. */
220 enum languages { knr, c, cpp, objc };
222 enum languages language = c;
224 /* Filename extensions to use with each language type. */
226 char *extensions[] = { "c", "c", "cc", "m" };
228 int num_files = DEFAULT_NUM_FILES;
230 int num_header_files = DEFAULT_NUM_HEADER_FILES;
232 char *file_base_name = "file";
234 int num_macros = DEFAULT_NUM_MACROS;
236 int num_lib_macros = DEFAULT_NUM_LIB_MACROS;
238 int num_enums = DEFAULT_NUM_ENUMS;
240 int num_lib_enums = DEFAULT_NUM_LIB_ENUMS;
242 int num_enumerators = DEFAULT_NUM_ENUMERATORS;
244 int num_structs = DEFAULT_NUM_STRUCTS;
246 int num_lib_structs = DEFAULT_NUM_LIB_STRUCTS;
248 int num_fields = DEFAULT_NUM_FIELDS;
250 int num_functions = DEFAULT_NUM_FUNCTIONS;
252 int num_lib_functions = DEFAULT_NUM_LIB_FUNCTIONS;
254 int max_function_args = DEFAULT_MAX_FUNCTION_ARGS;
256 int function_length = DEFAULT_FUNCTION_LENGTH;
258 int function_depth = DEFAULT_FUNCTION_DEPTH;
260 /* Percentage of library constructs that will be referenced. */
262 int lib_percent = DEFAULT_LIB_PERCENT;
264 int num_functions_per_file;
266 /* The amount of commenting in the source. */
270 /* Hash table for globally visible symbols. */
272 struct hash_table *global_hash_table;
274 /* The seed for the random number generator. */
278 /* Space to record info about generated constructs. */
280 struct macro_desc *macros;
282 struct macro_desc *lib_macros;
284 struct enum_desc *enums;
286 struct enum_desc *lib_enums;
288 struct struct_desc *structs;
290 struct struct_desc *lib_structs;
292 struct function_desc *functions;
294 struct function_desc *lib_functions;
296 int num_computer_terms;
298 /* Likely words to appear in names of things. These must never be
299 valid C/C++ keywords, since they may appear by themselves in some
302 char *computerese[] = {
303 "add", "all", "alloc", "allocate", "area", "array", "at",
305 "count", "create", "cull",
306 "del", "delete_", "desc", "discard", "dismiss",
307 "fill", "find", "fn", "for_",
309 "last", "line", "lis", "list", "lose",
310 "make", "mod", "modify", "more",
311 "new_", "node", "null", "num",
314 "ob", "obj", "object", "of",
315 "pnt", "point", "pos", "position",
316 "rect", "rectangle", "remove", "reset",
317 "see", "set", "shape", "str",
319 "vary", "vec", "vect", "vector", "virt", "virtual_",
320 "win", "wind", "window",
325 /* Return a word that commonly appears in programs. */
328 random_computer_word (void)
330 if (num_computer_terms == 0)
334 for (i = 0; computerese[i] != NULL; ++i)
336 num_computer_terms = i;
338 return computerese[xrandom (num_computer_terms)];
342 main (int argc, char **argv)
348 /* Parse all the arguments. */
349 /* (should check on numeric values) */
350 for (i = 1; i < argc; ++i)
353 if (strcmp(arg, "--basename") == 0)
355 file_base_name = copy_string(argv[++i]);
357 else if (strcmp(arg, "--comments") == 0)
359 num = strtol (argv[++i], NULL, 10);
362 else if (strcmp(arg, "--enums") == 0)
364 num = strtol (argv[++i], NULL, 10);
367 else if (strcmp(arg, "--enumerators") == 0)
369 num = strtol (argv[++i], NULL, 10);
370 num_enumerators = num;
372 else if (strcmp(arg, "--fields") == 0)
374 num = strtol (argv[++i], NULL, 10);
377 else if (strcmp(arg, "--files") == 0)
379 num = strtol (argv[++i], NULL, 10);
382 else if (strcmp(arg, "--functions") == 0)
384 num = strtol (argv[++i], NULL, 10);
387 else if (strcmp(arg, "--function-length") == 0)
389 num = strtol (argv[++i], NULL, 10);
390 function_length = num;
392 else if (strcmp(arg, "--function-depth") == 0)
394 num = strtol (argv[++i], NULL, 10);
395 function_depth = num;
397 else if (strcmp(arg, "--header-files") == 0)
399 num = strtol (argv[++i], NULL, 10);
400 num_header_files = num;
402 else if (strcmp(arg, "--help") == 0)
407 else if (strcmp(arg, "--language") == 0)
409 if (strcmp (argv[i+1], "c") == 0)
411 else if (strcmp (argv[i+1], "cpp") == 0)
413 else if (strcmp (argv[i+1], "knr") == 0)
415 else if (strcmp (argv[i+1], "objc") == 0)
419 else if (strcmp(arg, "--lib-enums") == 0)
421 num = strtol (argv[++i], NULL, 10);
424 else if (strcmp(arg, "--lib-functions") == 0)
426 num = strtol (argv[++i], NULL, 10);
427 num_lib_functions = num;
429 else if (strcmp(arg, "--lib-macros") == 0)
431 num = strtol (argv[++i], NULL, 10);
432 num_lib_macros = num;
434 else if (strcmp(arg, "--lib-structs") == 0)
436 num = strtol (argv[++i], NULL, 10);
437 num_lib_structs = num;
439 else if (strcmp(arg, "--macros") == 0)
441 num = strtol (argv[++i], NULL, 10);
444 else if (strcmp(arg, "--seed") == 0)
446 num = strtol (argv[++i], NULL, 10);
449 else if (strcmp(arg, "--structs") == 0)
451 num = strtol (argv[++i], NULL, 10);
454 else if (strcmp(arg, "--version") == 0)
456 fprintf (stderr, "SPU program generator version %s\n",
462 fprintf (stderr, "Usage: \"%s\" not valid, ignored\n", arg);
467 /* Create the definitions of objects internally. */
472 /* Round up the number of functions so each file gets the same
474 num_functions_per_file = (num_functions + num_files - 1) / num_files;
475 /* Write out a bunch of files. */
476 printf ("Writing %d header files...\n", num_header_files);
477 for (i = 0; i < num_header_files; ++i)
478 write_header_file (i);
479 write_lib_header_file ();
480 write_lib_source_file ();
481 printf ("Writing %d files...\n", num_files);
482 for (i = 0; i < num_files; ++i)
483 write_source_file (i);
484 /* Write out a makefile. */
486 /* Succeed if we actually wrote out a whole program correctly. */
493 fprintf (stderr, "Usage: spu [ ... options ... ]\n");
494 fprintf (stderr, "\t--basename str (default \"%s\")\n", "file");
495 fprintf (stderr, "\t--comments n\n");
496 fprintf (stderr, "\t--enums n (default %d)\n", DEFAULT_NUM_ENUMS);
497 fprintf (stderr, "\t--enumerators n (default %d)\n", DEFAULT_NUM_ENUMERATORS);
498 fprintf (stderr, "\t--fields n (default %d)\n", DEFAULT_NUM_FIELDS);
499 fprintf (stderr, "\t--files n (default %d)\n", DEFAULT_NUM_FILES);
500 fprintf (stderr, "\t--functions n (default %d)\n", DEFAULT_NUM_FUNCTIONS);
501 fprintf (stderr, "\t--function-length n (default %d)\n", DEFAULT_FUNCTION_LENGTH);
502 fprintf (stderr, "\t--function-depth n (default %d)\n", DEFAULT_FUNCTION_DEPTH);
503 fprintf (stderr, "\t--header-files n (default %d)\n", DEFAULT_NUM_HEADER_FILES);
504 fprintf (stderr, "\t--help\n");
505 fprintf (stderr, "\t--language c|cpp|knr|objc (default c)\n");
506 fprintf (stderr, "\t--lib-enums n (default %d)\n", DEFAULT_NUM_LIB_ENUMS);
507 fprintf (stderr, "\t--lib-functions n (default %d)\n", DEFAULT_NUM_LIB_FUNCTIONS);
508 fprintf (stderr, "\t--lib-macros n (default %d)\n", DEFAULT_NUM_LIB_MACROS);
509 fprintf (stderr, "\t--lib-structs n (default %d)\n", DEFAULT_NUM_LIB_STRUCTS);
510 fprintf (stderr, "\t--macros n (default %d)\n", DEFAULT_NUM_MACROS);
511 fprintf (stderr, "\t--seed n\n");
512 fprintf (stderr, "\t--structs n (default %d)\n", DEFAULT_NUM_STRUCTS);
513 fprintf (stderr, "\t--version\n");
522 /* Given a numbered type, return its name. */
525 name_from_type (int n)
537 /* Create basic definitions of macros. Negative number of arguments
538 means a macros that looks like a constant instead of a function. */
545 printf ("Creating %d macros...\n", num_macros);
547 (struct macro_desc *) xmalloc (num_macros * sizeof(struct macro_desc));
548 for (i = 0; i < num_macros; ++i)
550 create_macro (&(macros[i]));
552 printf ("Creating %d library macros...\n", num_lib_macros);
554 (struct macro_desc *) xmalloc (num_lib_macros * sizeof(struct macro_desc));
555 for (i = 0; i < num_lib_macros; ++i)
557 create_macro (&(lib_macros[i]));
558 if (!probability(lib_percent))
559 lib_macros[i].use = 0;
564 create_macro (struct macro_desc *macrodesc)
568 macrodesc->name = gen_new_macro_name ();
569 numargs = xrandom (DEFAULT_MAX_MACRO_ARGS + 1);
573 macrodesc->args = (char **) xmalloc (numargs * sizeof(char *));
574 for (j = 0; j < numargs; ++j)
576 macrodesc->args[j] = gen_random_local_name (j, NULL);
579 macrodesc->numargs = numargs;
583 /* Generate a macro name. */
586 gen_new_macro_name (void)
588 return gen_unique_global_name ("M", (xrandom (3) > 0));
591 /* Create definitions of the desired number of enums. */
598 printf ("Creating %d enums...\n", num_enums);
600 (struct enum_desc *) xmalloc (num_enums * sizeof(struct enum_desc));
601 for (i = 0; i < num_enums; ++i)
603 create_enum (&(enums[i]));
605 printf ("Creating %d lib_enums...\n", num_lib_enums);
607 (struct enum_desc *) xmalloc (num_lib_enums * sizeof(struct enum_desc));
608 for (i = 0; i < num_lib_enums; ++i)
610 create_enum (&(lib_enums[i]));
611 if (!probability(lib_percent))
612 lib_enums[i].use = 0;
617 create_enum (struct enum_desc *enumdesc)
621 /* Let some enums be anonymous. */
622 if (xrandom (100) < 50)
623 enumdesc->name = gen_unique_global_name (NULL, 0);
624 num = num_enumerators / 2 + xrandom (num_enumerators);
627 enumdesc->enumerators =
628 (struct enumerator_desc *) xmalloc (num * sizeof(struct enumerator_desc));
629 for (j = 0; j < num; ++j)
631 enumdesc->enumerators[j].name = gen_random_enumerator_name ();
633 enumdesc->num_enumerators = j;
637 /* Generate a unique enumerator within an enum. */
640 gen_random_enumerator_name (void)
642 return gen_unique_global_name ("enum", 0);
645 /* Create definitions of the desired number of structures. */
648 create_structs (void)
652 printf ("Creating %d structs...\n", num_structs);
654 (struct struct_desc *) xmalloc (num_structs * sizeof(struct struct_desc));
655 for (i = 0; i < num_structs; ++i)
657 create_struct (&(structs[i]));
659 printf ("Creating %d library structs...\n", num_lib_structs);
661 (struct struct_desc *) xmalloc (num_lib_structs * sizeof(struct struct_desc));
662 for (i = 0; i < num_lib_structs; ++i)
664 create_struct (&(lib_structs[i]));
665 if (!probability(lib_percent))
666 lib_structs[i].use = 0;
671 create_struct (struct struct_desc *structdesc)
675 structdesc->name = gen_unique_global_name (NULL, 0);
676 numf = xrandom (num_fields) + 1;
678 (struct field_desc *) xmalloc (numf * sizeof(struct field_desc));
679 for (j = 0; j < numf; ++j)
681 structdesc->fields[j].type = random_type ();
682 structdesc->fields[j].name = gen_random_field_name (j);
684 structdesc->numfields = numf;
689 gen_random_field_name (int n)
693 /* (should have more variety) */
694 sprintf (namebuf, "field%d", n);
695 return copy_string (namebuf);
698 /* Create a number of functions with random numbers of arguments. */
700 /* (should gen with random arg types also) */
703 create_functions (void)
707 printf ("Creating %d functions...\n", num_functions);
709 (struct function_desc *) xmalloc (num_functions * sizeof(struct function_desc));
710 /* Generate the main program, as the first function. */
711 functions[0].name = "main";
712 functions[0].numargs = 0;
713 /* Generate all the other functions. The bodies don't get created
714 until the functions are being written out. */
715 for (i = 1; i < num_functions; ++i)
717 create_function (&(functions[i]));
720 printf ("Creating %d library functions...\n", num_lib_functions);
722 (struct function_desc *) xmalloc (num_lib_functions * sizeof(struct function_desc));
723 for (i = 0; i < num_lib_functions; ++i)
725 create_function (&(lib_functions[i]));
726 if (!probability(lib_percent))
727 lib_functions[i].use = 0;
731 /* Generate the details of a single function. */
734 create_function (struct function_desc *fndesc)
736 int j, range, numargs;
738 fndesc->name = gen_unique_global_name ("fn", 0);
739 /* Choose the number of arguments, preferring shorter argument
740 lists by using a simple binomial distribution. */
741 range = 2 * (max_function_args + 1);
743 for (j = 0; j < 6; ++j)
744 numargs += xrandom (range + 1);
747 /* Shift distribution so 0 is in the middle. */
748 numargs -= max_function_args;
749 /* Fold negative values over to positive side. */
752 if (numargs > max_function_args)
753 numargs = max_function_args;
755 (struct arg_desc *) xmalloc (numargs * sizeof(struct arg_desc));
756 for (j = 0; j < numargs; ++j)
758 fndesc->args[j].type = 0;
759 fndesc->args[j].name = gen_random_local_name (j, NULL);
761 fndesc->numargs = numargs;
766 write_header_file (int n)
772 sprintf (tmpbuf, "%s%d.h", file_base_name, n);
773 fp = fopen (tmpbuf, "w");
777 fprintf (fp, "/* header */\n");
780 printf ("Writing %d macros...\n", num_macros);
781 for (i = 0; i < num_macros; ++i)
783 write_macro (fp, &(macros[i]));
788 printf ("Writing %d enums...\n", num_enums);
789 printf (" (Each enum contains up to %d values)\n", num_enumerators);
790 for (i = 0; i < num_enums; ++i)
792 write_enum (fp, &(enums[i]));
797 printf ("Writing %d structs...\n", num_structs);
798 printf (" (Each struct contains %d fields)\n", num_fields);
799 for (i = 0; i < num_structs; ++i)
801 write_struct (fp, &(structs[i]));
806 printf ("Writing %d function decls...\n", num_functions);
807 for (i = 0; i < num_functions; ++i)
809 write_function_decl (fp, &(functions[i]));
817 write_lib_header_file (void)
823 sprintf (tmpbuf, "%slib.h", file_base_name);
824 fp = fopen (tmpbuf, "w");
828 fprintf (fp, "/* library header */\n");
831 printf ("Writing %d library macros...\n", num_lib_macros);
832 for (i = 0; i < num_lib_macros; ++i)
834 write_macro (fp, &(lib_macros[i]));
839 printf ("Writing %d library enums...\n", num_lib_enums);
840 printf (" (Each enum contains up to %d values)\n", num_enumerators);
841 for (i = 0; i < num_lib_enums; ++i)
843 write_enum (fp, &(lib_enums[i]));
848 printf ("Writing %d library structs...\n", num_lib_structs);
849 printf (" (Each struct contains %d fields)\n", num_fields);
850 for (i = 0; i < num_lib_structs; ++i)
852 write_struct (fp, &(lib_structs[i]));
857 printf ("Writing %d lib function decls...\n", num_lib_functions);
858 for (i = 0; i < num_lib_functions; ++i)
860 write_function_decl (fp, &(lib_functions[i]));
868 write_macro (FILE *fp, struct macro_desc *macrodesc)
872 fprintf (fp, "#define %s", macrodesc->name);
873 /* Negative # arguments indicates an argumentless macro instead of
874 one with zero arguments. */
875 if (macrodesc->numargs >= 0)
878 for (j = 0; j < macrodesc->numargs; ++j)
882 fprintf (fp, "%s", macrodesc->args[j]);
886 /* Generate a macro body. */
890 fprintf (fp, " \\\n");
892 if (macrodesc->numargs > 0)
894 for (i = 0; i < macrodesc->numargs; ++i)
898 fprintf (fp, " \\\n");
899 fprintf (fp, " (%s)", macrodesc->args[i]);
900 if (xrandom (2) == 0)
903 fprintf (fp, " \\\n");
904 fprintf (fp, " ((int) (%s))", macrodesc->args[i]);
907 fprintf (fp, " \\\n");
911 fprintf (fp, " (1)");
916 fprintf (fp, " (%d)", xrandom (100));
919 fprintf (fp, "\n\n");
922 /* Write out the definition of a enum. */
925 write_enum (FILE *fp, struct enum_desc *enumdesc)
929 fprintf (fp, "enum");
931 fprintf (fp, " %s", enumdesc->name);
933 for (j = 0; j < enumdesc->num_enumerators; ++j)
937 fprintf (fp, "\n %s", enumdesc->enumerators[j].name);
939 fprintf (fp, "\n};\n\n");
942 /* Write out the definition of a structure. */
945 write_struct (FILE *fp, struct struct_desc *structdesc)
949 fprintf (fp, "struct %s {\n", structdesc->name);
950 for (j = 0; j < structdesc->numfields; ++j)
952 fprintf (fp, " %s %s;\n",
953 name_from_type (structdesc->fields[j].type),
954 structdesc->fields[j].name);
956 fprintf (fp, "};\n\n");
960 write_function_decl (FILE *fp, struct function_desc *fndesc)
964 fprintf (fp, "int %s (", fndesc->name);
967 for (i = 0; i < fndesc->numargs; ++i)
969 fprintf (fp, "int %s", fndesc->args[i].name);
970 if (i + 1 < fndesc->numargs)
974 fprintf (fp, ");\n");
977 /* Write a complete source file. */
980 write_source_file (int n)
985 extern unsigned long initial_randstate;
987 sprintf (tmpbuf, "%s%d.%s",
988 file_base_name, n, extensions[language]);
989 fp = fopen (tmpbuf, "w");
993 "/* A fine software product by SPU %s, random seed == %d */\n\n",
994 version_string, (int) initial_randstate);
995 if (1 /*num_lib_header_files*/ > 0)
997 for (j = 0; j < 1 /*num_header_files*/; ++j)
999 fprintf (fp, "#include \"%slib.h\"\n", file_base_name);
1003 if (num_header_files > 0)
1005 for (j = 0; j < num_header_files; ++j)
1007 fprintf (fp, "#include \"%s%d.h\"\n", file_base_name, j);
1013 printf (" (Each file contains %d functions)\n",
1014 num_functions_per_file);
1016 for (j = 0; j < num_functions_per_file; ++j)
1018 write_function (fp, n * num_functions_per_file + j);
1025 write_function (FILE *fp, int n)
1029 fprintf(fp, "int\n%s (", functions[n].name);
1030 for (i = 0; i < functions[n].numargs; ++i)
1032 if (language != knr)
1034 fprintf (fp, "int ");
1036 fprintf (fp, "%s", functions[n].args[i].name);
1037 if (i + 1 < functions[n].numargs)
1041 if (language == knr)
1043 for (i = 0; i < functions[n].numargs; ++i)
1045 fprintf (fp, "int %s;\n", functions[n].args[i].name);
1049 /* Generate a plausible function body by writing a number of
1051 for (k = 0; k < function_length; ++k)
1053 write_statement (fp, 1, function_depth - 1 + xrandom (3));
1055 fprintf (fp, "}\n\n");
1059 write_lib_source_file (void)
1065 sprintf (tmpbuf, "%slib.%s", file_base_name, extensions[language]);
1066 fp = fopen (tmpbuf, "w");
1069 if (1 /*num_lib_header_files*/ > 0)
1071 for (j = 0; j < 1 /*num_header_files*/; ++j)
1073 fprintf (fp, "#include \"%slib.h\"\n", file_base_name);
1078 for (j = 0; j < num_lib_functions; ++j)
1080 write_lib_function (fp, j);
1086 /* Generate empty bodies for library function definitions. */
1089 write_lib_function (FILE *fp, int n)
1093 fprintf (fp, "int\n%s (", lib_functions[n].name);
1094 for (i = 0; i < lib_functions[n].numargs; ++i)
1096 if (language != knr)
1098 fprintf (fp, "int ");
1100 fprintf (fp, "%s", lib_functions[n].args[i].name);
1101 if (i + 1 < lib_functions[n].numargs)
1105 if (!lib_functions[n].use)
1106 fprintf (fp, "/* unused */");
1108 if (language == knr)
1110 for (i = 0; i < lib_functions[n].numargs; ++i)
1112 fprintf (fp, "int %s;\n", lib_functions[n].args[i].name);
1115 fprintf (fp, "{\n");
1116 fprintf (fp, "}\n\n");
1120 write_statement (FILE *fp, int depth, int max_depth)
1124 for (i = 0; i < depth; ++i)
1126 /* Always do non-recursive statements if going too deep. */
1127 if (depth >= max_depth)
1129 write_expression (fp, 0, xrandom(4) + 1);
1130 fprintf (fp, ";\n");
1136 write_expression (fp, 0, xrandom(4) + 1);
1140 fprintf (fp, "if (");
1141 write_expression (fp, 0, xrandom(2) + 1);
1142 fprintf (fp, ") {\n");
1143 write_statement(fp, depth + 1, max_depth);
1144 for (i = 0; i < depth; ++i)
1152 /* Write a single expression. */
1155 write_expression (FILE *fp, int depth, int max_depth)
1159 /* Always do non-recursive statements if going too deep. */
1160 if (depth >= max_depth)
1163 switch (xrandom(10))
1166 fprintf (fp, "%d", xrandom (1000));
1169 fprintf (fp, "%d", xrandom (127));
1174 switch (xrandom(10))
1177 for (j = 0; j < 1000; ++j)
1179 n = xrandom (num_lib_functions);
1180 if (lib_functions[n].use)
1183 if (!lib_functions[n].use)
1185 n = xrandom (num_lib_functions);
1186 fprintf(fp, "%s (", lib_functions[n].name);
1187 for (j = 0; j < lib_functions[n].numargs; ++j)
1191 write_expression(fp, depth + 1, max_depth - 1);
1196 n = xrandom (num_functions);
1197 fprintf(fp, "%s (", functions[n].name);
1198 for (j = 0; j < functions[n].numargs; ++j)
1202 write_expression(fp, depth + 1, max_depth - 1);
1208 for (j = 0; j < 1000; ++j)
1210 n = xrandom (num_lib_macros);
1211 if (lib_macros[n].use)
1214 if (!lib_macros[n].use)
1216 fprintf(fp, "%s", lib_macros[n].name);
1217 if (lib_macros[n].numargs >= 0)
1220 for (j = 0; j < lib_macros[n].numargs; ++j)
1224 write_expression(fp, depth + 1, max_depth - 1);
1230 n = xrandom (num_macros);
1231 fprintf(fp, "%s", macros[n].name);
1232 if (macros[n].numargs >= 0)
1235 for (j = 0; j < macros[n].numargs; ++j)
1239 write_expression(fp, depth + 1, max_depth - 1);
1245 write_expression (fp, depth + 1, max_depth);
1246 fprintf (fp, " + ");
1247 write_expression (fp, depth + 1, max_depth);
1250 write_expression (fp, depth + 1, max_depth);
1251 fprintf (fp, " - ");
1252 write_expression (fp, depth + 1, max_depth);
1255 write_expression (fp, depth + 1, max_depth);
1256 fprintf (fp, " * ");
1257 write_expression (fp, depth + 1, max_depth);
1260 n = xrandom (num_enums);
1261 n2 = xrandom (enums[n].num_enumerators);
1262 fprintf (fp, "%s", enums[n].enumerators[n2].name);
1265 fprintf (fp, "%d", xrandom (127));
1270 /* Write out a makefile that will compile the program just generated. */
1273 write_makefile (void)
1279 sprintf (tmpbuf, "%s.mk", file_base_name);
1280 fp = fopen (tmpbuf, "w");
1283 /* Name the compiler so we can change it easily. */
1284 fprintf (fp, "CC = cc\n\n");
1285 /* Write dependencies and action line for the executable. */
1286 fprintf (fp, "%s: ", file_base_name);
1287 for (i = 0; i < num_files; ++i)
1288 fprintf (fp, " %s%d.o", file_base_name, i);
1289 fprintf (fp, " %slib.o", file_base_name);
1291 fprintf (fp, "\t$(CC) -o %s.out", file_base_name);
1292 for (i = 0; i < num_files; ++i)
1293 fprintf (fp, " %s%d.o", file_base_name, i);
1294 fprintf (fp, " %slib.o", file_base_name);
1295 fprintf (fp, "\n\n");
1296 /* Write dependencies for individual files. */
1297 for (i = 0; i < num_files; ++i)
1299 fprintf (fp, " %s%d.o: %s%d.%s",
1300 file_base_name, i, file_base_name, i,
1301 extensions[language]);
1302 for (j = 0; j < num_header_files; ++j)
1303 fprintf (fp, " %s%d.h", file_base_name, j);
1305 fprintf (fp, "\t$(CC) -c %s%d.%s\n",
1306 file_base_name, i, extensions[language]);
1308 fprintf (fp, " %slib.o: %slib.%s %slib.h",
1309 file_base_name, file_base_name, extensions[language],
1312 fprintf (fp, "\t$(CC) -c %slib.%s\n",
1313 file_base_name, extensions[language]);
1319 /* Utility/general functions. */
1322 gen_unique_global_name (char *root, int upcase)
1325 char *str, namebuf[100];
1327 if (global_hash_table == NULL)
1330 (struct hash_table *) xmalloc (sizeof (struct hash_table));
1333 /* Keep trying until we get a unique name. */
1334 for (i = 0; i < 100; ++i)
1336 gen_random_global_name (root, namebuf);
1339 for (j = 0; namebuf[j] != '\0'; ++j)
1340 namebuf[j] = toupper (namebuf[j]);
1342 if (get_from_hash_table (namebuf, global_hash_table) == NULL)
1344 str = add_to_hash_table (namebuf, global_hash_table);
1350 fprintf (stderr, "Can't get a unique name!\n");
1357 gen_random_global_name (char *root, char *namebuf)
1363 switch (xrandom (4))
1366 namebuf[0] = 'a' + xrandom (26);
1370 /* Convert a random number into a string, maybe with some
1371 underscores thrown in for flavor. */
1372 n = xrandom (10000);
1376 if (xrandom(6) == 0)
1378 namebuf[i++] = 'a' + (n % 26);
1384 strcat (namebuf, random_computer_word ());
1389 strcat (namebuf, "_");
1390 strcat (namebuf, root);
1392 switch (xrandom (4))
1395 strcat (namebuf, "_");
1396 len = strlen (namebuf);
1397 namebuf[len] = 'a' + xrandom (26);
1398 namebuf[len + 1] = '\0';
1401 strcat (namebuf, "_");
1402 sprintf (smallbuf, "%d", xrandom (10000));
1403 strcat (namebuf, smallbuf);
1406 strcat (namebuf, "_");
1407 strcat (namebuf, random_computer_word ());
1412 /* Generate a local variable name. */
1415 gen_random_local_name (int numothers, char **others)
1419 sprintf (namebuf, "%s%d",
1420 (xrandom (2) == 0 ? random_computer_word () : "arg"),
1422 return copy_string (namebuf);
1425 /* Generic hash table code. */
1428 hash_string (char *str)
1433 for (i = 0; str[i] != '\0'; ++i)
1442 get_hash_entry (void)
1444 return (struct hash_entry *) xmalloc (sizeof (struct hash_entry));
1448 add_to_hash_table (char *buf, struct hash_table *table)
1451 struct hash_entry *ent, *lastent;
1456 hash = hash_string (buf);
1457 if (table->entries[hash] == NULL)
1459 table->entries[hash] = get_hash_entry ();
1460 table->entries[hash]->val = copy_string (buf);
1461 return table->entries[hash]->val;
1465 for (ent = table->entries[hash]; ent != NULL; ent = ent->next)
1467 if (ent->val == NULL)
1469 if (strcmp (buf, ent->val) == 0)
1473 if (lastent != NULL)
1475 lastent->next = get_hash_entry ();
1476 lastent->next->val = copy_string (buf);
1477 return lastent->next->val;
1480 /* should never happen */
1485 get_from_hash_table (char *buf, struct hash_table *table)
1488 struct hash_entry *ent, *lastent;
1492 hash = hash_string (buf);
1493 if (table->entries[hash] == NULL)
1499 for (ent = table->entries[hash]; ent != NULL; ent = ent->next)
1501 if (ent->val == NULL)
1503 if (strcmp (buf, ent->val) == 0)
1507 if (lastent != NULL)
1512 /* should never happen */
1518 /* Random number handling is important but terrible/nonexistent in
1519 some systems. Do it ourselves. Also, this will give repeatable
1520 results across multiple platforms, which is important if this is
1521 being used to generate test cases. */
1523 /* The random state *must* be at least 32 bits. */
1525 unsigned long initial_randstate = 0;
1527 unsigned long randstate = 0;
1529 /* Seed can come from elsewhere, for repeatability. Otherwise, it comes
1530 from the current time, scaled down to where 32-bit arithmetic won't
1534 init_xrandom (int seed)
1540 /* If the random state is already set, changes are somewhat
1544 fprintf (stderr, "Randstate being changed from %lu to %d\n",
1554 /* Whatever its source, put the randstate into known range (0 - 99999). */
1555 randstate = abs (randstate);
1556 randstate %= 100000L;
1557 /* This is kept around for the sake of error reporting. */
1558 initial_randstate = randstate;
1561 /* Numbers lifted from Numerical Recipes, p. 198. */
1562 /* Arithmetic must be 32-bit. */
1567 randstate = (8121 * randstate + 28411) % 134456L;
1568 return ((m * randstate) / 134456L);
1571 /* Percentage probability, with bounds checking. */
1574 probability(int prob)
1580 return (xrandom(100) < prob);
1586 char *value = (char *) malloc (amt);
1590 /* This is pretty serious, have to get out quickly. */
1591 fprintf (stderr, "Memory exhausted!!\n");
1594 /* Save callers from having to clear things themselves. */
1595 memset (value, 0, amt);
1599 /* Copy a string to newly-allocated space. The new space is never
1603 copy_string (char *str)
1605 int len = strlen (str);
1608 rslt = xmalloc (len + 1);