home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gdb-4.16-base.tgz / gdb-4.16-base.tar / fsf / gdb / utils / spu / spu.c < prev   
C/C++ Source or Header  |  1994-06-27  |  19KB  |  934 lines

  1. /* spu -- A program to make lots of random C code.
  2.    Copyright (C) 1993, 1994 Free Software Foundation, Inc.
  3.    Contributed by Cygnus Support.  Written by Stan Shebs.
  4.  
  5. This file is part of SPU.
  6.  
  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)
  10. any later version.
  11.  
  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.
  16.  
  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.  */
  20.  
  21. /* This is a random program generator. */
  22.  
  23. #include <stdio.h>
  24.  
  25. #include "ansidecl.h"
  26.  
  27. /* The limits on these could be eliminated, but that would be
  28.    some work.  As they stand, the limits are enough to generate
  29.    some truly enormous programs...  */
  30.  
  31. #define MAXMACROS 50000
  32. #define MAXMARGS 6
  33. #define MAXSTRUCTS 1000
  34. #define MAXSLOTS 20
  35. #define MAXFUNCTIONS 50000
  36. #define MAXFARGS 6
  37.  
  38. struct macro_desc {
  39.   char *name;
  40.   int numargs;
  41.   char *args[MAXMARGS];
  42. };
  43.  
  44. struct slot_desc {
  45.   char *name;
  46. };
  47.  
  48. struct struct_desc {
  49.   char *name;
  50.   int numslots;
  51.   struct slot_desc slots[MAXSLOTS];
  52. };
  53.  
  54. /* (should add unions as type of struct) */
  55.  
  56. struct type_desc {
  57.   char *name;
  58. };
  59.  
  60. struct function_desc {
  61.   char *name;
  62.   int numargs;
  63.   char *args[MAXFARGS];
  64. };
  65.  
  66. struct file_desc {
  67.   char *name;
  68. };
  69.  
  70. void
  71. display_usage PARAMS ((void));
  72.  
  73. void
  74. init_xrandom PARAMS ((int seed));
  75.  
  76. int
  77. xrandom PARAMS ((int n));
  78.  
  79. char *
  80. copy_string PARAMS ((char *str));
  81.  
  82. char *
  83. xmalloc PARAMS ((int n));
  84.  
  85. char *
  86. gen_new_macro_name PARAMS ((int n));
  87.  
  88. char *
  89. gen_random_name PARAMS ((char *root));
  90.  
  91. char *
  92. gen_random_local_name PARAMS ((int n, char **others));
  93.  
  94. void
  95. write_struct PARAMS ((FILE *fp, int n));
  96.  
  97. void
  98. create_structs PARAMS ((void));
  99.  
  100. void
  101. create_macros PARAMS ((void));
  102.  
  103. void
  104. create_functions PARAMS ((void));
  105.  
  106. void
  107. write_header_file PARAMS ((int n));
  108.  
  109. void
  110. write_source_file PARAMS ((int n));
  111.  
  112. void
  113. write_macro PARAMS ((FILE *fp, int n));
  114.  
  115. void
  116. write_function_decl PARAMS ((FILE *fp, int n));
  117.  
  118. void
  119. write_function PARAMS ((FILE *fp, int n));
  120.  
  121. void
  122. write_statement PARAMS ((FILE *fp, int depth, int max_depth));
  123.  
  124. void
  125. write_expression PARAMS ((FILE *fp, int depth, int max_depth));
  126.  
  127. void
  128. write_makefile PARAMS ((void));
  129.  
  130. /* The default values are set low for testing purposes.
  131.    Real values can get much larger. */
  132.  
  133. int numfiles = 5;
  134. int numheaderfiles = 1;
  135.  
  136. char *file_base_name = "file";
  137.  
  138. int nummacros = 1000;
  139.  
  140. int numstructs = 20;
  141. int numslots = MAXSLOTS;
  142.  
  143. int numfunctions = 100;
  144.  
  145. int function_length = 20;
  146.  
  147. int num_functions_per_file;
  148.  
  149. /* The amount of commenting in the source. */
  150.  
  151. int commenting = 0;
  152.  
  153. struct macro_desc macros[MAXMACROS];
  154.  
  155. struct struct_desc structs[MAXSTRUCTS];
  156.  
  157. struct function_desc functions[MAXFUNCTIONS];
  158.  
  159. int num_computer_terms;
  160.  
  161. /* Likely words to appear in names of things. */
  162.  
  163. char *computerese[] = {
  164.   "make",
  165.   "create",
  166.   "alloc",
  167.   "modify",
  168.   "delete",
  169.   "new",
  170.   "add",
  171.   "list",
  172.   "array",
  173.   "queue",
  174.   "object",
  175.   "of",
  176.   "by",
  177.   "point",
  178.   "line",
  179.   "rectangle",
  180.   "shape",
  181.   "area",
  182.   "window",
  183.   "null",
  184.   NULL
  185. };
  186.  
  187. /* Return a word that commonly appears in programs. */
  188.  
  189. char *
  190. computer_word ()
  191. {
  192.   if (num_computer_terms == 0)
  193.     {
  194.       int i;
  195.  
  196.       for (i = 0; computerese[i] != NULL; ++i) ;
  197.       num_computer_terms = i;
  198.     }
  199.   return computerese[xrandom (num_computer_terms)];
  200. }
  201.  
  202. main (argc, argv)
  203.      int argc;
  204.      char **argv;
  205. {
  206.   int i, num;
  207.   char *arg;
  208.   FILE *fp;
  209.  
  210.   /* Parse all the arguments. */
  211.   /* (should check on numeric values) */
  212.   for (i = 1; i < argc; ++i)
  213.     {
  214.       arg = argv[i];
  215.       if (strcmp(arg, "--comments") == 0)
  216.     {
  217.       num = strtol (argv[++i], NULL, 10);
  218.       commenting = num;
  219.     }
  220.       else if (strcmp(arg, "--files") == 0)
  221.     {
  222.       num = strtol (argv[++i], NULL, 10);
  223.       numfiles = num;
  224.     }
  225.       else if (strcmp(arg, "--functions") == 0)
  226.     {
  227.       num = strtol (argv[++i], NULL, 10);
  228.       numfunctions = num;
  229.     }
  230.       else if (strcmp(arg, "--function-length") == 0)
  231.     {
  232.       num = strtol (argv[++i], NULL, 10);
  233.       function_length = num;
  234.     }
  235.       else if (strcmp(arg, "--function-depth") == 0)
  236.     {
  237.       num = strtol (argv[++i], NULL, 10);
  238.       /* (should use this!) */
  239.     }
  240.       else if (strcmp(arg, "--header-files") == 0)
  241.     {
  242.       num = strtol (argv[++i], NULL, 10);
  243.       numheaderfiles = num;
  244.     }
  245.       else if (strcmp(arg, "--help") == 0)
  246.     {
  247.       display_usage ();
  248.       exit (0);
  249.     }
  250.       else if (strcmp(arg, "--macros") == 0)
  251.     {
  252.       num = strtol (argv[++i], NULL, 10);
  253.       nummacros = num;
  254.     }
  255.       else if (strcmp(arg, "--slots") == 0)
  256.     {
  257.       num = strtol (argv[++i], NULL, 10);
  258.       numslots = num;
  259.     }
  260.       else if (strcmp(arg, "--structs") == 0)
  261.     {
  262.       num = strtol (argv[++i], NULL, 10);
  263.       numstructs = num;
  264.     }
  265.       else if (strcmp(arg, "--version") == 0)
  266.     {
  267.       fprintf (stderr, "SPU program generator version 0.1\n");
  268.       exit (0);
  269.     }
  270.       else
  271.     {
  272.       fprintf (stderr, "Usage: \"%s\" not valid, ignored\n", arg);
  273.       display_usage ();
  274.     }
  275.     }
  276.   init_xrandom (-1);
  277.   /* Create the definitions of objects internally. */
  278.   create_macros ();
  279.   create_structs ();
  280.   create_functions ();
  281.   num_functions_per_file = numfunctions / numfiles;
  282.   /* Write out a bunch of files. */
  283.   printf ("Writing %d header files...\n", numheaderfiles);
  284.   for (i = 0; i < numheaderfiles; ++i)
  285.     write_header_file (i);
  286.   printf ("Writing %d files...\n", numfiles);
  287.   for (i = 0; i < numfiles; ++i)
  288.     write_source_file (i);
  289.   /* Write out a makefile. */
  290.   write_makefile ();
  291.   /* Succeed if we actually wrote out a whole program correctly. */
  292.   exit (0);
  293. }
  294.  
  295. void
  296. display_usage ()
  297. {
  298.   fprintf (stderr, "Usage: spu [ ... options ... ]\n");
  299.   fprintf (stderr, "           --comments <n>\n");
  300.   fprintf (stderr, "           --files <n>\n");
  301.   fprintf (stderr, "           --functions <n>\n");
  302.   fprintf (stderr, "           --function-length <n>\n");
  303.   fprintf (stderr, "           --function-depth <n>\n");
  304.   fprintf (stderr, "           --help\n");
  305.   fprintf (stderr, "           --macros <n>\n");
  306.   fprintf (stderr, "           --slots <n>\n");
  307.   fprintf (stderr, "           --structs <n>\n");
  308.   fprintf (stderr, "           --version\n");
  309. }
  310.  
  311. int
  312. create_type (str)
  313. char *str;
  314. {
  315.   int i;
  316.  
  317.   return 1;
  318. }
  319.  
  320. int
  321. random_type ()
  322. {
  323.   return 1;
  324. }
  325.  
  326. char *
  327. name_from_type (n)
  328.      int n;
  329. {
  330.   return "int";
  331. }
  332.  
  333. /* Generate a macro name that is unique if the given n is unique. */
  334.  
  335. char *
  336. gen_new_macro_name (n)
  337.      int n;
  338. {
  339.   int i = 0;
  340.   char namebuf[100];
  341.  
  342.   ++n;
  343.   namebuf[i] = '\0';
  344.   strcat (namebuf, computer_word ());
  345.   i = strlen (namebuf);
  346.   namebuf[i++] = '_';
  347.   namebuf[i++] = 'M';
  348.   while (n > 0)
  349.     {
  350.       namebuf[i++] = 'a' + (n % 26);
  351.       n /= 26;
  352.     }
  353.   namebuf[i] = '\0';
  354.   return copy_string (namebuf);
  355. }
  356.  
  357. /* Create basic definitions of macros. */
  358.  
  359. void
  360. create_macros()
  361. {
  362.   int i, j, numargs;
  363.  
  364.   printf ("Creating %d macros...\n", nummacros);
  365.   for (i = 0; i < nummacros; ++i)
  366.     {
  367.       macros[i].name = gen_new_macro_name (i);
  368.       numargs = xrandom (MAXMARGS + 1);
  369.       for (j = 0; j < numargs; ++j)
  370.     {
  371.       macros[i].args[j] = gen_random_local_name(j, NULL);
  372.     }
  373.       macros[i].numargs = numargs;
  374.     }
  375. }
  376.  
  377. /* Generate a unique structure name, based on the number n. */
  378.  
  379. char *
  380. gen_new_struct_name (n)
  381.      int n;
  382. {
  383.   int i = 0;
  384.   char namebuf[100];
  385.  
  386.   ++n;
  387.   namebuf[i++] = 's';
  388.   namebuf[i++] = '_';
  389.   while (n > 0)
  390.     {
  391.       namebuf[i++] = 'a' + (n % 26);
  392.       n /= 26;
  393.     }
  394.   namebuf[i] = '\0';
  395.   if (xrandom (4) == 0)
  396.     strcat (namebuf, "_struct");
  397.   return copy_string (namebuf);
  398. }
  399.  
  400. char *
  401. gen_random_slot_name (n)
  402.      int n;
  403. {
  404.   char namebuf[100];
  405.  
  406.   /* (should have more variety) */
  407.   sprintf (namebuf, "slot%d", n);
  408.   return copy_string (namebuf);
  409. }
  410.  
  411. /* Create definitions of the desired number of structures. */
  412.  
  413. void
  414. create_structs()
  415. {
  416.   int i, j;
  417.  
  418.   printf ("Creating %d structs...\n", numstructs);
  419.   for (i = 0; i < numstructs; ++i)
  420.     {
  421.       structs[i].name = gen_new_struct_name(i);
  422.       for (j = 0; j < 20; ++j)
  423.     {
  424.       structs[i].slots[j].name = gen_random_slot_name (j);
  425.     }
  426.       structs[i].numslots = j;
  427.     }
  428. }
  429.  
  430. /* Generate a function name that is unique if n is unique. */
  431.  
  432. char *
  433. gen_new_function_name (n)
  434.      int n;
  435. {
  436.   int i = 0;
  437.   char namebuf[100];
  438.  
  439.   ++n;
  440.   namebuf[i] = '\0';
  441.   /* Start with a random computer term.  */
  442.   if (xrandom (5) == 0)
  443.     {
  444.       strcat (namebuf, computer_word ());
  445.       i = strlen (namebuf);
  446.       namebuf[i++] = '_';
  447.     }
  448.   namebuf[i++] = 'f';
  449.   /* Note that if we just add an 'f', there is a small chance of getting
  450.      the name "for", which make the compiler unhappy.  */
  451.   namebuf[i++] = 'n';
  452.   /* Convert the number n itself into a string, maybe with some underscores
  453.      thrown in for flavor.  */
  454.   while (n > 0)
  455.     {
  456.       if (xrandom(4) == 0) namebuf[i++] = '_';
  457.       namebuf[i++] = 'a' + (n % 26);
  458.       n /= 26;
  459.     }
  460.   namebuf[i] = '\0';
  461.   /* Maybe add some more computerese on the end. */
  462.   if (xrandom (4) != 0)
  463.     {
  464.       namebuf[i++] = '_';
  465.       namebuf[i] = '\0';
  466.       strcat (namebuf, computer_word ());
  467.     }
  468.   return copy_string (namebuf);
  469. }
  470.  
  471. /* Create a number of functions with random numbers of arguments. */
  472.  
  473. /* (should gen with random arg types also) */
  474.  
  475. void
  476. create_functions()
  477. {
  478.   int i, j, numargs;
  479.  
  480.   printf ("Creating %d functions...\n", numfunctions);
  481.   for (i = 0; i < numfunctions; ++i)
  482.     {
  483.       functions[i].name = gen_new_function_name(i);
  484.       numargs = xrandom (MAXFARGS + 1);
  485.       for (j = 0; j < numargs; ++j)
  486.     {
  487.       functions[i].args[j] = gen_random_local_name(j, NULL);
  488.     }
  489.       functions[i].numargs = numargs;
  490.     }
  491. }
  492.  
  493. void
  494. write_header_file (n)
  495.      int n;
  496. {
  497.   int i;
  498.   char tmpbuf[100];
  499.   FILE *fp;
  500.  
  501.   sprintf (tmpbuf, "%s%d.h", file_base_name, n);
  502.   fp = fopen (tmpbuf, "w");
  503.   if (fp)
  504.     {
  505.       if (commenting > 0)
  506.     fprintf (fp, "/* header */\n");
  507.       if (1)
  508.     {
  509.       printf ("Writing %d structs...\n", numstructs);
  510.       for (i = 0; i < numstructs; ++i)
  511.         {
  512.           write_struct (fp, i);
  513.         }
  514.     }
  515.       if (1)
  516.     {
  517.       printf ("Writing %d macros...\n", nummacros);
  518.       for (i = 0; i < nummacros; ++i)
  519.         {
  520.           write_macro (fp, i);
  521.         }
  522.     }
  523.       if (1)
  524.     {
  525.       printf ("Writing %d function decls...\n", numfunctions);
  526.       for (i = 0; i < numfunctions; ++i)
  527.         {
  528.           write_function_decl (fp, i);
  529.         }
  530.     }
  531.       fclose (fp);
  532.     }
  533. }
  534.  
  535. /* Write out the definition of a structure. */
  536.  
  537. void
  538. write_struct (fp, i)
  539.      FILE *fp;
  540.      int i;
  541. {
  542.   int j;
  543.  
  544.   if (i == 0) printf ("  (Each struct contains %d slots)\n", numslots);
  545.   fprintf (fp, "struct %s {\n", structs[i].name);
  546.   for (j = 0; j < structs[i].numslots; ++j)
  547.     {
  548.       fprintf (fp, "  %s %s;\n",
  549.            name_from_type (random_type ()), structs[i].slots[j].name);
  550.     }
  551.   fprintf (fp, "};\n\n");
  552. }
  553.  
  554. void
  555. write_macro (fp, n)
  556.      FILE *fp;
  557.      int n;
  558. {
  559.   int i, j;
  560.  
  561.   fprintf (fp, "#define %s", macros[n].name);
  562.   if (1)
  563.     {
  564.       fprintf (fp, "(");
  565.       for (j = 0; j < macros[n].numargs; ++j)
  566.     {
  567.       if (j > 0) fprintf (fp, ",");
  568.       fprintf (fp, "%s", macros[n].args[j]);
  569.     }
  570.       fprintf (fp, ")");
  571.     }
  572.   /* Generate a macro body. */
  573.   switch (xrandom(2))
  574.     {
  575.     case 0:
  576.       fprintf (fp, "\\\n");
  577.       fprintf (fp, "(");
  578.       if (macros[n].numargs > 0)
  579.     {
  580.       for (i = 0; i < macros[n].numargs; ++i)
  581.         {
  582.           if (i > 0) fprintf (fp, ",");
  583.           fprintf (fp, " \\\n");
  584.           fprintf (fp, "  (%s)", macros[n].args[i]);
  585.           if (xrandom (2) == 0)
  586.         {
  587.           fprintf (fp, ",");
  588.           fprintf (fp, " \\\n");
  589.           fprintf (fp, " ((int) (%s))", macros[n].args[i]);
  590.         }
  591.         }
  592.       fprintf (fp, "\\\n");
  593.     }
  594.       else
  595.     {
  596.       fprintf (fp, " (1)");
  597.     }
  598.       fprintf (fp, ")");
  599.       break;
  600.     default:
  601.       fprintf (fp, " (1)");
  602.       break;
  603.     }
  604.   fprintf (fp, "\n\n");
  605. }
  606.  
  607. void
  608. write_function_decl (fp, n)
  609.      FILE *fp;
  610.      int n;
  611. {
  612.   fprintf (fp, "int %s (", functions[n].name);
  613.   fprintf (fp, ");\n");
  614. }
  615.  
  616. /* Write a complete source file. */
  617.  
  618. void
  619. write_source_file (n)
  620.      int n;
  621. {
  622.   char tmpbuf[100];
  623.   int j, k;
  624.   FILE *fp;
  625.  
  626.   sprintf (tmpbuf, "%s%d.c", file_base_name, n);
  627.   fp = fopen (tmpbuf, "w");
  628.   if (fp)
  629.     {
  630.       if (numheaderfiles > 0)
  631.     {
  632.       for (j = 0; j < numheaderfiles; ++j)
  633.         {
  634.           fprintf(fp, "#include \"%s%d.h\"\n", file_base_name, j);
  635.         }
  636.       fprintf(fp, "\n");
  637.     }
  638.  
  639.       if (n == 0) printf ("  (Each file contains %d functions)\n",
  640.               num_functions_per_file);
  641.  
  642.       /* Put out a "main", but only in the first C file. */
  643.       if (n == 0)
  644.     {
  645.       fprintf (fp, "main ()\n");
  646.       fprintf (fp, "{\n");
  647.       if (1 /* use stdio */)
  648.         {
  649.           fprintf (fp, "  printf (\"hello world\\n\");\n");
  650.           /* (should issue calls to other functions?) */
  651.         }
  652.       fprintf (fp, "}\n\n");
  653.     }
  654.  
  655.       for (j = 0; j < num_functions_per_file; ++j)
  656.     {
  657.       write_function (fp, n * num_functions_per_file + j);
  658.     }
  659.     }
  660.   fclose (fp);
  661. }
  662.  
  663. void
  664. write_function (fp, n)
  665.      FILE *fp;
  666.      int n;
  667. {
  668.   int k;
  669.  
  670.   fprintf(fp, "%s ()\n", functions[n].name);
  671.   fprintf(fp, "{\n");
  672.   /* Generate a plausible function body. */
  673.   for (k = 0; k < function_length; ++k)
  674.     {
  675.       write_statement (fp, 0, xrandom(2) + 1);
  676.     }
  677.   fprintf (fp, "}\n\n");
  678. }
  679.  
  680. void
  681. write_statement (fp, depth, max_depth)
  682.      FILE *fp;
  683.      int depth, max_depth;
  684. {
  685.   int n, j;
  686.  
  687.   /* Always do non-recursive statements if going too deep. */
  688.   if (depth >= max_depth || xrandom(2) == 0)
  689.     {
  690.       switch (xrandom(2))
  691.     {
  692.     default:
  693.       write_expression (fp, 0, xrandom(4) + 1);
  694.       fprintf (fp, ";\n");
  695.       break;
  696.     }
  697.     }
  698.   else
  699.     {
  700.       switch (xrandom(2))
  701.     {
  702.     default:
  703.       fprintf (fp, "if (");
  704.       write_expression (fp, 0, xrandom(2) + 1);
  705.       fprintf (fp, ")\n    {\n");
  706.       write_statement(fp, depth + 1, max_depth);
  707.       fprintf (fp, "    }\n");
  708.       break;
  709.     }
  710.     }
  711. }
  712.  
  713. /* Write a single expression. */
  714.  
  715. void
  716. write_expression (fp, depth, max_depth)
  717.      FILE *fp;
  718.      int depth, max_depth;
  719. {
  720.   int n, j;
  721.  
  722.   /* Always do non-recursive statements if going too deep. */
  723.   if (depth >= max_depth || xrandom(2) == 0)
  724.     {
  725.       switch (xrandom(10))
  726.     {
  727.     case 7:
  728.       fprintf (fp, "%d", xrandom (1000));
  729.       break;
  730.     default:
  731.       fprintf (fp, "%d", xrandom (127));
  732.       break;
  733.     }
  734.     }
  735.   else
  736.     {
  737.       switch (xrandom(10))
  738.     {
  739.     case 0:
  740.     case 5:
  741.     case 7:
  742.       n = xrandom (numfunctions);
  743.       fprintf(fp, "  %s (", functions[n].name);
  744.       for (j = 0; j < functions[n].numargs; ++j)
  745.         {
  746.           if (j > 0) fprintf (fp, ", ");
  747.           write_expression(fp, depth + 1, max_depth);
  748.         }
  749.       fprintf(fp, ")");
  750.       break;
  751.     case 1:
  752.     case 6:
  753.     case 8:
  754.       n = xrandom (nummacros);
  755.       fprintf(fp, "  %s(", macros[n].name);
  756.       for (j = 0; j < macros[n].numargs; ++j)
  757.         {
  758.           if (j > 0) fprintf (fp, ", ");
  759.           write_expression(fp, depth + 1, max_depth);
  760.         }
  761.       fprintf(fp, ")");
  762.       break;
  763.     case 2:
  764.       write_expression (fp, depth + 1, max_depth);
  765.       fprintf (fp, " + ");
  766.       write_expression (fp, depth + 1, max_depth);
  767.       break;
  768.     case 3:
  769.       write_expression (fp, depth + 1, max_depth);
  770.       fprintf (fp, " - ");
  771.       write_expression (fp, depth + 1, max_depth);
  772.       break;
  773.     case 4:
  774.       write_expression (fp, depth + 1, max_depth);
  775.       fprintf (fp, " * ");
  776.       write_expression (fp, depth + 1, max_depth);
  777.       break;
  778.     default:
  779.       fprintf (fp, "%d", xrandom (127));
  780.       break;
  781.     }
  782.     }
  783. }
  784.  
  785. /* Write out a makefile that will compile the program just generated. */
  786.  
  787. void
  788. write_makefile ()
  789. {
  790.   char tmpbuf[100];
  791.   int i, j;
  792.   FILE *fp;
  793.  
  794.   sprintf (tmpbuf, "%s.mk", file_base_name);
  795.   fp = fopen (tmpbuf, "w");
  796.   if (fp)
  797.     {
  798.       fprintf (fp, "CC = cc\n\n");
  799.       /* Write dependencies and action line for the executable.  */
  800.       fprintf (fp, "%s:    ", file_base_name);
  801.       for (i = 0; i < numfiles; ++i)
  802.     fprintf (fp, " %s%d.o", file_base_name, i);
  803.       fprintf (fp, "\n");
  804.       fprintf (fp, "\t$(CC) -o %s.out", file_base_name);
  805.       for (i = 0; i < numfiles; ++i)
  806.     fprintf (fp, " %s%d.o", file_base_name, i);
  807.       fprintf (fp, "\n\n");
  808.       /* Write dependencies for individual files. */
  809.       for (i = 0; i < numfiles; ++i)
  810.     {
  811.       fprintf (fp, " %s%d.o:    %s%d.c",
  812.            file_base_name, i, file_base_name, i);
  813.       for (j = 0; j < numheaderfiles; ++j)
  814.         fprintf (fp, " %s%d.h", file_base_name, j);
  815.       fprintf (fp, "\n");
  816.     }
  817.       fclose (fp);
  818.     }
  819. }
  820.  
  821.  
  822. /* Utility/general functions. */
  823.  
  824. char *
  825. gen_random_name (root)
  826. char *root;
  827. {
  828.   char namebuf[100];
  829.  
  830.   if (root == NULL) root = "n";
  831.   sprintf (namebuf, "%s_%d", root, xrandom (10000));
  832.   return copy_string (namebuf);
  833. }
  834.  
  835. /* Generate a local variable name. */
  836.  
  837. char *
  838. gen_random_local_name (numothers, others)
  839. int numothers;
  840. char **others;
  841. {
  842.   char namebuf[100];
  843.  
  844.   sprintf (namebuf, "arg%d", numothers + 1);
  845.   return copy_string (namebuf);
  846. }
  847.  
  848. #include <time.h>
  849.  
  850. /* Random number handling is important but terrible/nonexistent
  851.    in some systems.  Do it ourselves.  Also, this will give repeatable
  852.    results across multiple platforms.  */
  853.  
  854. /* The random state *must* be at least 32 bits.  */
  855.  
  856. unsigned long initrandstate = 0;
  857.  
  858. unsigned long randstate = 0;
  859.  
  860. /* Seed can come from elsewhere, for repeatability.  Otherwise, it comes
  861.    from the current time, scaled down to where 32-bit arithmetic won't
  862.    overflow.  */
  863.  
  864. void
  865. init_xrandom (seed)
  866.      int seed;
  867. {
  868.   time_t tm;
  869.         
  870.   if (seed > 0)
  871.     {
  872.       /* If the random state is already set, changes are somewhat
  873.      suspicious.  */
  874.       if (randstate > 0)
  875.     {
  876.       fprintf (stderr, "Randstate being changed from %lu to %d\n",
  877.            randstate, seed);
  878.     }
  879.       randstate = seed;
  880.     }
  881.   else
  882.     {
  883.       time (&tm);
  884.       randstate = tm;
  885.     }
  886.   /* Whatever its source, put the randstate into known range (0 - 99999).  */
  887.   randstate = abs (randstate);
  888.   randstate %= 100000L;
  889.   /* This is kept around for the sake of error reporting. */
  890.   initrandstate = randstate;
  891. }
  892.  
  893. /* Numbers lifted from Numerical Recipes, p. 198.  */
  894. /* Arithmetic must be 32-bit.  */
  895.  
  896. int
  897. xrandom (m)
  898. int m;
  899. {
  900.     randstate = (8121 * randstate + 28411) % 134456L;
  901.     return ((m * randstate) / 134456L);
  902. }
  903.  
  904. char *
  905. xmalloc (amt)
  906.      int amt;
  907. {
  908.   char *value = (char *) malloc (amt);
  909.  
  910.   if (value == NULL)
  911.     {
  912.       /* This is pretty serious, have to get out quickly.  */
  913.       fprintf (stderr, "Memory exhausted!!\n");
  914.       exit (1);
  915.     }
  916.   /* Save callers from having to clear things themselves.  */
  917.   bzero (value, amt);
  918.   return value;
  919. }
  920.  
  921. /* Copy a string to newly-allocated space.  The new space is never freed. */
  922.  
  923. char *
  924. copy_string (str)
  925.      char *str;
  926. {
  927.   int len = strlen (str);
  928.   char *rslt;
  929.   
  930.   rslt = xmalloc (len + 1);
  931.   strcpy (rslt, str);
  932.   return rslt;
  933. }
  934.