17ec681f3Smrg/*
27ec681f3Smrg * Copyright (C) 2013 Rob Clark <robdclark@gmail.com>
37ec681f3Smrg * Copyright (C) 2010-2011 Marcin Kościelnicki <koriakin@0x04.net>
47ec681f3Smrg * Copyright (C) 2010 Luca Barbieri <luca@luca-barbieri.com>
57ec681f3Smrg * Copyright (C) 2010 Marcin Slusarz <marcin.slusarz@gmail.com>
67ec681f3Smrg * All Rights Reserved.
77ec681f3Smrg *
87ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a
97ec681f3Smrg * copy of this software and associated documentation files (the "Software"),
107ec681f3Smrg * to deal in the Software without restriction, including without limitation
117ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense,
127ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the
137ec681f3Smrg * Software is furnished to do so, subject to the following conditions:
147ec681f3Smrg *
157ec681f3Smrg * The above copyright notice and this permission notice (including the next
167ec681f3Smrg * paragraph) shall be included in all copies or substantial portions of the
177ec681f3Smrg * Software.
187ec681f3Smrg *
197ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
207ec681f3Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
217ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
227ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
237ec681f3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
247ec681f3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
257ec681f3Smrg * OTHER DEALINGS IN THE SOFTWARE.
267ec681f3Smrg */
277ec681f3Smrg
287ec681f3Smrg/* modified version of headergen which uses enums and inline fxns for
297ec681f3Smrg * type safety.. based on original headergen
307ec681f3Smrg */
317ec681f3Smrg
327ec681f3Smrg#include "rnn.h"
337ec681f3Smrg#include "util.h"
347ec681f3Smrg#include <stdbool.h>
357ec681f3Smrg#include <stdio.h>
367ec681f3Smrg#include <stdlib.h>
377ec681f3Smrg#include <inttypes.h>
387ec681f3Smrg#include <time.h>
397ec681f3Smrg#include <ctype.h>
407ec681f3Smrg#include <unistd.h>
417ec681f3Smrg#include <string.h>
427ec681f3Smrg#include <sys/stat.h>
437ec681f3Smrg#include <sys/wait.h>
447ec681f3Smrg#include <assert.h>
457ec681f3Smrg
467ec681f3Smrgstruct rnndelem **elems = NULL;
477ec681f3Smrgint elemsnum = 0;
487ec681f3Smrgint elemsmax = 0;
497ec681f3Smrg
507ec681f3Smrgchar **offsetfns = NULL;
517ec681f3Smrgint offsetfnsnum = 0;
527ec681f3Smrgint offsetfnsmax = 0;
537ec681f3Smrg
547ec681f3Smrgint startcol = 64;
557ec681f3Smrg
567ec681f3Smrgstruct fout {
577ec681f3Smrg	char *name;
587ec681f3Smrg	FILE *file;
597ec681f3Smrg	char *guard;
607ec681f3Smrg};
617ec681f3Smrg
627ec681f3Smrgstruct fout *fouts = 0;
637ec681f3Smrgint foutsnum = 0;
647ec681f3Smrgint foutsmax = 0;
657ec681f3Smrg
667ec681f3Smrgstatic bool no_asserts = false;
677ec681f3Smrg
687ec681f3Smrgstatic void seekcol (FILE *f, int src, int dst) {
697ec681f3Smrg	if (dst <= src)
707ec681f3Smrg		fprintf (f, "\t");
717ec681f3Smrg	else {
727ec681f3Smrg		int n = dst/8 - src/8;
737ec681f3Smrg		if (n) {
747ec681f3Smrg			while (n--)
757ec681f3Smrg				fprintf (f, "\t");
767ec681f3Smrg			n = dst&7;
777ec681f3Smrg		} else
787ec681f3Smrg			n = dst-src;
797ec681f3Smrg		while (n--)
807ec681f3Smrg			fprintf (f, " ");
817ec681f3Smrg	}
827ec681f3Smrg}
837ec681f3Smrg
847ec681f3Smrgstatic FILE *findfout (char *file) {
857ec681f3Smrg	int i;
867ec681f3Smrg	for (i = 0; i < foutsnum; i++)
877ec681f3Smrg		if (!strcmp(fouts[i].name, file))
887ec681f3Smrg			break;
897ec681f3Smrg	if (i == foutsnum) {
907ec681f3Smrg		fprintf (stderr, "AIII, didn't open file %s.\n", file);
917ec681f3Smrg		exit(1);
927ec681f3Smrg	}
937ec681f3Smrg	return fouts[i].file;
947ec681f3Smrg}
957ec681f3Smrg
967ec681f3Smrgstatic void printdef (char *name, char *suf, int type, uint64_t val, char *file) {
977ec681f3Smrg	FILE *dst = findfout(file);
987ec681f3Smrg	int len;
997ec681f3Smrg	if (suf)
1007ec681f3Smrg		fprintf (dst, "#define %s__%s%n", name, suf, &len);
1017ec681f3Smrg	else
1027ec681f3Smrg		fprintf (dst, "#define %s%n", name, &len);
1037ec681f3Smrg	if (type == 0 && val > 0xffffffffull)
1047ec681f3Smrg		seekcol (dst, len, startcol-8);
1057ec681f3Smrg	else
1067ec681f3Smrg		seekcol (dst, len, startcol);
1077ec681f3Smrg	switch (type) {
1087ec681f3Smrg		case 0:
1097ec681f3Smrg			if (val > 0xffffffffull)
1107ec681f3Smrg				fprintf (dst, "0x%016"PRIx64"ULL\n", val);
1117ec681f3Smrg			else
1127ec681f3Smrg				fprintf (dst, "0x%08"PRIx64"\n", val);
1137ec681f3Smrg			break;
1147ec681f3Smrg		case 1:
1157ec681f3Smrg			fprintf (dst, "%"PRIu64"\n", val);
1167ec681f3Smrg			break;
1177ec681f3Smrg	}
1187ec681f3Smrg}
1197ec681f3Smrg
1207ec681f3Smrgstatic void printvalue (struct rnnvalue *val, int shift) {
1217ec681f3Smrg	if (val->varinfo.dead)
1227ec681f3Smrg		return;
1237ec681f3Smrg	if (val->valvalid)
1247ec681f3Smrg		printdef (val->fullname, 0, 0, val->value << shift, val->file);
1257ec681f3Smrg}
1267ec681f3Smrg
1277ec681f3Smrgstatic void printbitfield (struct rnnbitfield *bf, int shift);
1287ec681f3Smrg
1297ec681f3Smrgstatic void printtypeinfo (struct rnntypeinfo *ti, struct rnnbitfield *bf,
1307ec681f3Smrg		char *prefix, char *file) {
1317ec681f3Smrg	FILE *dst = findfout(file);
1327ec681f3Smrg	enum rnnttype intype = ti->type;
1337ec681f3Smrg	char *typename = NULL;
1347ec681f3Smrg	uint32_t mask = typeinfo_mask(ti);
1357ec681f3Smrg	uint32_t width = 1 + ti->high - ti->low;
1367ec681f3Smrg
1377ec681f3Smrg	/* for fixed point, input type (arg to fxn) is float: */
1387ec681f3Smrg	if ((ti->type == RNN_TTYPE_FIXED) || (ti->type == RNN_TTYPE_UFIXED))
1397ec681f3Smrg		intype = RNN_TTYPE_FLOAT;
1407ec681f3Smrg
1417ec681f3Smrg	/* for toplevel register (ie. not bitfield), only generate accessor
1427ec681f3Smrg	 * fxn for special cases (float, shr, min/max, etc):
1437ec681f3Smrg	 */
1447ec681f3Smrg	if (bf || ti->shr || ti->minvalid || ti->maxvalid || ti->alignvalid ||
1457ec681f3Smrg			ti->radixvalid || (intype == RNN_TTYPE_FLOAT)) {
1467ec681f3Smrg		switch (intype) {
1477ec681f3Smrg		case RNN_TTYPE_HEX:
1487ec681f3Smrg		case RNN_TTYPE_UINT:
1497ec681f3Smrg		case RNN_TTYPE_A3XX_REGID:
1507ec681f3Smrg			typename = "uint32_t";
1517ec681f3Smrg			break;
1527ec681f3Smrg		case RNN_TTYPE_INT:
1537ec681f3Smrg			typename = "int32_t";
1547ec681f3Smrg			break;
1557ec681f3Smrg		case RNN_TTYPE_FLOAT:
1567ec681f3Smrg			typename = "float";
1577ec681f3Smrg			break;
1587ec681f3Smrg		case RNN_TTYPE_ENUM:
1597ec681f3Smrg			asprintf(&typename, "enum %s", ti->name);
1607ec681f3Smrg			break;
1617ec681f3Smrg		default:
1627ec681f3Smrg			break;
1637ec681f3Smrg		}
1647ec681f3Smrg	}
1657ec681f3Smrg
1667ec681f3Smrg	/* for boolean, just generate a #define flag.. rather than inline fxn */
1677ec681f3Smrg	if (bf && (intype == RNN_TTYPE_BOOLEAN)) {
1687ec681f3Smrg		printdef(bf->fullname, 0, 0, mask, file);
1697ec681f3Smrg		return;
1707ec681f3Smrg	}
1717ec681f3Smrg
1727ec681f3Smrg	if (typename) {
1737ec681f3Smrg		printdef(prefix, "MASK", 0, mask, file);
1747ec681f3Smrg		printdef(prefix, "SHIFT", 1, ti->low, file);
1757ec681f3Smrg
1767ec681f3Smrg		fprintf(dst, "static inline uint32_t %s(%s val)\n", prefix, typename);
1777ec681f3Smrg		fprintf(dst, "{\n");
1787ec681f3Smrg
1797ec681f3Smrg		if ((ti->minvalid || ti->maxvalid || ti->alignvalid) && !no_asserts) {
1807ec681f3Smrg			fprintf(dst, "\tassert(1");
1817ec681f3Smrg			if (ti->minvalid)
1827ec681f3Smrg				fprintf(dst, " && (val >= %"PRIu64")", ti->min);
1837ec681f3Smrg			if (ti->maxvalid)
1847ec681f3Smrg				fprintf(dst, " && (val <= %"PRIu64")", ti->max);
1857ec681f3Smrg			if (ti->alignvalid)
1867ec681f3Smrg				fprintf(dst, " && !(val %% %"PRIu64")", ti->align);
1877ec681f3Smrg			fprintf(dst, ");\n");
1887ec681f3Smrg		}
1897ec681f3Smrg
1907ec681f3Smrg		if (ti->shr && !no_asserts) {
1917ec681f3Smrg			fprintf(dst, "\tassert(!(val & 0x%x));\n", (1 << ti->shr) - 1);
1927ec681f3Smrg		}
1937ec681f3Smrg
1947ec681f3Smrg		fprintf(dst, "\treturn ((");
1957ec681f3Smrg
1967ec681f3Smrg		if (ti->type == RNN_TTYPE_FIXED) {
1977ec681f3Smrg			fprintf(dst, "((int32_t)(val * %d.0))", (1 << ti->radix));
1987ec681f3Smrg		} else if (ti->type == RNN_TTYPE_UFIXED) {
1997ec681f3Smrg			fprintf(dst, "((uint32_t)(val * %d.0))", (1 << ti->radix));
2007ec681f3Smrg		} else if (ti->type == RNN_TTYPE_FLOAT) {
2017ec681f3Smrg			if (width == 32)
2027ec681f3Smrg				fprintf(dst, "fui(val)");
2037ec681f3Smrg			else if (width == 16)
2047ec681f3Smrg				fprintf(dst, "_mesa_float_to_half(val)");
2057ec681f3Smrg			else
2067ec681f3Smrg				assert(!"invalid float size");
2077ec681f3Smrg		} else {
2087ec681f3Smrg			fprintf(dst, "val");
2097ec681f3Smrg		}
2107ec681f3Smrg
2117ec681f3Smrg		if (ti->shr)
2127ec681f3Smrg			fprintf(dst, " >> %d", ti->shr);
2137ec681f3Smrg
2147ec681f3Smrg		fprintf(dst, ") << %s__SHIFT) & %s__MASK;\n", prefix, prefix);
2157ec681f3Smrg		fprintf(dst, "}\n");
2167ec681f3Smrg
2177ec681f3Smrg		if (intype == RNN_TTYPE_ENUM)
2187ec681f3Smrg			free(typename);
2197ec681f3Smrg	}
2207ec681f3Smrg
2217ec681f3Smrg	int i;
2227ec681f3Smrg	for (i = 0; i < ti->valsnum; i++)
2237ec681f3Smrg		printvalue(ti->vals[i], ti->low);
2247ec681f3Smrg	for (i = 0; i < ti->bitfieldsnum; i++)
2257ec681f3Smrg		printbitfield(ti->bitfields[i], ti->low);
2267ec681f3Smrg}
2277ec681f3Smrg
2287ec681f3Smrgstatic void printbitfield (struct rnnbitfield *bf, int shift) {
2297ec681f3Smrg	if (bf->varinfo.dead)
2307ec681f3Smrg		return;
2317ec681f3Smrg	printtypeinfo (&bf->typeinfo, bf, bf->fullname, bf->file);
2327ec681f3Smrg}
2337ec681f3Smrg
2347ec681f3Smrgstatic void printdelem (struct rnndelem *elem, uint64_t offset, const char *str) {
2357ec681f3Smrg	int use_offset_fxn;
2367ec681f3Smrg	char *offsetfn = NULL;
2377ec681f3Smrg
2387ec681f3Smrg	if (elem->varinfo.dead)
2397ec681f3Smrg		return;
2407ec681f3Smrg
2417ec681f3Smrg	use_offset_fxn = elem->offsets || elem->doffset || elem->doffsets;
2427ec681f3Smrg	assert((!!elem->offsets + !!elem->doffset + !!elem->doffsets) <= 1);
2437ec681f3Smrg
2447ec681f3Smrg	if (use_offset_fxn)
2457ec681f3Smrg		asprintf(&offsetfn, "__offset_%s", elem->name);
2467ec681f3Smrg
2477ec681f3Smrg	if (elem->length != 1) {
2487ec681f3Smrg		ADDARRAY(elems, elem);
2497ec681f3Smrg		ADDARRAY(offsetfns, offsetfn);
2507ec681f3Smrg	}
2517ec681f3Smrg
2527ec681f3Smrg	if (elem->name) {
2537ec681f3Smrg		char *regname;
2547ec681f3Smrg		if (str) {
2557ec681f3Smrg			asprintf(&regname, "REG_%s_%s", elem->fullname, str);
2567ec681f3Smrg		} else {
2577ec681f3Smrg			asprintf(&regname, "REG_%s", elem->fullname);
2587ec681f3Smrg		}
2597ec681f3Smrg		if (elemsnum) {
2607ec681f3Smrg			int len;
2617ec681f3Smrg			FILE *dst = findfout(elem->file);
2627ec681f3Smrg			int i;
2637ec681f3Smrg
2647ec681f3Smrg			if (use_offset_fxn) {
2657ec681f3Smrg				fprintf(dst, "static inline uint32_t %s(", offsetfn);
2667ec681f3Smrg				if (elem->index)
2677ec681f3Smrg					fprintf(dst, "enum %s", elem->index->name);
2687ec681f3Smrg				else
2697ec681f3Smrg					fprintf(dst, "uint32_t");
2707ec681f3Smrg				fprintf(dst, " idx)\n");
2717ec681f3Smrg				fprintf(dst, "{\n");
2727ec681f3Smrg				if (elem->doffset) {
2737ec681f3Smrg					fprintf(dst, "\treturn (%s) + (%#" PRIx64 "*idx);\n", elem->doffset, elem->stride);
2747ec681f3Smrg				} else {
2757ec681f3Smrg					int valuesnum = elem->doffsets ? elem->doffsetsnum : elem->offsetsnum;
2767ec681f3Smrg
2777ec681f3Smrg					fprintf(dst, "\tswitch (idx) {\n");
2787ec681f3Smrg					for (i = 0; i < valuesnum; i++) {
2797ec681f3Smrg						struct rnnvalue *val = NULL;
2807ec681f3Smrg						fprintf(dst, "\t\tcase ");
2817ec681f3Smrg						if (elem->index) {
2827ec681f3Smrg							int j;
2837ec681f3Smrg							for (j = 0; j < elem->index->valsnum; j++) {
2847ec681f3Smrg								if (elem->index->vals[j]->value == i) {
2857ec681f3Smrg									val = elem->index->vals[j];
2867ec681f3Smrg									break;
2877ec681f3Smrg								}
2887ec681f3Smrg							}
2897ec681f3Smrg						}
2907ec681f3Smrg						if (val) {
2917ec681f3Smrg							fprintf(dst, "%s", val->name);
2927ec681f3Smrg						} else {
2937ec681f3Smrg							fprintf(dst, "%d", i);
2947ec681f3Smrg						}
2957ec681f3Smrg						if (elem->offsets) {
2967ec681f3Smrg							fprintf(dst, ": return 0x%08"PRIx64";\n", elem->offsets[i]);
2977ec681f3Smrg						} else {
2987ec681f3Smrg							fprintf(dst, ": return (%s);\n", elem->doffsets[i]);
2997ec681f3Smrg						}
3007ec681f3Smrg					}
3017ec681f3Smrg					fprintf(dst, "\t\tdefault: return INVALID_IDX(idx);\n");
3027ec681f3Smrg					fprintf(dst, "\t}\n");
3037ec681f3Smrg				}
3047ec681f3Smrg				fprintf(dst, "}\n");
3057ec681f3Smrg			}
3067ec681f3Smrg			fprintf (dst, "static inline uint32_t %s(", regname);
3077ec681f3Smrg			for (i = 0; i < elemsnum; i++) {
3087ec681f3Smrg				if (i)
3097ec681f3Smrg					fprintf(dst, ", ");
3107ec681f3Smrg				if (elems[i]->index)
3117ec681f3Smrg					fprintf(dst, "enum %s ", elems[i]->index->name);
3127ec681f3Smrg				else
3137ec681f3Smrg					fprintf(dst, "uint32_t ");
3147ec681f3Smrg				fprintf (dst, "i%d%n", i, &len);
3157ec681f3Smrg			}
3167ec681f3Smrg			fprintf (dst, ") { return ");
3177ec681f3Smrg			fprintf (dst, "0x%08"PRIx64"", offset + elem->offset);
3187ec681f3Smrg			for (i = 0; i < elemsnum; i++) {
3197ec681f3Smrg				if (offsetfns[i])
3207ec681f3Smrg					fprintf(dst, " + %s(i%d)", offsetfns[i], i);
3217ec681f3Smrg				else
3227ec681f3Smrg					fprintf (dst, " + %#" PRIx64 "*i%d", elems[i]->stride, i);
3237ec681f3Smrg			}
3247ec681f3Smrg			fprintf (dst, "; }\n");
3257ec681f3Smrg		} else
3267ec681f3Smrg			printdef (regname, 0, 0, offset + elem->offset, elem->file);
3277ec681f3Smrg
3287ec681f3Smrg		free(regname);
3297ec681f3Smrg/*
3307ec681f3Smrg		if (elem->stride)
3317ec681f3Smrg			printdef (elem->fullname, "ESIZE", 0, elem->stride, elem->file);
3327ec681f3Smrg		if (elem->length != 1)
3337ec681f3Smrg			printdef (elem->fullname, "LEN", 0, elem->length, elem->file);
3347ec681f3Smrg*/
3357ec681f3Smrg		printtypeinfo (&elem->typeinfo, NULL, elem->fullname, elem->file);
3367ec681f3Smrg	}
3377ec681f3Smrg	fprintf (findfout(elem->file), "\n");
3387ec681f3Smrg	int j;
3397ec681f3Smrg	for (j = 0; j < elem->subelemsnum; j++) {
3407ec681f3Smrg		printdelem(elem->subelems[j], offset + elem->offset, elem->varinfo.prefixstr);
3417ec681f3Smrg	}
3427ec681f3Smrg	if (elem->length != 1) {
3437ec681f3Smrg		elemsnum--;
3447ec681f3Smrg		offsetfnsnum--;
3457ec681f3Smrg	}
3467ec681f3Smrg	free(offsetfn);
3477ec681f3Smrg}
3487ec681f3Smrg
3497ec681f3Smrgstatic void print_file_info_(FILE *dst, struct stat* sb, struct tm* tm)
3507ec681f3Smrg{
3517ec681f3Smrg	char timestr[64];
3527ec681f3Smrg	strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
3537ec681f3Smrg	fprintf(dst, "(%7Lu bytes, from %s)\n", (unsigned long long)sb->st_size, timestr);
3547ec681f3Smrg}
3557ec681f3Smrg
3567ec681f3Smrgstatic void print_file_info(FILE *dst, const char* file)
3577ec681f3Smrg{
3587ec681f3Smrg	struct stat sb;
3597ec681f3Smrg	struct tm tm;
3607ec681f3Smrg	stat(file, &sb);
3617ec681f3Smrg	gmtime_r(&sb.st_mtime, &tm);
3627ec681f3Smrg	print_file_info_(dst, &sb, &tm);
3637ec681f3Smrg}
3647ec681f3Smrg
3657ec681f3Smrgstatic void printhead(struct fout f, struct rnndb *db) {
3667ec681f3Smrg	int i, j;
3677ec681f3Smrg	struct stat sb;
3687ec681f3Smrg	struct tm tm;
3697ec681f3Smrg	stat(f.name, &sb);
3707ec681f3Smrg	gmtime_r(&sb.st_mtime, &tm);
3717ec681f3Smrg	fprintf (f.file, "#ifndef %s\n", f.guard);
3727ec681f3Smrg	fprintf (f.file, "#define %s\n", f.guard);
3737ec681f3Smrg	fprintf (f.file, "\n");
3747ec681f3Smrg	fprintf(f.file,
3757ec681f3Smrg		"/* Autogenerated file, DO NOT EDIT manually!\n"
3767ec681f3Smrg		"\n"
3777ec681f3Smrg		"This file was generated by the rules-ng-ng headergen tool in this git repository:\n"
3787ec681f3Smrg		"http://github.com/freedreno/envytools/\n"
3797ec681f3Smrg		"git clone https://github.com/freedreno/envytools.git\n"
3807ec681f3Smrg		"\n"
3817ec681f3Smrg		"The rules-ng-ng source files this header was generated from are:\n");
3827ec681f3Smrg	unsigned maxlen = 0;
3837ec681f3Smrg	for(i = 0; i < db->filesnum; ++i) {
3847ec681f3Smrg		unsigned len = strlen(db->files[i]);
3857ec681f3Smrg		if(len > maxlen)
3867ec681f3Smrg			maxlen = len;
3877ec681f3Smrg	}
3887ec681f3Smrg	for(i = 0; i < db->filesnum; ++i) {
3897ec681f3Smrg		unsigned len = strlen(db->files[i]);
3907ec681f3Smrg		fprintf(f.file, "- %s%*s ", db->files[i], maxlen - len, "");
3917ec681f3Smrg		print_file_info(f.file, db->files[i]);
3927ec681f3Smrg	}
3937ec681f3Smrg	fprintf(f.file,
3947ec681f3Smrg		"\n"
3957ec681f3Smrg		"Copyright (C) ");
3967ec681f3Smrg	if(db->copyright.firstyear && db->copyright.firstyear < (1900 + tm.tm_year))
3977ec681f3Smrg		fprintf(f.file, "%u-", db->copyright.firstyear);
3987ec681f3Smrg	fprintf(f.file, "%u", 1900 + tm.tm_year);
3997ec681f3Smrg	if(db->copyright.authorsnum) {
4007ec681f3Smrg		fprintf(f.file, " by the following authors:");
4017ec681f3Smrg		for(i = 0; i < db->copyright.authorsnum; ++i) {
4027ec681f3Smrg			fprintf(f.file, "\n- ");
4037ec681f3Smrg			if(db->copyright.authors[i]->name)
4047ec681f3Smrg				fprintf(f.file, "%s", db->copyright.authors[i]->name);
4057ec681f3Smrg			if(db->copyright.authors[i]->email)
4067ec681f3Smrg				fprintf(f.file, " <%s>", db->copyright.authors[i]->email);
4077ec681f3Smrg			if(db->copyright.authors[i]->nicknamesnum) {
4087ec681f3Smrg				for(j = 0; j < db->copyright.authors[i]->nicknamesnum; ++j) {
4097ec681f3Smrg					fprintf(f.file, "%s%s", (j ? ", " : " ("), db->copyright.authors[i]->nicknames[j]);
4107ec681f3Smrg				}
4117ec681f3Smrg				fprintf(f.file, ")");
4127ec681f3Smrg			}
4137ec681f3Smrg		}
4147ec681f3Smrg	}
4157ec681f3Smrg	fprintf(f.file, "\n");
4167ec681f3Smrg	if(db->copyright.license)
4177ec681f3Smrg		fprintf(f.file, "\n%s\n", db->copyright.license);
4187ec681f3Smrg	fprintf(f.file, "*/\n\n\n");
4197ec681f3Smrg}
4207ec681f3Smrg
4217ec681f3Smrgint main(int argc, char **argv) {
4227ec681f3Smrg	char *file;
4237ec681f3Smrg	struct rnndb *db;
4247ec681f3Smrg	int i, j;
4257ec681f3Smrg
4267ec681f3Smrg	if (argc < 2) {
4277ec681f3Smrg		fprintf(stderr, "Usage:\n\theadergen database-file\n");
4287ec681f3Smrg		exit(1);
4297ec681f3Smrg	}
4307ec681f3Smrg
4317ec681f3Smrg	if ((argc >= 3) && !strcmp(argv[1], "--no-asserts")) {
4327ec681f3Smrg		no_asserts = true;
4337ec681f3Smrg		file = argv[2];
4347ec681f3Smrg	} else {
4357ec681f3Smrg		file = argv[1];
4367ec681f3Smrg	}
4377ec681f3Smrg
4387ec681f3Smrg	rnn_init();
4397ec681f3Smrg	db = rnn_newdb();
4407ec681f3Smrg	rnn_parsefile (db, file);
4417ec681f3Smrg	rnn_prepdb (db);
4427ec681f3Smrg	for(i = 0; i < db->filesnum; ++i) {
4437ec681f3Smrg		char *dstname = malloc(strlen(db->files[i]) + 3);
4447ec681f3Smrg		char *pretty;
4457ec681f3Smrg		strcpy(dstname, db->files[i]);
4467ec681f3Smrg		strcat(dstname, ".h");
4477ec681f3Smrg		struct fout f = { db->files[i], fopen(dstname, "w") };
4487ec681f3Smrg		if (!f.file) {
4497ec681f3Smrg			perror(dstname);
4507ec681f3Smrg			exit(1);
4517ec681f3Smrg		}
4527ec681f3Smrg		free(dstname);
4537ec681f3Smrg		pretty = strrchr(f.name, '/');
4547ec681f3Smrg		if (pretty)
4557ec681f3Smrg			pretty += 1;
4567ec681f3Smrg		else
4577ec681f3Smrg			pretty = f.name;
4587ec681f3Smrg		f.guard = strdup(pretty);
4597ec681f3Smrg		for (j = 0; j < strlen(f.guard); j++)
4607ec681f3Smrg			if (isalnum(f.guard[j]))
4617ec681f3Smrg				f.guard[j] = toupper(f.guard[j]);
4627ec681f3Smrg			else
4637ec681f3Smrg				f.guard[j] = '_';
4647ec681f3Smrg		ADDARRAY(fouts, f);
4657ec681f3Smrg		printhead(f, db);
4667ec681f3Smrg	}
4677ec681f3Smrg
4687ec681f3Smrg	for (i = 0; i < db->enumsnum; i++) {
4697ec681f3Smrg		FILE *dst = NULL;
4707ec681f3Smrg		int j;
4717ec681f3Smrg		for (j = 0; j < db->enums[i]->valsnum; j++) {
4727ec681f3Smrg			if (!dst) {
4737ec681f3Smrg				dst = findfout(db->enums[i]->vals[j]->file);
4747ec681f3Smrg				fprintf(dst, "enum %s {\n", db->enums[i]->name);
4757ec681f3Smrg			}
4767ec681f3Smrg			if (0xffff0000 & db->enums[i]->vals[j]->value)
4777ec681f3Smrg				fprintf(dst, "\t%s = 0x%08"PRIx64",\n", db->enums[i]->vals[j]->name,
4787ec681f3Smrg						db->enums[i]->vals[j]->value);
4797ec681f3Smrg			else
4807ec681f3Smrg				fprintf(dst, "\t%s = %"PRIu64",\n", db->enums[i]->vals[j]->name,
4817ec681f3Smrg						db->enums[i]->vals[j]->value);
4827ec681f3Smrg		}
4837ec681f3Smrg		if (dst) {
4847ec681f3Smrg			fprintf(dst, "};\n\n");
4857ec681f3Smrg		}
4867ec681f3Smrg	}
4877ec681f3Smrg	for (i = 0; i < db->bitsetsnum; i++) {
4887ec681f3Smrg		if (db->bitsets[i]->isinline)
4897ec681f3Smrg			continue;
4907ec681f3Smrg		int j;
4917ec681f3Smrg		for (j = 0; j < db->bitsets[i]->bitfieldsnum; j++)
4927ec681f3Smrg			printbitfield (db->bitsets[i]->bitfields[j], 0);
4937ec681f3Smrg	}
4947ec681f3Smrg	for (i = 0; i < db->domainsnum; i++) {
4957ec681f3Smrg		if (db->domains[i]->size)
4967ec681f3Smrg			printdef (db->domains[i]->fullname, "SIZE", 0, db->domains[i]->size, db->domains[i]->file);
4977ec681f3Smrg		int j;
4987ec681f3Smrg		for (j = 0; j < db->domains[i]->subelemsnum; j++) {
4997ec681f3Smrg			printdelem(db->domains[i]->subelems[j], 0, NULL);
5007ec681f3Smrg		}
5017ec681f3Smrg	}
5027ec681f3Smrg	for(i = 0; i < foutsnum; ++i) {
5037ec681f3Smrg		fprintf (fouts[i].file, "\n#endif /* %s */\n", fouts[i].guard);
5047ec681f3Smrg	}
5057ec681f3Smrg	return db->estatus;
5067ec681f3Smrg}
507