mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-28 07:02:14 +00:00
68b5cd89d2
While the previous cleanup took care of the C side, it turns out vkgen was leaking property list items all over the place, but they were cleaned up by the shutdown code.
273 lines
5.9 KiB
R
273 lines
5.9 KiB
R
#include <hash.h>
|
|
#include <qfile.h>
|
|
#include <runtime.h>
|
|
#include <string.h>
|
|
#include <types.h>
|
|
#include <Array.h>
|
|
#include <AutoreleasePool.h>
|
|
#include <PropertyList.h>
|
|
|
|
#include "vkgen.h"
|
|
#include "vkstruct.h"
|
|
#include "vkfixedarray.h"
|
|
#include "vkenum.h"
|
|
|
|
static AutoreleasePool *autorelease_pool;
|
|
static void
|
|
arp_start (void)
|
|
{
|
|
autorelease_pool = [[AutoreleasePool alloc] init];
|
|
}
|
|
|
|
static void
|
|
arp_end (void)
|
|
{
|
|
[autorelease_pool release];
|
|
autorelease_pool = nil;
|
|
}
|
|
|
|
void printf (string fmt, ...) = #0;
|
|
|
|
void fprintf (QFile file, string format, ...)
|
|
{
|
|
Qputs (file, vsprintf (format, va_copy (@args)));
|
|
}
|
|
|
|
hashtab_t *available_types;
|
|
hashtab_t *processed_types;
|
|
Array *queue;
|
|
Array *output_types;
|
|
|
|
PLItem *parse;
|
|
QFile output_file;
|
|
QFile header_file;
|
|
|
|
qfot_type_encodings_t *encodings;
|
|
|
|
qfot_type_t *
|
|
next_type (qfot_type_t *type)
|
|
{
|
|
int size = type.size;
|
|
if (!size)
|
|
size = 4;
|
|
return (qfot_type_t *) ((int *) type + size);
|
|
}
|
|
|
|
int
|
|
type_is_null (qfot_type_t *type)
|
|
{
|
|
return type.size == 0;
|
|
}
|
|
|
|
void print_type (qfot_type_t *type)
|
|
{
|
|
//printf ("type: %p %d %d %s", type, type.meta, type.size, type.encoding);
|
|
switch (type.meta) {
|
|
case ty_basic:
|
|
//printf (" %d", type.type);
|
|
switch (type.type) {
|
|
case ev_ptr:
|
|
case ev_field:
|
|
//printf (" ");
|
|
print_type (type.fldptr.aux_type);
|
|
break;
|
|
case ev_func:
|
|
//printf (" %p %d\n", type.func.return_type,
|
|
// type.func.num_params);
|
|
default:
|
|
//printf ("\n");
|
|
break;
|
|
}
|
|
break;
|
|
case ty_struct:
|
|
case ty_union:
|
|
case ty_enum:
|
|
//printf (" %s %d\n", type.strct.tag, type.strct.num_fields);
|
|
break;
|
|
case ty_array:
|
|
//printf (" %p %d %d\n", type.array.type, type.array.base,
|
|
// type.array.size);
|
|
break;
|
|
case ty_class:
|
|
//printf (" %s\n", type.class);
|
|
break;
|
|
case ty_alias:
|
|
//printf (" %d %s ", type.alias.type, type.alias.name);
|
|
print_type (type.alias.aux_type);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void
|
|
scan_types (void)
|
|
{
|
|
qfot_type_t *type;
|
|
|
|
for (type = encodings.types;
|
|
((int *)type - (int *) encodings.types) < encodings.size;
|
|
type = next_type (type)) {
|
|
if (type.size) {
|
|
string tag = str_mid(type.strct.tag, 4);
|
|
Type *avail_type = [Type fromType: type];
|
|
if (avail_type) {
|
|
if (!Hash_Find (available_types, [avail_type name])) {
|
|
//printf ("scan: %s %s\n", tag, [avail_type name]);
|
|
Hash_Add (available_types, avail_type);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static string
|
|
get_string_key (void *str, void *unused)
|
|
{
|
|
return (string) str;
|
|
}
|
|
|
|
static string
|
|
get_object_key (void *obj, void *unused)
|
|
{
|
|
return [(id)obj name];
|
|
}
|
|
|
|
static void
|
|
free_object (void *obj, void *unused)
|
|
{
|
|
[(id)obj release];
|
|
}
|
|
|
|
void
|
|
usage (string name)
|
|
{
|
|
printf ("%s [plist file] [output file] [header file]\n", name);
|
|
}
|
|
|
|
int
|
|
main(int argc, string *argv)
|
|
{
|
|
int do_struct = 0;
|
|
int do_enum = 0;
|
|
string plist_filename;
|
|
QFile plist_file;
|
|
PLItem *plist;
|
|
PLItem *search;
|
|
PLItem *handles;
|
|
|
|
arp_start ();
|
|
|
|
if (argc != 4) {
|
|
usage (argv[0]);
|
|
return 1;
|
|
}
|
|
plist_filename = argv[1];
|
|
plist_file = Qopen (plist_filename, "rt");
|
|
if (!plist_file) {
|
|
printf ("could not open property list file: %s\n", plist_filename);
|
|
return 1;
|
|
}
|
|
plist = [[PLDictionary fromFile: plist_file] retain];
|
|
if (!plist) {
|
|
printf ("error parsing: %s\n", plist_filename);
|
|
return 1;
|
|
}
|
|
Qclose (plist_file);
|
|
if ([plist class] != [PLDictionary class]) {
|
|
printf ("%s not a dictionary\n", plist_filename);
|
|
return 1;
|
|
}
|
|
search = [[plist getObjectForKey: "search"] retain];
|
|
handles = [[plist getObjectForKey: "handles"] retain];
|
|
parse = [[plist getObjectForKey: "parse"] retain];
|
|
|
|
encodings = PR_FindGlobal (".type_encodings");
|
|
if (!encodings) {
|
|
printf ("Can't find encodings\n");
|
|
return 1;
|
|
}
|
|
queue = [[Array array] retain];
|
|
output_types = [[Array array] retain];
|
|
available_types = Hash_NewTable (127, get_object_key, free_object, nil);
|
|
processed_types = Hash_NewTable (127, get_string_key, nil, nil);
|
|
scan_types ();
|
|
|
|
for (int i = [search numObjects]; i-- > 0; ) {
|
|
PLString *str = (PLString *) [search getObjectAtIndex:i];
|
|
string search_name = [str string];
|
|
id obj = (id) Hash_Find (available_types, search_name);
|
|
obj = [obj resolveType];
|
|
//printf("obj: %d %s\n", obj, class_get_class_name([obj class]));
|
|
if (obj && ([obj class] == [Struct class]
|
|
|| [obj class] == [Enum class])) {
|
|
[obj addToQueue];
|
|
}
|
|
}
|
|
|
|
while ([queue count]) {
|
|
id obj = [queue objectAtIndex:0];
|
|
[queue removeObjectAtIndex:0];
|
|
if ([obj class] == [Struct class]) {
|
|
string name = [obj name];
|
|
if (name == "char" // char type faked via a struct
|
|
|| [[parse getObjectForKey:name] string] == "skip") {
|
|
continue;
|
|
}
|
|
[obj queueFieldTypes];
|
|
}
|
|
[output_types addObject:obj];
|
|
}
|
|
|
|
for (int i = 0; i < argc; i++) {
|
|
//printf ("vkgen %d %s\n", i, argv[i]);
|
|
}
|
|
|
|
arp_end ();
|
|
|
|
output_file = Qopen (argv[2], "wt");
|
|
header_file = Qopen (argv[3], "wt");
|
|
for (int i = [output_types count]; i-- > 0; ) {
|
|
id obj = [output_types objectAtIndex:i];
|
|
if ([obj name] == "VkStructureType") {
|
|
continue;
|
|
}
|
|
|
|
arp_start ();
|
|
[obj writeForward];
|
|
[obj initParse:[parse getObjectForKey:[obj name]]];
|
|
arp_end ();
|
|
}
|
|
for (int i = [output_types count]; i-- > 0; ) {
|
|
id obj = [output_types objectAtIndex:i];
|
|
if ([obj name] == "VkStructureType") {
|
|
continue;
|
|
}
|
|
|
|
arp_start ();
|
|
[obj writeTable];
|
|
arp_end ();
|
|
}
|
|
fprintf (output_file, "static void\n");
|
|
fprintf (output_file, "vkgen_init_symtabs (exprctx_t *context)\n");
|
|
fprintf (output_file, "{\n");
|
|
for (int i = [output_types count]; i-- > 0; ) {
|
|
id obj = [output_types objectAtIndex:i];
|
|
if ([obj name] == "VkStructureType") {
|
|
continue;
|
|
}
|
|
arp_start ();
|
|
[obj writeSymtabInit];
|
|
[obj writeSymtabEntry];
|
|
arp_end ();
|
|
}
|
|
fprintf (output_file, "}\n");
|
|
Qclose (output_file);
|
|
Qclose (header_file);
|
|
Hash_DelTable (available_types);
|
|
[plist release];
|
|
[search release];
|
|
[handles release];
|
|
[parse release];
|
|
[queue release];
|
|
[output_types release];
|
|
return 0;
|
|
}
|