📄 spu.c
字号:
} fprintf(fp, ")"); break; case 1: case 6: macrodesc = find_macro (t_int, lib_macros, num_lib_macros, exclude_id); if (macrodesc == NULL) { cast_integer_type (fp, rslttype); fprintf (fp, "%d", xrandom (100)); return; } cast_integer_type (fp, rslttype); fprintf (fp, "%s", macrodesc->name); if (macrodesc->numargs >= 0) { fprintf (fp, " ("); for (j = 0; j < macrodesc->numargs; ++j) { if (j > 0) fprintf (fp, ", "); write_expression (fp, t_int, depth + 1, max_depth - 1, exclude_id); } fprintf (fp, ")"); } break; case 8: macrodesc = find_macro (t_int, macros, num_macros, exclude_id); if (macrodesc == NULL) { cast_integer_type (fp, rslttype); fprintf (fp, "%d", xrandom (100)); return; } cast_integer_type (fp, rslttype); fprintf (fp, "%s", macrodesc->name); if (macrodesc->numargs >= 0) { fprintf (fp, " ("); for (j = 0; j < macrodesc->numargs; ++j) { if (j > 0) fprintf (fp, ", "); write_expression (fp, t_int, depth + 1, max_depth - 1, exclude_id); } fprintf (fp, ")"); } break; case 2: cast_integer_type (fp, rslttype); fprintf (fp, "("); write_expression (fp, t_int, depth + 1, max_depth, exclude_id); fprintf (fp, " + "); write_expression (fp, t_int, depth + 1, max_depth, exclude_id); fprintf (fp, ")"); break; case 3: cast_integer_type (fp, rslttype); fprintf (fp, "("); write_expression (fp, t_int, depth + 1, max_depth, exclude_id); fprintf (fp, " - "); write_expression (fp, t_int, depth + 1, max_depth, exclude_id); fprintf (fp, ")"); break; case 4: cast_integer_type (fp, rslttype); fprintf (fp, "("); write_expression (fp, t_int, depth + 1, max_depth, exclude_id); fprintf (fp, " * "); write_expression (fp, t_int, depth + 1, max_depth, exclude_id); fprintf (fp, ")"); break; case 5: cast_integer_type (fp, rslttype); n = xrandom (num_enums); n2 = xrandom (enums[n].num_enumerators); fprintf (fp, "%s", enums[n].enumerators[n2].name); break; default: cast_integer_type (fp, rslttype); fprintf (fp, "%d", xrandom (127)); break; }}voidcast_integer_type (FILE *fp, int type){ if (type == t_void || type == t_int) return; fprintf (fp, "(%s) ", name_from_type (type));}struct macro_desc *find_macro (int rslttype, struct macro_desc *macs, int nummacros, int exclude_id){ int j, n; for (j = 0; j < 1000; ++j) { n = xrandom (nummacros); if (macs[n].use && macs[n].id > exclude_id) return &(macs[n]); } return NULL;}/* Find a function that has the right return type. */struct function_desc *find_function (int rslttype, struct function_desc *fns, int numfns){ int j, n; /* Try several times, but eventually give up. */ for (j = 0; j < 1000; ++j) { n = xrandom (numfns); if (fns[n].use && fns[n].return_type == rslttype) return &(fns[n]); } return NULL;}/* Write out a comment block that lists all the parameters used to generate this program. */voidwrite_description_block (FILE *fp){ extern unsigned long initial_randstate; fprintf (fp, "/* A fine software product by SPU %s. */\n", version_string); fprintf (fp, "/* Written in %s. */\n", lang_names[language]); fprintf (fp, "/* Program: %d macros, %d enums, %d structs, %d classes, %d functions, */\n", num_macros, num_enums, num_structs, num_classes, num_functions); fprintf (fp, "/* divided into %d source file(s) and %d header(s). */\n", num_files, num_header_files); fprintf (fp, "/* Library: %d macros, %d enums, %d structs, %d classes, %d functions. */\n", num_lib_macros, num_lib_enums, num_lib_structs, num_lib_classes, num_lib_functions); fprintf (fp, "/* Enumerators per enum range from %d to %d. */\n", num_enumerators / 2, num_enumerators + 1); fprintf (fp, "/* Fields per struct/class range from %d to %d. */\n", 1, num_fields); if (num_classes > 0 || num_lib_classes > 0) fprintf (fp, "/* Methods per class range from %d to %d. */\n", 0, num_methods); fprintf (fp, "/* Function length is %d statements, expression depth is %d. */\n", function_length, function_depth); fprintf (fp, "/* Random seed is %d. */\n", (int) initial_randstate); fprintf (fp, "\n");}/* Write out a makefile that will compile the program just generated. */voidwrite_makefile (void){ char tmpbuf[100]; int i, j; FILE *fp; sprintf (tmpbuf, "%s.mk", file_base_name); fp = fopen (tmpbuf, "w"); if (fp) { /* Name the compiler so we can change it easily. */ fprintf (fp, "CC = cc\n\n"); /* Write dependencies and action line for the executable. */ fprintf (fp, "%s.out: ", file_base_name); for (i = 0; i < num_files; ++i) fprintf (fp, " %s%d.o", file_base_name, i); fprintf (fp, " %slib.o", file_base_name); fprintf (fp, "\n"); fprintf (fp, "\t$(CC) -o %s.out", file_base_name); for (i = 0; i < num_files; ++i) fprintf (fp, " %s%d.o", file_base_name, i); fprintf (fp, " %slib.o", file_base_name); fprintf (fp, "\n\n"); /* Write dependencies for individual files. */ for (i = 0; i < num_files; ++i) { fprintf (fp, " %s%d.o: %s%d.%s", file_base_name, i, file_base_name, i, extensions[language]); for (j = 0; j < num_header_files; ++j) fprintf (fp, " %s%d.h", file_base_name, j); fprintf (fp, "\n"); fprintf (fp, "\t$(CC) -c %s%d.%s\n", file_base_name, i, extensions[language]); } /* Library stuff. */ fprintf (fp, "\nlib: %slib.o\n\n", file_base_name); fprintf (fp, " %slib.o: %slib.%s %slib.h", file_base_name, file_base_name, extensions[language], file_base_name); fprintf (fp, "\n"); fprintf (fp, "\t$(CC) -c %slib.%s\n", file_base_name, extensions[language]); fclose (fp); }}/* Utility/general functions. *//* Generate a name that is guaranteed to be a valid C/C++ identifier. */char *gen_unique_global_name (char *root, int upcase){ int i, j; char *str, namebuf[100]; if (global_hash_table == NULL) { global_hash_table = (struct hash_table *) xmalloc (sizeof (struct hash_table)); } str = NULL; /* Keep trying until we get a unique name. */ for (i = 0; i < 10000; ++i) { gen_random_global_name (root, namebuf); if (upcase) { for (j = 0; namebuf[j] != '\0'; ++j) namebuf[j] = toupper (namebuf[j]); } if (get_from_hash_table (namebuf, global_hash_table) == NULL) { str = add_to_hash_table (namebuf, global_hash_table); break; } } if (str == NULL) { fprintf (stderr, "Can't get a unique name!\n"); exit(1); } return str;}/* Synthesize a random name that is a valid C/C++ identifier and that "looks like" something one might see in a program. */voidgen_random_global_name (char *root, char *namebuf){ char smallbuf[100]; int n, i, len; namebuf[0] = '\0'; switch (xrandom (4)) { case 0: namebuf[0] = 'a' + xrandom (26); namebuf[1] = '\0'; break; case 1: /* Convert a random number into a string, maybe with some underscores thrown in for flavor. */ n = xrandom (10000); i = 0; while (n > 0) { if (xrandom (6) == 0) namebuf[i++] = '_'; namebuf[i++] = 'a' + (n % 26); n /= 26; } namebuf[i] = '\0'; break; default: strcat (namebuf, random_computer_word ()); break; } if (root != NULL) { strcat (namebuf, "_"); strcat (namebuf, root); } switch (xrandom (5)) { case 0: strcat (namebuf, "_"); len = strlen (namebuf); namebuf[len] = 'a' + xrandom (26); namebuf[len + 1] = '\0'; break; case 1: strcat (namebuf, "_"); sprintf (smallbuf, "%d", xrandom (10000)); strcat (namebuf, smallbuf); break; case 2: n = xrandom (10000); len = strlen (namebuf); i = len; while (n > 0) { if (xrandom (6) == 0) namebuf[i++] = '_'; namebuf[i++] = 'a' + (n % 26); n /= 26; } namebuf[i] = '\0'; break; default: strcat (namebuf, "_"); strcat (namebuf, random_computer_word ()); break; } if (xrandom (5) == 0) { strcat (namebuf, "_"); sprintf (smallbuf, "%d", xrandom (10000)); strcat (namebuf, smallbuf); }#if 0 /* enable to study random name distribution */ printf ("Try %s\n", namebuf);#endif}/* Generate a local variable name. */char *gen_random_local_name (int numothers, char **others){ char namebuf[100]; sprintf (namebuf, "%s%d", (xrandom (2) == 0 ? random_computer_word () : "arg"), numothers + 1); return copy_string (namebuf);}/* Generic hash table code. */inthash_string (char *str){ int i, rslt; rslt = 0; for (i = 0; str[i] != '\0'; ++i) { rslt ^= str[i]; rslt %= 253; } return rslt;}struct hash_entry *get_hash_entry (void){ return (struct hash_entry *) xmalloc (sizeof (struct hash_entry));}char *add_to_hash_table (char *buf, struct hash_table *table){ int hash; struct hash_entry *ent, *lastent; if (buf == NULL) buf = ""; ++(table->numadds); hash = hash_string (buf); if (table->entries[hash] == NULL) { table->entries[hash] = get_hash_entry (); table->entries[hash]->val = copy_string (buf); return table->entries[hash]->val; } else { for (ent = table->entries[hash]; ent != NULL; ent = ent->next) { if (ent->val == NULL) return "null!?!"; if (strcmp (buf, ent->val) == 0) return ent->val; lastent = ent; } if (lastent != NULL) { lastent->next = get_hash_entry (); lastent->next->val = copy_string (buf); return lastent->next->val; } } /* should never happen */ return "?!hash!?";}char *get_from_hash_table (char *buf, struct hash_table *table){ int hash; struct hash_entry *ent, *lastent; if (buf == NULL) buf = ""; hash = hash_string (buf); if (table->entries[hash] == NULL) { return NULL; } else { for (ent = table->entries[hash]; ent != NULL; ent = ent->next) { if (ent->val == NULL) return "null!?!"; if (strcmp (buf, ent->val) == 0) return ent->val; lastent = ent; } if (lastent != NULL) { return NULL; } } /* should never happen */ return "?!hash!?";}/* Random number handling is important but terrible/nonexistent in some systems. Do it ourselves. Also, this will give repeatable results across multiple platforms, which is important if this is being used to generate test cases. *//* The random state *must* be at least 32 bits. */unsigned long initial_randstate = 0;unsigned long randstate = 0;/* Seed can come from elsewhere, for repeatability. Otherwise, it comes from the current time, scaled down to where 32-bit arithmetic won't overflow. */voidinit_xrandom (int seed){ time_t tm; if (seed > 0) { /* If the random state is already set, changes are somewhat suspicious. */ if (randstate > 0) { fprintf (stderr, "Randstate being changed from %lu to %d\n", randstate, seed); } randstate = seed; } else { time (&tm); randstate = tm; } /* Whatever its source, put the randstate into known range (0 - 199999). */ randstate = abs (randstate); randstate %= 200000; /* This is kept around for the sake of error reporting. */ initial_randstate = randstate;}/* Numbers lifted from Numerical Recipes, p. 198. *//* Arithmetic must be 32-bit. */intxrandom (int m){ int rslt; randstate = (9301 * randstate + 49297) % 233280; rslt = (m * randstate) / 233280;#if 0 /* enable to study random number distribution */ printf ("# %lu -> %d\n", randstate, rslt);#endif return rslt;}/* Percentage probability, with bounds checking. */intprobability(int prob){ if (prob <= 0) return 0; if (prob >= 100) return 1; return (xrandom (100) < prob);}char *xmalloc (int amt){ char *value = (char *) malloc (amt); if (value == NULL) { /* This is pretty serious, have to get out quickly. */ fprintf (stderr, "Memory exhausted!!\n"); exit (1); } /* Save callers from having to clear things themselves. */ memset (value, 0, amt); return value;}/* Copy a string to newly-allocated space. The new space is never freed. */char *copy_string (char *str){ int len = strlen (str); char *rslt; rslt = xmalloc (len + 1); strcpy (rslt, str); return rslt;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -