174 lines
3.4 KiB
C
174 lines
3.4 KiB
C
|
// SPDX-License-Identifier: MIT
|
||
|
/*
|
||
|
* Copyright © 2023 Intel Corporation
|
||
|
*/
|
||
|
|
||
|
#define _GNU_SOURCE
|
||
|
#include <ctype.h>
|
||
|
#include <errno.h>
|
||
|
#include <stdbool.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
|
||
|
#define HEADER \
|
||
|
"// SPDX-License-Identifier: MIT\n" \
|
||
|
"\n" \
|
||
|
"/*\n" \
|
||
|
" * DO NOT MODIFY.\n" \
|
||
|
" *\n" \
|
||
|
" * This file was generated from rules: %s\n" \
|
||
|
" */\n" \
|
||
|
"#ifndef _GENERATED_XE_WA_OOB_\n" \
|
||
|
"#define _GENERATED_XE_WA_OOB_\n" \
|
||
|
"\n" \
|
||
|
"enum {\n"
|
||
|
|
||
|
#define FOOTER \
|
||
|
"};\n" \
|
||
|
"\n" \
|
||
|
"#endif\n"
|
||
|
|
||
|
static void print_usage(FILE *f)
|
||
|
{
|
||
|
fprintf(f, "usage: %s <input-rule-file> <generated-c-source-file> <generated-c-header-file>\n",
|
||
|
program_invocation_short_name);
|
||
|
}
|
||
|
|
||
|
static void print_parse_error(const char *err_msg, const char *line,
|
||
|
unsigned int lineno)
|
||
|
{
|
||
|
fprintf(stderr, "ERROR: %s\nERROR: %u: %.60s\n",
|
||
|
err_msg, lineno, line);
|
||
|
}
|
||
|
|
||
|
static char *strip(char *line, size_t linelen)
|
||
|
{
|
||
|
while (isspace(*(line + linelen)))
|
||
|
linelen--;
|
||
|
|
||
|
line[linelen - 1] = '\0';
|
||
|
|
||
|
return line + strspn(line, " \f\n\r\t\v");
|
||
|
}
|
||
|
|
||
|
#define MAX_LINE_LEN 4096
|
||
|
static int parse(FILE *input, FILE *csource, FILE *cheader)
|
||
|
{
|
||
|
char line[MAX_LINE_LEN + 1];
|
||
|
char *name, *prev_name = NULL, *rules;
|
||
|
unsigned int lineno = 0, idx = 0;
|
||
|
|
||
|
while (fgets(line, sizeof(line), input)) {
|
||
|
size_t linelen;
|
||
|
bool is_continuation;
|
||
|
|
||
|
if (line[0] == '\0' || line[0] == '#' || line[0] == '\n') {
|
||
|
lineno++;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
linelen = strlen(line);
|
||
|
if (linelen == MAX_LINE_LEN) {
|
||
|
print_parse_error("line too long", line, lineno);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
is_continuation = isspace(line[0]);
|
||
|
name = strip(line, linelen);
|
||
|
|
||
|
if (!is_continuation) {
|
||
|
name = strtok(name, " \t");
|
||
|
rules = strtok(NULL, "");
|
||
|
} else {
|
||
|
if (!prev_name) {
|
||
|
print_parse_error("invalid rule continuation",
|
||
|
line, lineno);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
rules = name;
|
||
|
name = NULL;
|
||
|
}
|
||
|
|
||
|
if (rules[0] == '\0') {
|
||
|
print_parse_error("invalid empty rule\n", line, lineno);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
if (name) {
|
||
|
fprintf(cheader, "\tXE_WA_OOB_%s = %u,\n", name, idx);
|
||
|
|
||
|
/* Close previous entry before starting a new one */
|
||
|
if (idx)
|
||
|
fprintf(csource, ") },\n");
|
||
|
|
||
|
fprintf(csource, "{ XE_RTP_NAME(\"%s\"),\n XE_RTP_RULES(%s",
|
||
|
name, rules);
|
||
|
idx++;
|
||
|
} else {
|
||
|
fprintf(csource, ", OR,\n\t%s", rules);
|
||
|
}
|
||
|
|
||
|
lineno++;
|
||
|
if (!is_continuation)
|
||
|
prev_name = name;
|
||
|
}
|
||
|
|
||
|
/* Close last entry */
|
||
|
if (idx)
|
||
|
fprintf(csource, ") },\n");
|
||
|
|
||
|
fprintf(cheader, "\t_XE_WA_OOB_COUNT = %u\n", idx);
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int main(int argc, const char *argv[])
|
||
|
{
|
||
|
enum {
|
||
|
ARGS_INPUT,
|
||
|
ARGS_CSOURCE,
|
||
|
ARGS_CHEADER,
|
||
|
_ARGS_COUNT
|
||
|
};
|
||
|
struct {
|
||
|
const char *fn;
|
||
|
const char *mode;
|
||
|
FILE *f;
|
||
|
} args[] = {
|
||
|
[ARGS_INPUT] = { .fn = argv[1], .mode = "r" },
|
||
|
[ARGS_CSOURCE] = { .fn = argv[2], .mode = "w" },
|
||
|
[ARGS_CHEADER] = { .fn = argv[3], .mode = "w" },
|
||
|
};
|
||
|
int ret = 1;
|
||
|
|
||
|
if (argc < 3) {
|
||
|
fprintf(stderr, "ERROR: wrong arguments\n");
|
||
|
print_usage(stderr);
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
for (int i = 0; i < _ARGS_COUNT; i++) {
|
||
|
args[i].f = fopen(args[i].fn, args[i].mode);
|
||
|
if (!args[i].f) {
|
||
|
fprintf(stderr, "ERROR: Can't open %s: %m\n",
|
||
|
args[i].fn);
|
||
|
goto err;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
fprintf(args[ARGS_CHEADER].f, HEADER, args[ARGS_INPUT].fn);
|
||
|
ret = parse(args[ARGS_INPUT].f, args[ARGS_CSOURCE].f,
|
||
|
args[ARGS_CHEADER].f);
|
||
|
if (!ret)
|
||
|
fprintf(args[ARGS_CHEADER].f, FOOTER);
|
||
|
|
||
|
err:
|
||
|
for (int i = 0; i < _ARGS_COUNT; i++) {
|
||
|
if (args[i].f)
|
||
|
fclose(args[i].f);
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
}
|