174 lines · c
1// SPDX-License-Identifier: MIT2/*3 * Copyright © 2023 Intel Corporation4 */5 6#define _GNU_SOURCE7#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 409655static 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_COUNT133 };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}174