1bf215546Sopenharmony_ci/*
2bf215546Sopenharmony_ci * Copyright (C) 2013 Rob Clark <robdclark@gmail.com>
3bf215546Sopenharmony_ci * Copyright (C) 2010-2011 Marcin Kościelnicki <koriakin@0x04.net>
4bf215546Sopenharmony_ci * Copyright (C) 2010 Luca Barbieri <luca@luca-barbieri.com>
5bf215546Sopenharmony_ci * Copyright (C) 2010 Marcin Slusarz <marcin.slusarz@gmail.com>
6bf215546Sopenharmony_ci * All Rights Reserved.
7bf215546Sopenharmony_ci *
8bf215546Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a
9bf215546Sopenharmony_ci * copy of this software and associated documentation files (the "Software"),
10bf215546Sopenharmony_ci * to deal in the Software without restriction, including without limitation
11bf215546Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense,
12bf215546Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the
13bf215546Sopenharmony_ci * Software is furnished to do so, subject to the following conditions:
14bf215546Sopenharmony_ci *
15bf215546Sopenharmony_ci * The above copyright notice and this permission notice (including the next
16bf215546Sopenharmony_ci * paragraph) shall be included in all copies or substantial portions of the
17bf215546Sopenharmony_ci * Software.
18bf215546Sopenharmony_ci *
19bf215546Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20bf215546Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21bf215546Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
22bf215546Sopenharmony_ci * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
23bf215546Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
24bf215546Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
25bf215546Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE.
26bf215546Sopenharmony_ci */
27bf215546Sopenharmony_ci
28bf215546Sopenharmony_ci/* modified version of headergen which uses enums and inline fxns for
29bf215546Sopenharmony_ci * type safety.. based on original headergen
30bf215546Sopenharmony_ci */
31bf215546Sopenharmony_ci
32bf215546Sopenharmony_ci#include "rnn.h"
33bf215546Sopenharmony_ci#include "util.h"
34bf215546Sopenharmony_ci#include <stdbool.h>
35bf215546Sopenharmony_ci#include <stdio.h>
36bf215546Sopenharmony_ci#include <stdlib.h>
37bf215546Sopenharmony_ci#include <inttypes.h>
38bf215546Sopenharmony_ci#include <time.h>
39bf215546Sopenharmony_ci#include <ctype.h>
40bf215546Sopenharmony_ci#include <unistd.h>
41bf215546Sopenharmony_ci#include <string.h>
42bf215546Sopenharmony_ci#include <sys/stat.h>
43bf215546Sopenharmony_ci#include <sys/wait.h>
44bf215546Sopenharmony_ci#include <assert.h>
45bf215546Sopenharmony_ci
46bf215546Sopenharmony_cistruct rnndelem **elems = NULL;
47bf215546Sopenharmony_ciint elemsnum = 0;
48bf215546Sopenharmony_ciint elemsmax = 0;
49bf215546Sopenharmony_ci
50bf215546Sopenharmony_cichar **offsetfns = NULL;
51bf215546Sopenharmony_ciint offsetfnsnum = 0;
52bf215546Sopenharmony_ciint offsetfnsmax = 0;
53bf215546Sopenharmony_ci
54bf215546Sopenharmony_ciint startcol = 64;
55bf215546Sopenharmony_ci
56bf215546Sopenharmony_cistruct fout {
57bf215546Sopenharmony_ci	char *name;
58bf215546Sopenharmony_ci	FILE *file;
59bf215546Sopenharmony_ci	char *guard;
60bf215546Sopenharmony_ci};
61bf215546Sopenharmony_ci
62bf215546Sopenharmony_cistruct fout *fouts = 0;
63bf215546Sopenharmony_ciint foutsnum = 0;
64bf215546Sopenharmony_ciint foutsmax = 0;
65bf215546Sopenharmony_ci
66bf215546Sopenharmony_cistatic bool no_asserts = false;
67bf215546Sopenharmony_ci
68bf215546Sopenharmony_cistatic void seekcol (FILE *f, int src, int dst) {
69bf215546Sopenharmony_ci	if (dst <= src)
70bf215546Sopenharmony_ci		fprintf (f, "\t");
71bf215546Sopenharmony_ci	else {
72bf215546Sopenharmony_ci		int n = dst/8 - src/8;
73bf215546Sopenharmony_ci		if (n) {
74bf215546Sopenharmony_ci			while (n--)
75bf215546Sopenharmony_ci				fprintf (f, "\t");
76bf215546Sopenharmony_ci			n = dst&7;
77bf215546Sopenharmony_ci		} else
78bf215546Sopenharmony_ci			n = dst-src;
79bf215546Sopenharmony_ci		while (n--)
80bf215546Sopenharmony_ci			fprintf (f, " ");
81bf215546Sopenharmony_ci	}
82bf215546Sopenharmony_ci}
83bf215546Sopenharmony_ci
84bf215546Sopenharmony_cistatic FILE *findfout (char *file) {
85bf215546Sopenharmony_ci	int i;
86bf215546Sopenharmony_ci	for (i = 0; i < foutsnum; i++)
87bf215546Sopenharmony_ci		if (!strcmp(fouts[i].name, file))
88bf215546Sopenharmony_ci			break;
89bf215546Sopenharmony_ci	if (i == foutsnum) {
90bf215546Sopenharmony_ci		fprintf (stderr, "AIII, didn't open file %s.\n", file);
91bf215546Sopenharmony_ci		exit(1);
92bf215546Sopenharmony_ci	}
93bf215546Sopenharmony_ci	return fouts[i].file;
94bf215546Sopenharmony_ci}
95bf215546Sopenharmony_ci
96bf215546Sopenharmony_cistatic void printdef (char *name, char *suf, int type, uint64_t val, char *file) {
97bf215546Sopenharmony_ci	FILE *dst = findfout(file);
98bf215546Sopenharmony_ci	int len;
99bf215546Sopenharmony_ci	if (suf)
100bf215546Sopenharmony_ci		fprintf (dst, "#define %s__%s%n", name, suf, &len);
101bf215546Sopenharmony_ci	else
102bf215546Sopenharmony_ci		fprintf (dst, "#define %s%n", name, &len);
103bf215546Sopenharmony_ci	if (type == 0 && val > 0xffffffffull)
104bf215546Sopenharmony_ci		seekcol (dst, len, startcol-8);
105bf215546Sopenharmony_ci	else
106bf215546Sopenharmony_ci		seekcol (dst, len, startcol);
107bf215546Sopenharmony_ci	switch (type) {
108bf215546Sopenharmony_ci		case 0:
109bf215546Sopenharmony_ci			if (val > 0xffffffffull)
110bf215546Sopenharmony_ci				fprintf (dst, "0x%016"PRIx64"ULL\n", val);
111bf215546Sopenharmony_ci			else
112bf215546Sopenharmony_ci				fprintf (dst, "0x%08"PRIx64"\n", val);
113bf215546Sopenharmony_ci			break;
114bf215546Sopenharmony_ci		case 1:
115bf215546Sopenharmony_ci			fprintf (dst, "%"PRIu64"\n", val);
116bf215546Sopenharmony_ci			break;
117bf215546Sopenharmony_ci	}
118bf215546Sopenharmony_ci}
119bf215546Sopenharmony_ci
120bf215546Sopenharmony_cistatic void printvalue (struct rnnvalue *val, int shift) {
121bf215546Sopenharmony_ci	if (val->varinfo.dead)
122bf215546Sopenharmony_ci		return;
123bf215546Sopenharmony_ci	if (val->valvalid)
124bf215546Sopenharmony_ci		printdef (val->fullname, 0, 0, val->value << shift, val->file);
125bf215546Sopenharmony_ci}
126bf215546Sopenharmony_ci
127bf215546Sopenharmony_cistatic void printbitfield (struct rnnbitfield *bf, int shift);
128bf215546Sopenharmony_ci
129bf215546Sopenharmony_cistatic void printtypeinfo (struct rnntypeinfo *ti, struct rnnbitfield *bf,
130bf215546Sopenharmony_ci		char *prefix, char *file) {
131bf215546Sopenharmony_ci	FILE *dst = findfout(file);
132bf215546Sopenharmony_ci	enum rnnttype intype = ti->type;
133bf215546Sopenharmony_ci	char *typename = NULL;
134bf215546Sopenharmony_ci	uint32_t mask = typeinfo_mask(ti);
135bf215546Sopenharmony_ci	uint32_t width = 1 + ti->high - ti->low;
136bf215546Sopenharmony_ci
137bf215546Sopenharmony_ci	/* for fixed point, input type (arg to fxn) is float: */
138bf215546Sopenharmony_ci	if ((ti->type == RNN_TTYPE_FIXED) || (ti->type == RNN_TTYPE_UFIXED))
139bf215546Sopenharmony_ci		intype = RNN_TTYPE_FLOAT;
140bf215546Sopenharmony_ci
141bf215546Sopenharmony_ci	/* for toplevel register (ie. not bitfield), only generate accessor
142bf215546Sopenharmony_ci	 * fxn for special cases (float, shr, min/max, etc):
143bf215546Sopenharmony_ci	 */
144bf215546Sopenharmony_ci	if (bf || ti->shr || ti->minvalid || ti->maxvalid || ti->alignvalid ||
145bf215546Sopenharmony_ci			ti->radixvalid || (intype == RNN_TTYPE_FLOAT)) {
146bf215546Sopenharmony_ci		switch (intype) {
147bf215546Sopenharmony_ci		case RNN_TTYPE_HEX:
148bf215546Sopenharmony_ci		case RNN_TTYPE_UINT:
149bf215546Sopenharmony_ci		case RNN_TTYPE_A3XX_REGID:
150bf215546Sopenharmony_ci			typename = "uint32_t";
151bf215546Sopenharmony_ci			break;
152bf215546Sopenharmony_ci		case RNN_TTYPE_INT:
153bf215546Sopenharmony_ci			typename = "int32_t";
154bf215546Sopenharmony_ci			break;
155bf215546Sopenharmony_ci		case RNN_TTYPE_FLOAT:
156bf215546Sopenharmony_ci			typename = "float";
157bf215546Sopenharmony_ci			break;
158bf215546Sopenharmony_ci		case RNN_TTYPE_ENUM:
159bf215546Sopenharmony_ci			asprintf(&typename, "enum %s", ti->name);
160bf215546Sopenharmony_ci			break;
161bf215546Sopenharmony_ci		default:
162bf215546Sopenharmony_ci			break;
163bf215546Sopenharmony_ci		}
164bf215546Sopenharmony_ci	}
165bf215546Sopenharmony_ci
166bf215546Sopenharmony_ci	/* for boolean, just generate a #define flag.. rather than inline fxn */
167bf215546Sopenharmony_ci	if (bf && (intype == RNN_TTYPE_BOOLEAN)) {
168bf215546Sopenharmony_ci		printdef(bf->fullname, 0, 0, mask, file);
169bf215546Sopenharmony_ci		return;
170bf215546Sopenharmony_ci	}
171bf215546Sopenharmony_ci
172bf215546Sopenharmony_ci	if (typename) {
173bf215546Sopenharmony_ci		printdef(prefix, "MASK", 0, mask, file);
174bf215546Sopenharmony_ci		printdef(prefix, "SHIFT", 1, ti->low, file);
175bf215546Sopenharmony_ci
176bf215546Sopenharmony_ci		fprintf(dst, "static inline uint32_t %s(%s val)\n", prefix, typename);
177bf215546Sopenharmony_ci		fprintf(dst, "{\n");
178bf215546Sopenharmony_ci
179bf215546Sopenharmony_ci		if ((ti->minvalid || ti->maxvalid || ti->alignvalid) && !no_asserts) {
180bf215546Sopenharmony_ci			fprintf(dst, "\tassert(1");
181bf215546Sopenharmony_ci			if (ti->minvalid)
182bf215546Sopenharmony_ci				fprintf(dst, " && (val >= %"PRIu64")", ti->min);
183bf215546Sopenharmony_ci			if (ti->maxvalid)
184bf215546Sopenharmony_ci				fprintf(dst, " && (val <= %"PRIu64")", ti->max);
185bf215546Sopenharmony_ci			if (ti->alignvalid)
186bf215546Sopenharmony_ci				fprintf(dst, " && !(val %% %"PRIu64")", ti->align);
187bf215546Sopenharmony_ci			fprintf(dst, ");\n");
188bf215546Sopenharmony_ci		}
189bf215546Sopenharmony_ci
190bf215546Sopenharmony_ci		if (ti->shr && !no_asserts) {
191bf215546Sopenharmony_ci			fprintf(dst, "\tassert(!(val & 0x%x));\n", (1 << ti->shr) - 1);
192bf215546Sopenharmony_ci		}
193bf215546Sopenharmony_ci
194bf215546Sopenharmony_ci		fprintf(dst, "\treturn ((");
195bf215546Sopenharmony_ci
196bf215546Sopenharmony_ci		if (ti->type == RNN_TTYPE_FIXED) {
197bf215546Sopenharmony_ci			fprintf(dst, "((int32_t)(val * %d.0))", (1 << ti->radix));
198bf215546Sopenharmony_ci		} else if (ti->type == RNN_TTYPE_UFIXED) {
199bf215546Sopenharmony_ci			fprintf(dst, "((uint32_t)(val * %d.0))", (1 << ti->radix));
200bf215546Sopenharmony_ci		} else if (ti->type == RNN_TTYPE_FLOAT) {
201bf215546Sopenharmony_ci			if (width == 32)
202bf215546Sopenharmony_ci				fprintf(dst, "fui(val)");
203bf215546Sopenharmony_ci			else if (width == 16)
204bf215546Sopenharmony_ci				fprintf(dst, "_mesa_float_to_half(val)");
205bf215546Sopenharmony_ci			else
206bf215546Sopenharmony_ci				assert(!"invalid float size");
207bf215546Sopenharmony_ci		} else {
208bf215546Sopenharmony_ci			fprintf(dst, "val");
209bf215546Sopenharmony_ci		}
210bf215546Sopenharmony_ci
211bf215546Sopenharmony_ci		if (ti->shr)
212bf215546Sopenharmony_ci			fprintf(dst, " >> %d", ti->shr);
213bf215546Sopenharmony_ci
214bf215546Sopenharmony_ci		fprintf(dst, ") << %s__SHIFT) & %s__MASK;\n", prefix, prefix);
215bf215546Sopenharmony_ci		fprintf(dst, "}\n");
216bf215546Sopenharmony_ci
217bf215546Sopenharmony_ci		if (intype == RNN_TTYPE_ENUM)
218bf215546Sopenharmony_ci			free(typename);
219bf215546Sopenharmony_ci	}
220bf215546Sopenharmony_ci
221bf215546Sopenharmony_ci	int i;
222bf215546Sopenharmony_ci	for (i = 0; i < ti->valsnum; i++)
223bf215546Sopenharmony_ci		printvalue(ti->vals[i], ti->low);
224bf215546Sopenharmony_ci	for (i = 0; i < ti->bitfieldsnum; i++)
225bf215546Sopenharmony_ci		printbitfield(ti->bitfields[i], ti->low);
226bf215546Sopenharmony_ci}
227bf215546Sopenharmony_ci
228bf215546Sopenharmony_cistatic void printbitfield (struct rnnbitfield *bf, int shift) {
229bf215546Sopenharmony_ci	if (bf->varinfo.dead)
230bf215546Sopenharmony_ci		return;
231bf215546Sopenharmony_ci	printtypeinfo (&bf->typeinfo, bf, bf->fullname, bf->file);
232bf215546Sopenharmony_ci}
233bf215546Sopenharmony_ci
234bf215546Sopenharmony_cistatic void printdelem (struct rnndelem *elem, uint64_t offset, const char *str) {
235bf215546Sopenharmony_ci	int use_offset_fxn;
236bf215546Sopenharmony_ci	char *offsetfn = NULL;
237bf215546Sopenharmony_ci
238bf215546Sopenharmony_ci	if (elem->varinfo.dead)
239bf215546Sopenharmony_ci		return;
240bf215546Sopenharmony_ci
241bf215546Sopenharmony_ci	use_offset_fxn = elem->offsets || elem->doffset || elem->doffsets;
242bf215546Sopenharmony_ci	assert((!!elem->offsets + !!elem->doffset + !!elem->doffsets) <= 1);
243bf215546Sopenharmony_ci
244bf215546Sopenharmony_ci	if (use_offset_fxn)
245bf215546Sopenharmony_ci		asprintf(&offsetfn, "__offset_%s", elem->name);
246bf215546Sopenharmony_ci
247bf215546Sopenharmony_ci	if (elem->length != 1) {
248bf215546Sopenharmony_ci		ADDARRAY(elems, elem);
249bf215546Sopenharmony_ci		ADDARRAY(offsetfns, offsetfn);
250bf215546Sopenharmony_ci	}
251bf215546Sopenharmony_ci
252bf215546Sopenharmony_ci	if (elem->name) {
253bf215546Sopenharmony_ci		char *regname;
254bf215546Sopenharmony_ci		if (str) {
255bf215546Sopenharmony_ci			asprintf(&regname, "REG_%s_%s", elem->fullname, str);
256bf215546Sopenharmony_ci		} else {
257bf215546Sopenharmony_ci			asprintf(&regname, "REG_%s", elem->fullname);
258bf215546Sopenharmony_ci		}
259bf215546Sopenharmony_ci		if (elemsnum) {
260bf215546Sopenharmony_ci			int len;
261bf215546Sopenharmony_ci			FILE *dst = findfout(elem->file);
262bf215546Sopenharmony_ci			int i;
263bf215546Sopenharmony_ci
264bf215546Sopenharmony_ci			if (use_offset_fxn) {
265bf215546Sopenharmony_ci				fprintf(dst, "static inline uint32_t %s(", offsetfn);
266bf215546Sopenharmony_ci				if (elem->index)
267bf215546Sopenharmony_ci					fprintf(dst, "enum %s", elem->index->name);
268bf215546Sopenharmony_ci				else
269bf215546Sopenharmony_ci					fprintf(dst, "uint32_t");
270bf215546Sopenharmony_ci				fprintf(dst, " idx)\n");
271bf215546Sopenharmony_ci				fprintf(dst, "{\n");
272bf215546Sopenharmony_ci				if (elem->doffset) {
273bf215546Sopenharmony_ci					fprintf(dst, "\treturn (%s) + (%#" PRIx64 "*idx);\n", elem->doffset, elem->stride);
274bf215546Sopenharmony_ci				} else {
275bf215546Sopenharmony_ci					int valuesnum = elem->doffsets ? elem->doffsetsnum : elem->offsetsnum;
276bf215546Sopenharmony_ci
277bf215546Sopenharmony_ci					fprintf(dst, "\tswitch (idx) {\n");
278bf215546Sopenharmony_ci					for (i = 0; i < valuesnum; i++) {
279bf215546Sopenharmony_ci						struct rnnvalue *val = NULL;
280bf215546Sopenharmony_ci						fprintf(dst, "\t\tcase ");
281bf215546Sopenharmony_ci						if (elem->index) {
282bf215546Sopenharmony_ci							int j;
283bf215546Sopenharmony_ci							for (j = 0; j < elem->index->valsnum; j++) {
284bf215546Sopenharmony_ci								if (elem->index->vals[j]->value == i) {
285bf215546Sopenharmony_ci									val = elem->index->vals[j];
286bf215546Sopenharmony_ci									break;
287bf215546Sopenharmony_ci								}
288bf215546Sopenharmony_ci							}
289bf215546Sopenharmony_ci						}
290bf215546Sopenharmony_ci						if (val) {
291bf215546Sopenharmony_ci							fprintf(dst, "%s", val->name);
292bf215546Sopenharmony_ci						} else {
293bf215546Sopenharmony_ci							fprintf(dst, "%d", i);
294bf215546Sopenharmony_ci						}
295bf215546Sopenharmony_ci						if (elem->offsets) {
296bf215546Sopenharmony_ci							fprintf(dst, ": return 0x%08"PRIx64";\n", elem->offsets[i]);
297bf215546Sopenharmony_ci						} else {
298bf215546Sopenharmony_ci							fprintf(dst, ": return (%s);\n", elem->doffsets[i]);
299bf215546Sopenharmony_ci						}
300bf215546Sopenharmony_ci					}
301bf215546Sopenharmony_ci					fprintf(dst, "\t\tdefault: return INVALID_IDX(idx);\n");
302bf215546Sopenharmony_ci					fprintf(dst, "\t}\n");
303bf215546Sopenharmony_ci				}
304bf215546Sopenharmony_ci				fprintf(dst, "}\n");
305bf215546Sopenharmony_ci			}
306bf215546Sopenharmony_ci			fprintf (dst, "static inline uint32_t %s(", regname);
307bf215546Sopenharmony_ci			for (i = 0; i < elemsnum; i++) {
308bf215546Sopenharmony_ci				if (i)
309bf215546Sopenharmony_ci					fprintf(dst, ", ");
310bf215546Sopenharmony_ci				if (elems[i]->index)
311bf215546Sopenharmony_ci					fprintf(dst, "enum %s ", elems[i]->index->name);
312bf215546Sopenharmony_ci				else
313bf215546Sopenharmony_ci					fprintf(dst, "uint32_t ");
314bf215546Sopenharmony_ci				fprintf (dst, "i%d%n", i, &len);
315bf215546Sopenharmony_ci			}
316bf215546Sopenharmony_ci			fprintf (dst, ") { return ");
317bf215546Sopenharmony_ci			fprintf (dst, "0x%08"PRIx64"", offset + elem->offset);
318bf215546Sopenharmony_ci			for (i = 0; i < elemsnum; i++) {
319bf215546Sopenharmony_ci				if (offsetfns[i])
320bf215546Sopenharmony_ci					fprintf(dst, " + %s(i%d)", offsetfns[i], i);
321bf215546Sopenharmony_ci				else
322bf215546Sopenharmony_ci					fprintf (dst, " + %#" PRIx64 "*i%d", elems[i]->stride, i);
323bf215546Sopenharmony_ci			}
324bf215546Sopenharmony_ci			fprintf (dst, "; }\n");
325bf215546Sopenharmony_ci		} else
326bf215546Sopenharmony_ci			printdef (regname, 0, 0, offset + elem->offset, elem->file);
327bf215546Sopenharmony_ci
328bf215546Sopenharmony_ci		free(regname);
329bf215546Sopenharmony_ci/*
330bf215546Sopenharmony_ci		if (elem->stride)
331bf215546Sopenharmony_ci			printdef (elem->fullname, "ESIZE", 0, elem->stride, elem->file);
332bf215546Sopenharmony_ci		if (elem->length != 1)
333bf215546Sopenharmony_ci			printdef (elem->fullname, "LEN", 0, elem->length, elem->file);
334bf215546Sopenharmony_ci*/
335bf215546Sopenharmony_ci		printtypeinfo (&elem->typeinfo, NULL, elem->fullname, elem->file);
336bf215546Sopenharmony_ci	}
337bf215546Sopenharmony_ci	fprintf (findfout(elem->file), "\n");
338bf215546Sopenharmony_ci	int j;
339bf215546Sopenharmony_ci	for (j = 0; j < elem->subelemsnum; j++) {
340bf215546Sopenharmony_ci		printdelem(elem->subelems[j], offset + elem->offset, elem->varinfo.prefixstr);
341bf215546Sopenharmony_ci	}
342bf215546Sopenharmony_ci	if (elem->length != 1) {
343bf215546Sopenharmony_ci		elemsnum--;
344bf215546Sopenharmony_ci		offsetfnsnum--;
345bf215546Sopenharmony_ci	}
346bf215546Sopenharmony_ci	free(offsetfn);
347bf215546Sopenharmony_ci}
348bf215546Sopenharmony_ci
349bf215546Sopenharmony_cistatic void print_file_info_(FILE *dst, struct stat* sb, struct tm* tm)
350bf215546Sopenharmony_ci{
351bf215546Sopenharmony_ci	char timestr[64];
352bf215546Sopenharmony_ci	strftime(timestr, sizeof(timestr), "%Y-%m-%d %H:%M:%S", tm);
353bf215546Sopenharmony_ci	fprintf(dst, "(%7Lu bytes, from %s)\n", (unsigned long long)sb->st_size, timestr);
354bf215546Sopenharmony_ci}
355bf215546Sopenharmony_ci
356bf215546Sopenharmony_cistatic void print_file_info(FILE *dst, const char* file)
357bf215546Sopenharmony_ci{
358bf215546Sopenharmony_ci	struct stat sb;
359bf215546Sopenharmony_ci	struct tm tm;
360bf215546Sopenharmony_ci	stat(file, &sb);
361bf215546Sopenharmony_ci	gmtime_r(&sb.st_mtime, &tm);
362bf215546Sopenharmony_ci	print_file_info_(dst, &sb, &tm);
363bf215546Sopenharmony_ci}
364bf215546Sopenharmony_ci
365bf215546Sopenharmony_cistatic void printhead(struct fout f, struct rnndb *db) {
366bf215546Sopenharmony_ci	int i, j;
367bf215546Sopenharmony_ci	struct stat sb;
368bf215546Sopenharmony_ci	struct tm tm;
369bf215546Sopenharmony_ci	stat(f.name, &sb);
370bf215546Sopenharmony_ci	gmtime_r(&sb.st_mtime, &tm);
371bf215546Sopenharmony_ci	fprintf (f.file, "#ifndef %s\n", f.guard);
372bf215546Sopenharmony_ci	fprintf (f.file, "#define %s\n", f.guard);
373bf215546Sopenharmony_ci	fprintf (f.file, "\n");
374bf215546Sopenharmony_ci	fprintf(f.file,
375bf215546Sopenharmony_ci		"/* Autogenerated file, DO NOT EDIT manually!\n"
376bf215546Sopenharmony_ci		"\n"
377bf215546Sopenharmony_ci		"This file was generated by the rules-ng-ng headergen tool in this git repository:\n"
378bf215546Sopenharmony_ci		"http://github.com/freedreno/envytools/\n"
379bf215546Sopenharmony_ci		"git clone https://github.com/freedreno/envytools.git\n"
380bf215546Sopenharmony_ci		"\n"
381bf215546Sopenharmony_ci		"The rules-ng-ng source files this header was generated from are:\n");
382bf215546Sopenharmony_ci	unsigned maxlen = 0;
383bf215546Sopenharmony_ci	for(i = 0; i < db->filesnum; ++i) {
384bf215546Sopenharmony_ci		unsigned len = strlen(db->files[i]);
385bf215546Sopenharmony_ci		if(len > maxlen)
386bf215546Sopenharmony_ci			maxlen = len;
387bf215546Sopenharmony_ci	}
388bf215546Sopenharmony_ci	for(i = 0; i < db->filesnum; ++i) {
389bf215546Sopenharmony_ci		unsigned len = strlen(db->files[i]);
390bf215546Sopenharmony_ci		fprintf(f.file, "- %s%*s ", db->files[i], maxlen - len, "");
391bf215546Sopenharmony_ci		print_file_info(f.file, db->files[i]);
392bf215546Sopenharmony_ci	}
393bf215546Sopenharmony_ci	fprintf(f.file,
394bf215546Sopenharmony_ci		"\n"
395bf215546Sopenharmony_ci		"Copyright (C) ");
396bf215546Sopenharmony_ci	if(db->copyright.firstyear && db->copyright.firstyear < (1900 + tm.tm_year))
397bf215546Sopenharmony_ci		fprintf(f.file, "%u-", db->copyright.firstyear);
398bf215546Sopenharmony_ci	fprintf(f.file, "%u", 1900 + tm.tm_year);
399bf215546Sopenharmony_ci	if(db->copyright.authorsnum) {
400bf215546Sopenharmony_ci		fprintf(f.file, " by the following authors:");
401bf215546Sopenharmony_ci		for(i = 0; i < db->copyright.authorsnum; ++i) {
402bf215546Sopenharmony_ci			fprintf(f.file, "\n- ");
403bf215546Sopenharmony_ci			if(db->copyright.authors[i]->name)
404bf215546Sopenharmony_ci				fprintf(f.file, "%s", db->copyright.authors[i]->name);
405bf215546Sopenharmony_ci			if(db->copyright.authors[i]->email)
406bf215546Sopenharmony_ci				fprintf(f.file, " <%s>", db->copyright.authors[i]->email);
407bf215546Sopenharmony_ci			if(db->copyright.authors[i]->nicknamesnum) {
408bf215546Sopenharmony_ci				for(j = 0; j < db->copyright.authors[i]->nicknamesnum; ++j) {
409bf215546Sopenharmony_ci					fprintf(f.file, "%s%s", (j ? ", " : " ("), db->copyright.authors[i]->nicknames[j]);
410bf215546Sopenharmony_ci				}
411bf215546Sopenharmony_ci				fprintf(f.file, ")");
412bf215546Sopenharmony_ci			}
413bf215546Sopenharmony_ci		}
414bf215546Sopenharmony_ci	}
415bf215546Sopenharmony_ci	fprintf(f.file, "\n");
416bf215546Sopenharmony_ci	if(db->copyright.license)
417bf215546Sopenharmony_ci		fprintf(f.file, "\n%s\n", db->copyright.license);
418bf215546Sopenharmony_ci	fprintf(f.file, "*/\n\n\n");
419bf215546Sopenharmony_ci}
420bf215546Sopenharmony_ci
421bf215546Sopenharmony_ciint main(int argc, char **argv) {
422bf215546Sopenharmony_ci	char *file;
423bf215546Sopenharmony_ci	struct rnndb *db;
424bf215546Sopenharmony_ci	int i, j;
425bf215546Sopenharmony_ci
426bf215546Sopenharmony_ci	if (argc < 2) {
427bf215546Sopenharmony_ci		fprintf(stderr, "Usage:\n\theadergen database-file\n");
428bf215546Sopenharmony_ci		exit(1);
429bf215546Sopenharmony_ci	}
430bf215546Sopenharmony_ci
431bf215546Sopenharmony_ci	if ((argc >= 3) && !strcmp(argv[1], "--no-asserts")) {
432bf215546Sopenharmony_ci		no_asserts = true;
433bf215546Sopenharmony_ci		file = argv[2];
434bf215546Sopenharmony_ci	} else {
435bf215546Sopenharmony_ci		file = argv[1];
436bf215546Sopenharmony_ci	}
437bf215546Sopenharmony_ci
438bf215546Sopenharmony_ci	rnn_init();
439bf215546Sopenharmony_ci	db = rnn_newdb();
440bf215546Sopenharmony_ci	rnn_parsefile (db, file);
441bf215546Sopenharmony_ci	rnn_prepdb (db);
442bf215546Sopenharmony_ci	for(i = 0; i < db->filesnum; ++i) {
443bf215546Sopenharmony_ci		char *dstname = malloc(strlen(db->files[i]) + 3);
444bf215546Sopenharmony_ci		char *pretty;
445bf215546Sopenharmony_ci		strcpy(dstname, db->files[i]);
446bf215546Sopenharmony_ci		strcat(dstname, ".h");
447bf215546Sopenharmony_ci		struct fout f = { db->files[i], fopen(dstname, "w") };
448bf215546Sopenharmony_ci		if (!f.file) {
449bf215546Sopenharmony_ci			perror(dstname);
450bf215546Sopenharmony_ci			exit(1);
451bf215546Sopenharmony_ci		}
452bf215546Sopenharmony_ci		free(dstname);
453bf215546Sopenharmony_ci		pretty = strrchr(f.name, '/');
454bf215546Sopenharmony_ci		if (pretty)
455bf215546Sopenharmony_ci			pretty += 1;
456bf215546Sopenharmony_ci		else
457bf215546Sopenharmony_ci			pretty = f.name;
458bf215546Sopenharmony_ci		f.guard = strdup(pretty);
459bf215546Sopenharmony_ci		for (j = 0; j < strlen(f.guard); j++)
460bf215546Sopenharmony_ci			if (isalnum(f.guard[j]))
461bf215546Sopenharmony_ci				f.guard[j] = toupper(f.guard[j]);
462bf215546Sopenharmony_ci			else
463bf215546Sopenharmony_ci				f.guard[j] = '_';
464bf215546Sopenharmony_ci		ADDARRAY(fouts, f);
465bf215546Sopenharmony_ci		printhead(f, db);
466bf215546Sopenharmony_ci	}
467bf215546Sopenharmony_ci
468bf215546Sopenharmony_ci	for (i = 0; i < db->enumsnum; i++) {
469bf215546Sopenharmony_ci		FILE *dst = NULL;
470bf215546Sopenharmony_ci		int j;
471bf215546Sopenharmony_ci		for (j = 0; j < db->enums[i]->valsnum; j++) {
472bf215546Sopenharmony_ci			if (!dst) {
473bf215546Sopenharmony_ci				dst = findfout(db->enums[i]->vals[j]->file);
474bf215546Sopenharmony_ci				fprintf(dst, "enum %s {\n", db->enums[i]->name);
475bf215546Sopenharmony_ci			}
476bf215546Sopenharmony_ci			if (0xffff0000 & db->enums[i]->vals[j]->value)
477bf215546Sopenharmony_ci				fprintf(dst, "\t%s = 0x%08"PRIx64",\n", db->enums[i]->vals[j]->name,
478bf215546Sopenharmony_ci						db->enums[i]->vals[j]->value);
479bf215546Sopenharmony_ci			else
480bf215546Sopenharmony_ci				fprintf(dst, "\t%s = %"PRIu64",\n", db->enums[i]->vals[j]->name,
481bf215546Sopenharmony_ci						db->enums[i]->vals[j]->value);
482bf215546Sopenharmony_ci		}
483bf215546Sopenharmony_ci		if (dst) {
484bf215546Sopenharmony_ci			fprintf(dst, "};\n\n");
485bf215546Sopenharmony_ci		}
486bf215546Sopenharmony_ci	}
487bf215546Sopenharmony_ci	for (i = 0; i < db->bitsetsnum; i++) {
488bf215546Sopenharmony_ci		if (db->bitsets[i]->isinline)
489bf215546Sopenharmony_ci			continue;
490bf215546Sopenharmony_ci		int j;
491bf215546Sopenharmony_ci		for (j = 0; j < db->bitsets[i]->bitfieldsnum; j++)
492bf215546Sopenharmony_ci			printbitfield (db->bitsets[i]->bitfields[j], 0);
493bf215546Sopenharmony_ci	}
494bf215546Sopenharmony_ci	for (i = 0; i < db->domainsnum; i++) {
495bf215546Sopenharmony_ci		if (db->domains[i]->size)
496bf215546Sopenharmony_ci			printdef (db->domains[i]->fullname, "SIZE", 0, db->domains[i]->size, db->domains[i]->file);
497bf215546Sopenharmony_ci		int j;
498bf215546Sopenharmony_ci		for (j = 0; j < db->domains[i]->subelemsnum; j++) {
499bf215546Sopenharmony_ci			printdelem(db->domains[i]->subelems[j], 0, NULL);
500bf215546Sopenharmony_ci		}
501bf215546Sopenharmony_ci	}
502bf215546Sopenharmony_ci	for(i = 0; i < foutsnum; ++i) {
503bf215546Sopenharmony_ci		fprintf (fouts[i].file, "\n#endif /* %s */\n", fouts[i].guard);
504bf215546Sopenharmony_ci	}
505bf215546Sopenharmony_ci	return db->estatus;
506bf215546Sopenharmony_ci}
507