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