Merge tag 'for-6.8-rc6-tag' of git://git.kernel.org/pub/scm/linux/kernel/git/kdave...
[linux-block.git] / drivers / gpu / drm / xe / xe_gen_wa_oob.c
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
31 static 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
37 static 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
44 static 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
55 static 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                         fprintf(csource, "{ XE_RTP_NAME(\"%s\"), XE_RTP_RULES(%s) },\n",
101                                 name, rules);
102                 } else {
103                         fprintf(csource, "{ XE_RTP_NAME(NULL), XE_RTP_RULES(%s) },\n",
104                                 rules);
105                 }
106
107                 idx++;
108                 lineno++;
109                 if (!is_continuation)
110                         prev_name = name;
111         }
112
113         fprintf(cheader, "\t_XE_WA_OOB_COUNT = %u\n", idx);
114
115         return 0;
116 }
117
118 int main(int argc, const char *argv[])
119 {
120         enum {
121                 ARGS_INPUT,
122                 ARGS_CSOURCE,
123                 ARGS_CHEADER,
124                 _ARGS_COUNT
125         };
126         struct {
127                 const char *fn;
128                 const char *mode;
129                 FILE *f;
130         } args[] = {
131                 [ARGS_INPUT] = { .fn = argv[1], .mode = "r" },
132                 [ARGS_CSOURCE] = { .fn = argv[2], .mode = "w" },
133                 [ARGS_CHEADER] = { .fn = argv[3], .mode = "w" },
134         };
135         int ret = 1;
136
137         if (argc < 3) {
138                 fprintf(stderr, "ERROR: wrong arguments\n");
139                 print_usage(stderr);
140                 return 1;
141         }
142
143         for (int i = 0; i < _ARGS_COUNT; i++) {
144                 args[i].f = fopen(args[i].fn, args[i].mode);
145                 if (!args[i].f) {
146                         fprintf(stderr, "ERROR: Can't open %s: %m\n",
147                                 args[i].fn);
148                         goto err;
149                 }
150         }
151
152         fprintf(args[ARGS_CHEADER].f, HEADER, args[ARGS_INPUT].fn);
153         ret = parse(args[ARGS_INPUT].f, args[ARGS_CSOURCE].f,
154                     args[ARGS_CHEADER].f);
155         if (!ret)
156                 fprintf(args[ARGS_CHEADER].f, FOOTER);
157
158 err:
159         for (int i = 0; i < _ARGS_COUNT; i++) {
160                 if (args[i].f)
161                         fclose(args[i].f);
162         }
163
164         return ret;
165 }