exp: fix shift/reduce conflict complaints
[fio.git] / exp / fixup-buggy-yacc-output.c
CommitLineData
b470a02c
SC
1/*
2 * (C) Copyright 2014, Stephen M. Cameron.
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 */
18
19#include <stdio.h>
20#include <stdlib.h>
21#include <unistd.h>
22#include <sys/types.h>
23#include <sys/stat.h>
24#include <fcntl.h>
25#include <string.h>
26#include <errno.h>
27
28static char *programname;
29
30static char *slurp_file(char *f, off_t *textsize)
31{
32 int fd;
33 struct stat statbuf;
34 off_t bytesleft, bytesread;
35 char *fileptr = NULL;
36 char *slurped_file = NULL;
37
38 fd = open(f, O_RDONLY);
39 if (fd < 0) {
40 fprintf(stderr, "%s: Cannot open '%s': %s\n",
41 programname, f, strerror(errno));
42 return NULL;
43 }
44 if (fstat(fd, &statbuf) != 0) {
45 fprintf(stderr, "%s: Cannot stat '%s': %s\n",
46 programname, f, strerror(errno));
47 close(fd);
48 return NULL;
49 }
50 bytesleft = statbuf.st_size;
51 slurped_file = malloc(bytesleft + 1);
52 fileptr = slurped_file;
53 if (!slurped_file) {
54 fprintf(stderr, "%s: malloc returned NULL, out of memory\n",
55 programname);
56 goto bail_out;
57 }
58 memset(slurped_file, 0, bytesleft + 1);
59 do {
60 bytesread = read(fd, fileptr, bytesleft);
61 if (bytesread < 0 && errno == EAGAIN)
62 continue;
63 if (bytesread < 0) {
64 fprintf(stderr, "%s: error reading '%s: %s'\n",
65 programname, f, strerror(errno));
66 goto bail_out;
67 }
68 if (bytesread == 0) {
69 fprintf(stderr, "%s: unexpected EOF in %s\n",
70 programname, f);
71 goto bail_out;
72 }
73 fileptr += bytesread;
74 bytesleft -= bytesread;
75 } while (bytesleft > 0);
76
77 *textsize = statbuf.st_size;
78
79 close(fd);
80 return slurped_file;
81
82bail_out:
83 if (slurped_file)
84 free(slurped_file);
85 close(fd);
86 return NULL;
87}
88
89static int detect_buggy_yacc(char *text)
90{
91 char *x;
92
93 x = strstr(text, " #line ");
94 if (!x)
95 return 0;
96 return 1;
97}
98
99static void fixup_buggy_yacc_file(char *f)
100{
101 char *slurped_file, *x;
102 off_t textsize;
103 char *newname;
104 int fd;
105 off_t bytesleft, byteswritten;
106
107 newname = alloca(strlen(f) + 10);
108 strcpy(newname, "broken-");
109 strcat(newname, f);
110
111 slurped_file = slurp_file(f, &textsize);
112 if (!slurped_file)
113 return;
114 if (!detect_buggy_yacc(slurped_file))
115 return;
116
117 x = slurped_file;
118
119
120 /*
121 * Fixup the '#line' directives which yacc botched.
122 * Note: this is vulnerable to false positives, but
123 * since this program is just a hack to make this particular
124 * program work, it is sufficient for our purposes.
125 * regexp could make this better, but the real fix needs
126 * to be made in yacc/bison.
127 */
128 while ((x = strstr(x, " #line ")) != NULL) {
129 *x = '\n';
130 }
131
132 if (rename(f, newname) != 0) {
133 fprintf(stderr, "%s: Failed to rename '%s' to '%s': %s\n",
134 programname, f, newname, strerror(errno));
135 return;
136 }
137 fd = open(f, O_CREAT | O_TRUNC | O_RDWR, 0644);
138 if (fd < 0) {
139 fprintf(stderr, "%s: failed to create '%s': %s\n",
140 programname, f, strerror(errno));
141 return;
142 }
143
144 bytesleft = textsize;
145 x = slurped_file;
146 do {
147 byteswritten = write(fd, x, bytesleft);
148 if (byteswritten < 0) {
149 fprintf(stderr, "%s: Error writing '%s': %s\n",
150 programname, f, strerror(errno));
151 return;
152 }
153 if (byteswritten == 0 && errno == EINTR)
154 continue;
155 x += byteswritten;
156 bytesleft -= byteswritten;
157 } while (bytesleft > 0);
158 close(fd);
159}
160
161int main(int argc, char *argv[])
162{
163 int i;
164
165 programname = argv[0];
166
167 for (i = 1; i < argc; i++)
168 fixup_buggy_yacc_file(argv[i]);
169 return 0;
170}