📄 spu.c
字号:
else if (strcmp(arg, "--lib-functions") == 0) { num = strtol (argv[++i], NULL, 10); num_lib_functions = num; } else if (strcmp(arg, "--lib-macros") == 0) { num = strtol (argv[++i], NULL, 10); num_lib_macros = num; } else if (strcmp(arg, "--lib-structs") == 0) { num = strtol (argv[++i], NULL, 10); num_lib_structs = num; } else if (strcmp(arg, "--macros") == 0) { num = strtol (argv[++i], NULL, 10); num_macros = num; } else if (strcmp(arg, "--methods") == 0) { num = strtol (argv[++i], NULL, 10); num_methods = num; } else if (strcmp(arg, "--seed") == 0) { num = strtol (argv[++i], NULL, 10); seed = num; } else if (strcmp(arg, "--structs") == 0) { num = strtol (argv[++i], NULL, 10); num_structs = num; } else if (strcmp(arg, "--version") == 0) { fprintf (stderr, "SPU program generator version %s\n", version_string); exit (0); } else { fprintf (stderr, "Usage: \"%s\" not valid, ignored\n", arg); display_usage (); } } if (language != cpp) num_classes = num_lib_classes = 0; init_xrandom (seed); /* Round up the number of functions so each file gets the same number. */ num_functions_per_file = (num_functions + num_files - 1) / num_files; num_functions = num_functions_per_file * num_files; /* Create the definitions of objects internally. */ order.size = num_macros + num_enums + num_structs + num_classes + num_functions; order.nextentry = 0; order.entries = (struct decl_entry *) xmalloc (order.size * sizeof(struct decl_entry)); lib_order.size = num_lib_macros + num_lib_enums + num_lib_structs + num_lib_classes + num_lib_functions; lib_order.nextentry = 0; lib_order.entries = (struct decl_entry *) xmalloc (lib_order.size * sizeof(struct decl_entry)); create_macros (); create_enums (); create_structs (); create_functions (); create_classes (); /* Write out a bunch of files. */ printf ("Writing %d header files...\n", num_header_files); for (i = 0; i < num_header_files; ++i) write_header_file (i); write_lib_header_file (); write_lib_source_file (); printf ("Writing %d files...\n", num_files); for (i = 0; i < num_files; ++i) write_source_file (i); /* Write out a makefile. */ write_makefile (); /* Succeed if we actually wrote out a whole program correctly. */ exit (0);}voiddisplay_usage (void){ fprintf (stderr, "Usage: spu [ ... options ... ]\n"); fprintf (stderr, "\t--basename str (default \"%s\")\n", "file"); fprintf (stderr, "\t--classes n (default %d)\n", DEFAULT_NUM_CLASSES); fprintf (stderr, "\t--comments n\n"); fprintf (stderr, "\t--enums n (default %d)\n", DEFAULT_NUM_ENUMS); fprintf (stderr, "\t--enumerators n (default %d)\n", DEFAULT_NUM_ENUMERATORS); fprintf (stderr, "\t--fields n (default %d)\n", DEFAULT_NUM_FIELDS); fprintf (stderr, "\t--files n (default %d)\n", DEFAULT_NUM_FILES); fprintf (stderr, "\t--functions n (default %d)\n", DEFAULT_NUM_FUNCTIONS); fprintf (stderr, "\t--function-length n (default %d)\n", DEFAULT_FUNCTION_LENGTH); fprintf (stderr, "\t--function-depth n (default %d)\n", DEFAULT_FUNCTION_DEPTH); fprintf (stderr, "\t--header-files n (default %d)\n", DEFAULT_NUM_HEADER_FILES); fprintf (stderr, "\t--help\n"); fprintf (stderr, "\t--language c|cpp|knr|objc (default c)\n"); fprintf (stderr, "\t--lib-classes n (default %d)\n", DEFAULT_NUM_LIB_CLASSES); fprintf (stderr, "\t--lib-enums n (default %d)\n", DEFAULT_NUM_LIB_ENUMS); fprintf (stderr, "\t--lib-functions n (default %d)\n", DEFAULT_NUM_LIB_FUNCTIONS); fprintf (stderr, "\t--lib-macros n (default %d)\n", DEFAULT_NUM_LIB_MACROS); fprintf (stderr, "\t--lib-structs n (default %d)\n", DEFAULT_NUM_LIB_STRUCTS); fprintf (stderr, "\t--macros n (default %d)\n", DEFAULT_NUM_MACROS); fprintf (stderr, "\t--methods n (default %d)\n", DEFAULT_NUM_METHODS); fprintf (stderr, "\t--seed n\n"); fprintf (stderr, "\t--structs n (default %d)\n", DEFAULT_NUM_STRUCTS); fprintf (stderr, "\t--version\n");}intrandom_type (int libonly){ int i, n; switch (xrandom (6)) { case 0: return t_short; case 1: return t_char; case 2: return t_char_ptr; case 3: for (i = 0; i < 1000; ++i) { n = xrandom (num_lib_structs); if (lib_structs[n].id > 0 && lib_structs[n].use) return t_first_user + lib_structs[n].id; } return t_int; case 4: if (libonly) return t_int; for (i = 0; i < 1000; ++i) { n = xrandom (num_structs); if (structs[n].id > 0) return t_first_user + structs[n].id; } return t_int; default: return t_int; }}/* Given a numbered type, return its name. */char *name_from_type (int n){ int i; char tmpbuf[100]; if (n < t_first_user) { return typenames[n]; } else if (n >= 1000000 && (n - 1000000) < t_first_user) { sprintf (tmpbuf, "%s *", typenames[n - 1000000]); return copy_string (tmpbuf); } else { for (i = 0; i < num_structs; ++i) { if (structs[i].id == (n - t_first_user)) { sprintf (tmpbuf, "struct %s *", structs[i].name); return copy_string (tmpbuf); } } for (i = 0; i < num_lib_structs; ++i) { if (lib_structs[i].id == (n - t_first_user)) { sprintf (tmpbuf, "struct %s *", lib_structs[i].name); return copy_string (tmpbuf); } } } return "?type?";}voidadd_decl_to_table (enum decl_types type, void *desc, struct decl_table *table){ int n = table->nextentry++; table->entries[n].type = type; switch (type) { case d_macro: table->entries[n].decl.macro_d = (struct macro_desc *) desc; break; case d_enum: table->entries[n].decl.enum_d = (struct enum_desc *) desc; break; case d_struct: table->entries[n].decl.struct_d = (struct struct_desc *) desc; break; case d_class: table->entries[n].decl.class_d = (struct class_desc *) desc; break; case d_function: table->entries[n].decl.function_d = (struct function_desc *) desc; break; default: fprintf (stderr, "Unknown decl type %d in add_decl_to_table\n", type); break; } table->entries[n].seq = n; if (randomize_order) table->entries[n].order = xrandom (10000);}/* Create basic definitions of macros. Negative number of arguments means a macros that looks like a constant instead of a function. */voidcreate_macros (void){ int i; printf ("Creating %d macros...\n", num_macros); macros = (struct macro_desc *) xmalloc (num_macros * sizeof(struct macro_desc)); for (i = 0; i < num_macros; ++i) { create_macro (&(macros[i])); add_decl_to_table (d_macro, &(macros[i]), &order); } /* It's important to create library macros second, so that their ids are higher than those for program macros. This is so that library macro bodies are excluded from referencing any program macros (because of the exclude_id bits in write_expression). */ printf ("Creating %d library macros...\n", num_lib_macros); lib_macros = (struct macro_desc *) xmalloc (num_lib_macros * sizeof(struct macro_desc)); for (i = 0; i < num_lib_macros; ++i) { create_macro (&(lib_macros[i])); if (!probability(lib_percent)) lib_macros[i].use = 0; add_decl_to_table (d_macro, &(lib_macros[i]), &lib_order); }}voidcreate_macro (struct macro_desc *macrodesc){ int j, numargs; macrodesc->id = next_id++; macrodesc->name = gen_new_macro_name (); numargs = xrandom (DEFAULT_MAX_MACRO_ARGS + 1); --numargs; if (numargs > 0) { macrodesc->args = (char **) xmalloc (numargs * sizeof(char *)); for (j = 0; j < numargs; ++j) { macrodesc->args[j] = gen_random_local_name (j, NULL); } } macrodesc->numargs = numargs; macrodesc->use = 1;}/* Generate a macro name. */char *gen_new_macro_name (void){ return gen_unique_global_name ("M", (xrandom (3) > 0));}/* Create definitions of the desired number of enums. */voidcreate_enums (void){ int i; printf ("Creating %d enums...\n", num_enums); enums = (struct enum_desc *) xmalloc (num_enums * sizeof(struct enum_desc)); for (i = 0; i < num_enums; ++i) { create_enum (&(enums[i])); add_decl_to_table (d_enum, &(enums[i]), &order); } printf ("Creating %d library enums...\n", num_lib_enums); lib_enums = (struct enum_desc *) xmalloc (num_lib_enums * sizeof(struct enum_desc)); for (i = 0; i < num_lib_enums; ++i) { create_enum (&(lib_enums[i])); if (!probability(lib_percent)) lib_enums[i].use = 0; add_decl_to_table (d_enum, &(lib_enums[i]), &lib_order); }}voidcreate_enum (struct enum_desc *enumdesc){ int j, num; enumdesc->id = next_id++; /* Let some enums be anonymous. */ if (xrandom (100) < 50) enumdesc->name = gen_unique_global_name (NULL, 0); num = num_enumerators / 2 + xrandom (num_enumerators); if (num <= 0) num = 1; enumdesc->enumerators = (struct enumerator_desc *) xmalloc (num * sizeof(struct enumerator_desc)); for (j = 0; j < num; ++j) { enumdesc->enumerators[j].name = gen_random_enumerator_name (); } enumdesc->num_enumerators = j; enumdesc->use = 1;}/* Generate a unique enumerator within an enum. */char *gen_random_enumerator_name (void){ return gen_unique_global_name ("enum", 0);}/* Create definitions of the desired number of structures. */voidcreate_structs (void){ int i; /* Do the library structs first, so that program structs may use them in their definitions. */ printf ("Creating %d library structs...\n", num_lib_structs); lib_structs = (struct struct_desc *) xmalloc (num_lib_structs * sizeof(struct struct_desc)); for (i = 0; i < num_lib_structs; ++i) { create_struct (&(lib_structs[i]), 1); if (!probability(lib_percent)) lib_structs[i].use = 0; add_decl_to_table (d_struct, &(lib_structs[i]), &lib_order); } printf ("Creating %d structs...\n", num_structs); structs = (struct struct_desc *) xmalloc (num_structs * sizeof(struct struct_desc)); for (i = 0; i < num_structs; ++i) { create_struct (&(structs[i]), 0); add_decl_to_table (d_struct, &(structs[i]), &order); }}voidcreate_struct (struct struct_desc *structdesc, int lib){ int j, numf; structdesc->id = next_id++; structdesc->name = gen_unique_global_name (NULL, 0); numf = xrandom (num_fields) + 1; structdesc->fields = (struct field_desc *) xmalloc (numf * sizeof(struct field_desc)); for (j = 0; j < numf; ++j) { structdesc->fields[j].type = random_type (lib); structdesc->fields[j].name = gen_random_field_name (j); } structdesc->numfields = numf; structdesc->use = 1;}char *gen_random_field_name (int n){ char namebuf[100]; /* (should have more variety) */ sprintf (namebuf, "field%d", n); return copy_string (namebuf);}/* Create definitions of the desired number of classures. */voidcreate_classes (void){ int i; /* Do the library classes first, so that program classes may use them in their definitions. */ printf ("Creating %d library classes...\n", num_lib_classes); lib_classes = (struct class_desc *) xmalloc (num_lib_classes * sizeof(struct class_desc)); for (i = 0; i < num_lib_classes; ++i) { create_class (&(lib_classes[i]), 1); if (!probability(lib_percent)) lib_classes[i].use = 0; add_decl_to_table (d_class, &(lib_classes[i]), &lib_order); } printf ("Creating %d classes...\n", num_classes); classes = (struct class_desc *) xmalloc (num_classes * sizeof(struct class_desc)); for (i = 0; i < num_classes; ++i) { create_class (&(classes[i]), 0); add_decl_to_table (d_class, &(classes[i]), &order); }}voidcreate_class (struct class_desc *classdesc, int lib){ int j, numf, numm; classdesc->id = next_id++; classdesc->name = gen_unique_global_name (NULL, 0); numf = xrandom (num_fields) + 1; classdesc->fields = (struct field_desc *) xmalloc (numf * sizeof(struct field_desc)); for (j = 0; j < numf; ++j) { classdesc->fields[j].type = random_type (lib); classdesc->fields[j].name = gen_random_field_name (j); } classdesc->numfields = numf; numm = xrandom (num_methods + 1); classdesc->methods = (struct function_desc *) xmalloc (numm * sizeof(struct function_desc)); for (j = 0; j < numm; ++j) { create_function (&(classdesc->methods[j]), lib); classdesc->methods[j].class = classdesc; } classdesc->nummethods = numm; classdesc->use = 1;}/* Create a number of functions with random numbers and types of arguments. */voidcreate_functions (void){ int i; printf ("Creating %d functions...\n", num_functions); functions = (struct function_desc *) xmalloc (num_functions * sizeof(struct function_desc)); /* Generate the main program, as the first function. */ functions[0].id = next_id++; functions[0].name = "main"; functions[0].return_type = t_int; functions[0].numargs = 0; functions[0].use = 1; add_decl_to_table (d_function, &(functions[0]), &order); /* Generate all the other functions. */ for (i = 1; i < num_functions; ++i) { create_function (&(functions[i]), 0); add_decl_to_table (d_function, &(functions[i]), &order);#if 0 /* use forward decls for now instead */ { int j, type; struct function_desc *fndesc = &(functions[i]); for (j = 0; j < fndesc->numargs; ++j) { type = fndesc->args[i].type; if (type >= t_first_user) { /* (should find arg types and increase fndesc->order) */ } } }#endif } printf ("Creating %d library functions...\n", num_lib_functions); lib_functions = (struct function_desc *) xmalloc (num_lib_functions * sizeof(struct function_desc)); for (i = 0; i < num_lib_functions; ++i) { create_function (&(lib_functions[i]), 1); /* Mark some functions as not to be referenced from the program. */ if (!probability(lib_percent)) lib_functions[i].use = 0; add_decl_to_table (d_function, &(lib_functions[i]), &lib_order); }}/* Generate the details of a single function. */voidcreate_function (struct function_desc *fndesc, int lib){ int j, range, numargs; fndesc->id = next_id++; fndesc->name = gen_unique_global_name ("fn", 0); fndesc->return_type = ((xrandom (4) == 0) ? t_void : random_type (lib)); /* Choose the number of arguments, preferring shorter argument lists by using a simple binomial distribution that is "folded" in the middle so zero-arg functions are the most common. */ range = 2 * (max_function_args + 1); numargs = 0; for (j = 0; j < 6; ++j) numargs += xrandom (range + 1); if (j > 0) numargs /= j; /* Shift distribution so 0 is in the middle. */ numargs -= max_function_args; /* Fold negative values over to positive side. */ if (numargs < 0)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -