Change source files over to GPLv3.
[deliverable/binutils-gdb.git] / opcodes / i386-gen.c
CommitLineData
40b8e679
L
1/* Copyright 2007 Free Software Foundation, Inc.
2
9b201bb5 3 This file is part of the GNU opcodes library.
40b8e679 4
9b201bb5 5 This library is free software; you can redistribute it and/or modify
40b8e679 6 it under the terms of the GNU General Public License as published by
9b201bb5
NC
7 the Free Software Foundation; either version 3, or (at your option)
8 any later version.
40b8e679 9
9b201bb5
NC
10 It is distributed in the hope that it will be useful, but WITHOUT
11 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
12 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
13 License for more details.
40b8e679
L
14
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
9b201bb5
NC
17 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
18 MA 02110-1301, USA. */
40b8e679
L
19
20#include <stdio.h>
21#include <stdlib.h>
22#include <string.h>
23#include <errno.h>
24#include "getopt.h"
25#include "libiberty.h"
26#include "safe-ctype.h"
27
28#include "i386-opc.h"
29
30#include <libintl.h>
31#define _(String) gettext (String)
32
33static const char *program_name = NULL;
34static int debug = 0;
35
36static void
37fail (const char *message, ...)
38{
39 va_list args;
40
41 va_start (args, message);
42 fprintf (stderr, _("%s: Error: "), program_name);
43 vfprintf (stderr, message, args);
44 va_end (args);
45 xexit (1);
46}
47
48/* Remove leading white spaces. */
49
50static char *
51remove_leading_whitespaces (char *str)
52{
53 while (ISSPACE (*str))
54 str++;
55 return str;
56}
57
58/* Remove trailing white spaces. */
59
60static void
61remove_trailing_whitespaces (char *str)
62{
63 size_t last = strlen (str);
64
65 if (last == 0)
66 return;
67
68 do
69 {
70 last--;
71 if (ISSPACE (str [last]))
72 str[last] = '\0';
73 else
74 break;
75 }
76 while (last != 0);
77}
78
79/* Find next field separated by '.' and terminate it. Return a
80 pointer to the one after it. */
81
82static char *
83next_field (char *str, char **next)
84{
85 char *p;
86
87 p = remove_leading_whitespaces (str);
88 for (str = p; *str != ',' && *str != '\0'; str++);
89
90 *str = '\0';
91 remove_trailing_whitespaces (p);
92
93 *next = str + 1;
94
95 return p;
96}
97
98static void
99process_i386_opcodes (void)
100{
101 FILE *fp = fopen ("i386-opc.tbl", "r");
102 char buf[2048];
103 unsigned int i;
104 char *str, *p, *last;
105 char *name, *operands, *base_opcode, *extension_opcode;
106 char *cpu_flags, *opcode_modifier, *operand_types [MAX_OPERANDS];
107
108 if (fp == NULL)
109 fail (_("can't find i386-opc.tbl for reading\n"));
110
111 printf ("\n/* i386 opcode table. */\n\n");
112 printf ("const template i386_optab[] =\n{\n");
113
114 while (!feof (fp))
115 {
116 if (fgets (buf, sizeof (buf), fp) == NULL)
117 break;
118
119 p = remove_leading_whitespaces (buf);
120
121 /* Skip comments. */
122 str = strstr (p, "//");
123 if (str != NULL)
124 str[0] = '\0';
125
126 /* Remove trailing white spaces. */
127 remove_trailing_whitespaces (p);
128
129 switch (p[0])
130 {
131 case '#':
132 printf ("%s\n", p);
133 case '\0':
134 continue;
135 break;
136 default:
137 break;
138 }
139
140 last = p + strlen (p);
141
142 /* Find name. */
143 name = next_field (p, &str);
144
145 if (str >= last)
146 abort ();
147
148 /* Find number of operands. */
149 operands = next_field (str, &str);
150
151 if (str >= last)
152 abort ();
153
154 /* Find base_opcode. */
155 base_opcode = next_field (str, &str);
156
157 if (str >= last)
158 abort ();
159
160 /* Find extension_opcode. */
161 extension_opcode = next_field (str, &str);
162
163 if (str >= last)
164 abort ();
165
166 /* Find cpu_flags. */
167 cpu_flags = next_field (str, &str);
168
169 if (str >= last)
170 abort ();
171
172 /* Find opcode_modifier. */
173 opcode_modifier = next_field (str, &str);
174
175 if (str >= last)
176 abort ();
177
178 /* Remove the first {. */
179 str = remove_leading_whitespaces (str);
180 if (*str != '{')
181 abort ();
182 str = remove_leading_whitespaces (str + 1);
183
184 i = strlen (str);
185
186 /* There are at least "X}". */
187 if (i < 2)
188 abort ();
189
190 /* Remove trailing white spaces and }. */
191 do
192 {
193 i--;
194 if (ISSPACE (str[i]) || str[i] == '}')
195 str[i] = '\0';
196 else
197 break;
198 }
199 while (i != 0);
200
201 last = str + i;
202
203 /* Find operand_types. */
204 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
205 {
206 if (str >= last)
207 {
208 operand_types [i] = NULL;
209 break;
210 }
211
212 operand_types [i] = next_field (str, &str);
213 if (*operand_types[i] == '0')
214 {
215 if (i != 0)
216 operand_types[i] = NULL;
217 break;
218 }
219 }
220
221 printf (" { \"%s\", %s, %s, %s, %s,\n",
222 name, operands, base_opcode, extension_opcode,
223 cpu_flags);
224
225 printf (" %s,\n", opcode_modifier);
226
227 printf (" { ");
228
229 for (i = 0; i < ARRAY_SIZE (operand_types); i++)
230 {
231 if (operand_types[i] == NULL
232 || *operand_types[i] == '0')
233 {
234 if (i == 0)
235 printf ("0");
236 break;
237 }
238
239 if (i != 0)
240 printf (",\n ");
241
242 printf ("%s", operand_types[i]);
243 }
244 printf (" } },\n");
245 }
246
247 printf (" { NULL, 0, 0, 0, 0, 0, { 0 } }\n");
248 printf ("};\n");
249}
250
251static void
252process_i386_registers (void)
253{
254 FILE *fp = fopen ("i386-reg.tbl", "r");
255 char buf[2048];
256 char *str, *p, *last;
257 char *reg_name, *reg_type, *reg_flags, *reg_num;
258
259 if (fp == NULL)
260 fail (_("can't find i386-reg.tbl for reading\n"));
261
262 printf ("\n/* i386 register table. */\n\n");
263 printf ("const reg_entry i386_regtab[] =\n{\n");
264
265 while (!feof (fp))
266 {
267 if (fgets (buf, sizeof (buf), fp) == NULL)
268 break;
269
270 p = remove_leading_whitespaces (buf);
271
272 /* Skip comments. */
273 str = strstr (p, "//");
274 if (str != NULL)
275 str[0] = '\0';
276
277 /* Remove trailing white spaces. */
278 remove_trailing_whitespaces (p);
279
280 switch (p[0])
281 {
282 case '#':
283 printf ("%s\n", p);
284 case '\0':
285 continue;
286 break;
287 default:
288 break;
289 }
290
291 last = p + strlen (p);
292
293 /* Find reg_name. */
294 reg_name = next_field (p, &str);
295
296 if (str >= last)
297 abort ();
298
299 /* Find reg_type. */
300 reg_type = next_field (str, &str);
301
302 if (str >= last)
303 abort ();
304
305 /* Find reg_flags. */
306 reg_flags = next_field (str, &str);
307
308 if (str >= last)
309 abort ();
310
311 /* Find reg_num. */
312 reg_num = next_field (str, &str);
313
314 printf (" { \"%s\", %s, %s, %s },\n",
315 reg_name, reg_type, reg_flags, reg_num);
316 }
317
318 printf ("};\n");
319
320 printf ("\nconst unsigned int i386_regtab_size = ARRAY_SIZE (i386_regtab);\n");
321}
322
323/* Program options. */
324#define OPTION_SRCDIR 200
325
326struct option long_options[] =
327{
328 {"srcdir", required_argument, NULL, OPTION_SRCDIR},
329 {"debug", no_argument, NULL, 'd'},
330 {"version", no_argument, NULL, 'V'},
331 {"help", no_argument, NULL, 'h'},
332 {0, no_argument, NULL, 0}
333};
334
335static void
336print_version (void)
337{
338 printf ("%s: version 1.0\n", program_name);
339 xexit (0);
340}
341
342static void
343usage (FILE * stream, int status)
344{
345 fprintf (stream, "Usage: %s [-V | --version] [-d | --debug] [--srcdir=dirname] [--help]\n",
346 program_name);
347 xexit (status);
348}
349
350int
351main (int argc, char **argv)
352{
353 extern int chdir (char *);
354 char *srcdir = NULL;
355 int c;
356
357 program_name = *argv;
358 xmalloc_set_program_name (program_name);
359
360 while ((c = getopt_long (argc, argv, "vVdh", long_options, 0)) != EOF)
361 switch (c)
362 {
363 case OPTION_SRCDIR:
364 srcdir = optarg;
365 break;
366 case 'V':
367 case 'v':
368 print_version ();
369 break;
370 case 'd':
371 debug = 1;
372 break;
373 case 'h':
374 case '?':
375 usage (stderr, 0);
376 default:
377 case 0:
378 break;
379 }
380
381 if (optind != argc)
382 usage (stdout, 1);
383
384 if (srcdir != NULL)
385 if (chdir (srcdir) != 0)
386 fail (_("unable to change directory to \"%s\", errno = %s\n"),
387 srcdir, strerror (errno));
388
389 printf ("/* This file is automatically generated by i386-gen. Do not edit! */\n");
9b201bb5
NC
390 printf ("/* Copyright 2007 Free Software Foundation, Inc.\n\
391\n\
392 This file is part of the GNU opcodes library.\n\
393\n\
394 This library is free software; you can redistribute it and/or modify\n\
395 it under the terms of the GNU General Public License as published by\n\
396 the Free Software Foundation; either version 3, or (at your option)\n\
397 any later version.\n\
398\n\
399 It is distributed in the hope that it will be useful, but WITHOUT\n\
400 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\n\
401 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public\n\
402 License for more details.\n\
403\n\
404 You should have received a copy of the GNU General Public License\n\
405 along with this program; if not, write to the Free Software\n\
406 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,\n\
407 MA 02110-1301, USA. */");
40b8e679
L
408
409 process_i386_opcodes ();
410 process_i386_registers ();
411
412 exit (0);
413}
This page took 0.053164 seconds and 4 git commands to generate.