2 * (C) Copyright 2014, Stephen M. Cameron.
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.
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.
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
22 #include <sys/types.h>
28 static char *programname;
30 static char *slurp_file(char *f, off_t *textsize)
34 off_t bytesleft, bytesread;
36 char *slurped_file = NULL;
38 fd = open(f, O_RDONLY);
40 fprintf(stderr, "%s: Cannot open '%s': %s\n",
41 programname, f, strerror(errno));
44 if (fstat(fd, &statbuf) != 0) {
45 fprintf(stderr, "%s: Cannot stat '%s': %s\n",
46 programname, f, strerror(errno));
50 bytesleft = statbuf.st_size;
51 slurped_file = malloc(bytesleft + 1);
52 fileptr = slurped_file;
54 fprintf(stderr, "%s: malloc returned NULL, out of memory\n",
58 memset(slurped_file, 0, bytesleft + 1);
60 bytesread = read(fd, fileptr, bytesleft);
61 if (bytesread < 0 && errno == EAGAIN)
64 fprintf(stderr, "%s: error reading '%s: %s'\n",
65 programname, f, strerror(errno));
69 fprintf(stderr, "%s: unexpected EOF in %s\n",
74 bytesleft -= bytesread;
75 } while (bytesleft > 0);
77 *textsize = statbuf.st_size;
89 static int detect_buggy_yacc(char *text)
93 x = strstr(text, " #line ");
99 static void fixup_buggy_yacc_file(char *f)
101 char *slurped_file, *x;
105 off_t bytesleft, byteswritten;
107 newname = alloca(strlen(f) + 10);
108 strcpy(newname, "broken-");
111 slurped_file = slurp_file(f, &textsize);
114 if (!detect_buggy_yacc(slurped_file))
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.
128 while ((x = strstr(x, " #line ")) != NULL) {
132 if (rename(f, newname) != 0) {
133 fprintf(stderr, "%s: Failed to rename '%s' to '%s': %s\n",
134 programname, f, newname, strerror(errno));
137 fd = open(f, O_CREAT | O_TRUNC | O_RDWR, 0644);
139 fprintf(stderr, "%s: failed to create '%s': %s\n",
140 programname, f, strerror(errno));
144 bytesleft = textsize;
147 byteswritten = write(fd, x, bytesleft);
148 if (byteswritten < 0) {
149 fprintf(stderr, "%s: Error writing '%s': %s\n",
150 programname, f, strerror(errno));
153 if (byteswritten == 0 && errno == EINTR)
156 bytesleft -= byteswritten;
157 } while (bytesleft > 0);
161 int main(int argc, char *argv[])
165 programname = argv[0];
167 for (i = 1; i < argc; i++)
168 fixup_buggy_yacc_file(argv[i]);