Linux Audio

Check our new training course

Loading...
Note: File does not exist in v5.4.
  1// SPDX-License-Identifier: MIT
  2/*
  3 * Copyright © 2023 Intel Corporation
  4 */
  5
  6#define _GNU_SOURCE
  7#include <ctype.h>
  8#include <errno.h>
  9#include <stdbool.h>
 10#include <stdio.h>
 11#include <string.h>
 12
 13#define HEADER \
 14	"// SPDX-License-Identifier: MIT\n" \
 15	"\n" \
 16	"/*\n" \
 17	" * DO NOT MODIFY.\n" \
 18	" *\n" \
 19	" * This file was generated from rules: %s\n" \
 20	" */\n" \
 21	"#ifndef _GENERATED_XE_WA_OOB_\n" \
 22	"#define _GENERATED_XE_WA_OOB_\n" \
 23	"\n" \
 24	"enum {\n"
 25
 26#define FOOTER \
 27	"};\n" \
 28	"\n" \
 29	"#endif\n"
 30
 31static void print_usage(FILE *f)
 32{
 33	fprintf(f, "usage: %s <input-rule-file> <generated-c-source-file> <generated-c-header-file>\n",
 34		program_invocation_short_name);
 35}
 36
 37static void print_parse_error(const char *err_msg, const char *line,
 38			      unsigned int lineno)
 39{
 40	fprintf(stderr, "ERROR: %s\nERROR: %u: %.60s\n",
 41		err_msg, lineno, line);
 42}
 43
 44static char *strip(char *line, size_t linelen)
 45{
 46	while (isspace(*(line + linelen)))
 47		linelen--;
 48
 49	line[linelen - 1] = '\0';
 50
 51	return  line + strspn(line, " \f\n\r\t\v");
 52}
 53
 54#define MAX_LINE_LEN 4096
 55static int parse(FILE *input, FILE *csource, FILE *cheader)
 56{
 57	char line[MAX_LINE_LEN + 1];
 58	char *name, *prev_name = NULL, *rules;
 59	unsigned int lineno = 0, idx = 0;
 60
 61	while (fgets(line, sizeof(line), input)) {
 62		size_t linelen;
 63		bool is_continuation;
 64
 65		if (line[0] == '\0' || line[0] == '#' || line[0] == '\n') {
 66			lineno++;
 67			continue;
 68		}
 69
 70		linelen = strlen(line);
 71		if (linelen == MAX_LINE_LEN) {
 72			print_parse_error("line too long", line, lineno);
 73			return -EINVAL;
 74		}
 75
 76		is_continuation = isspace(line[0]);
 77		name = strip(line, linelen);
 78
 79		if (!is_continuation) {
 80			name = strtok(name, " \t");
 81			rules = strtok(NULL, "");
 82		} else {
 83			if (!prev_name) {
 84				print_parse_error("invalid rule continuation",
 85						  line, lineno);
 86				return -EINVAL;
 87			}
 88
 89			rules = name;
 90			name = NULL;
 91		}
 92
 93		if (rules[0] == '\0') {
 94			print_parse_error("invalid empty rule\n", line, lineno);
 95			return -EINVAL;
 96		}
 97
 98		if (name) {
 99			fprintf(cheader, "\tXE_WA_OOB_%s = %u,\n", name, idx);
100
101			/* Close previous entry before starting a new one */
102			if (idx)
103				fprintf(csource, ") },\n");
104
105			fprintf(csource, "{ XE_RTP_NAME(\"%s\"),\n  XE_RTP_RULES(%s",
106				name, rules);
107			idx++;
108		} else {
109			fprintf(csource, ", OR,\n\t%s", rules);
110		}
111
112		lineno++;
113		if (!is_continuation)
114			prev_name = name;
115	}
116
117	/* Close last entry */
118	if (idx)
119		fprintf(csource, ") },\n");
120
121	fprintf(cheader, "\t_XE_WA_OOB_COUNT = %u\n", idx);
122
123	return 0;
124}
125
126int main(int argc, const char *argv[])
127{
128	enum {
129		ARGS_INPUT,
130		ARGS_CSOURCE,
131		ARGS_CHEADER,
132		_ARGS_COUNT
133	};
134	struct {
135		const char *fn;
136		const char *mode;
137		FILE *f;
138	} args[] = {
139		[ARGS_INPUT] = { .fn = argv[1], .mode = "r" },
140		[ARGS_CSOURCE] = { .fn = argv[2], .mode = "w" },
141		[ARGS_CHEADER] = { .fn = argv[3], .mode = "w" },
142	};
143	int ret = 1;
144
145	if (argc < 3) {
146		fprintf(stderr, "ERROR: wrong arguments\n");
147		print_usage(stderr);
148		return 1;
149	}
150
151	for (int i = 0; i < _ARGS_COUNT; i++) {
152		args[i].f = fopen(args[i].fn, args[i].mode);
153		if (!args[i].f) {
154			fprintf(stderr, "ERROR: Can't open %s: %m\n",
155				args[i].fn);
156			goto err;
157		}
158	}
159
160	fprintf(args[ARGS_CHEADER].f, HEADER, args[ARGS_INPUT].fn);
161	ret = parse(args[ARGS_INPUT].f, args[ARGS_CSOURCE].f,
162		    args[ARGS_CHEADER].f);
163	if (!ret)
164		fprintf(args[ARGS_CHEADER].f, FOOTER);
165
166err:
167	for (int i = 0; i < _ARGS_COUNT; i++) {
168		if (args[i].f)
169			fclose(args[i].f);
170	}
171
172	return ret;
173}