1 /* This file is part of the gf2x library.
2 
3    Copyright 2007, 2008, 2009, 2010, 2013, 2015
4    Richard Brent, Pierrick Gaudry, Emmanuel Thome', Paul Zimmermann
5 
6    This program is free software; you can redistribute it and/or modify it
7    under the terms of either:
8     - If the archive contains a file named toom-gpl.c (not a trivial
9     placeholder), the GNU General Public License as published by the Free
10     Software Foundation; either version 3 of the License, or (at your
11     option) any later version.
12     - If the archive contains a file named toom-gpl.c which is a trivial
13     placeholder, the GNU Lesser General Public License as published by
14     the Free Software Foundation; either version 2.1 of the License, or
15     (at your option) any later version.
16 
17    This program is distributed in the hope that it will be useful, but WITHOUT
18    ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
19    FITNESS FOR A PARTICULAR PURPOSE.  See the license text for more details.
20 
21    You should have received a copy of the GNU General Public License as
22    well as the GNU Lesser General Public License along with this program;
23    see the files COPYING and COPYING.LIB.  If not, write to the Free
24    Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
25    02110-1301, USA.
26 */
27 
28 /* Helper program for rewriting headers after tuning. */
29 
30 #define _GNU_SOURCE
31 
32 #include <stdlib.h>
33 #include <stdio.h>
34 #include <string.h>
35 #include <ctype.h>
36 #include "replace.h"
37 
set_hash_define_int(struct hash_define * ptr,const char * name,int x)38 void set_hash_define_int(struct hash_define * ptr, const char * name, int x)
39 {
40     ptr->identifier = strdup(name);
41     ptr->string = malloc(32);
42     snprintf(ptr->string, 32, "%d", x);
43 }
44 
set_hash_define(struct hash_define * ptr,const char * name,const char * v)45 void set_hash_define(struct hash_define * ptr, const char * name, const char *v)
46 {
47     ptr->identifier = strdup(name);
48     ptr->string = strdup(v);
49     unsigned long l = strlen(ptr->string);
50     for( ; l && isspace(ptr->string[l-1]) ; l--);
51     ptr->string[l] = '\0';
52 }
53 
54 
55 typedef int (*sortfunc_t) (const void *, const void *);
cmp_hash_define(struct hash_define * a,struct hash_define * b)56 int cmp_hash_define(struct hash_define * a, struct hash_define * b)
57 {
58     return strcmp(a->identifier, b->identifier);
59 }
search_hash_define(const char * a,struct hash_define * b)60 int search_hash_define(const char * a, struct hash_define * b)
61 {
62     return strcmp(a, b->identifier);
63 }
64 
65 
replace(struct hash_define * ptr,unsigned long n,const char * fname)66 void replace(struct hash_define * ptr, unsigned long n, const char * fname)
67 {
68 
69     qsort(ptr, n, sizeof(struct hash_define), (sortfunc_t) & cmp_hash_define);
70 
71     FILE * fi, * fo;
72     char * fname_out;
73     size_t sl = strlen(fname)+10;
74     char buffer[1024];
75     char id[80];
76 
77     fname_out = malloc(sl);
78     snprintf(fname_out,sl,"%s.new",fname);
79 
80     fi = fopen(fname, "r");
81     fo = fopen(fname_out, "w");
82 
83     for (;!feof(fi);) {
84         const char * x, *y;
85         if (fgets(buffer, sizeof(buffer), fi) == NULL) {
86             /* EOF, most certainly */
87             break;
88         }
89 #define	IS_HDEFINE(X)	(strncmp(X,"#define",7) == 0)
90 #define	IS_HUNDEF(X)	(strncmp(X,"#undef",6) == 0)
91         if (!(IS_HDEFINE(buffer) || IS_HUNDEF(buffer))) {
92             fputs(buffer, fo);
93             continue;
94         }
95         x = buffer;
96         for(;*x && !isspace(*x);x++);
97         for(;*x && isspace(*x);x++);
98         for(y=x;*y&&!isspace(*y);y++);
99         strncpy(id,x,y-x);
100         id[y-x]='\0';
101         /* identifier is id */
102         struct hash_define * loc;
103         loc = bsearch(id, ptr, n, sizeof(struct hash_define), (sortfunc_t) & search_hash_define);
104         if (loc == NULL) {
105             fputs(buffer, fo);
106             continue;
107         }
108         if (loc->string[0] == '\0') {
109             fprintf(stderr,
110                     "Error: replacement string %s used twice!\n",
111                     loc->identifier);
112             exit(1);
113         }
114         for( ;; ) {
115             x = buffer + strlen(buffer) - 1;
116             for( ; (x - buffer >= 0) && isspace(*x) ; x--);
117             /* If the current line was followed by a backslash, gobble
118              * the following line as well.
119              */
120             if ((x - buffer >= 0) && *x != '\\')
121                 break;
122             /* It's normally an error to arrive here, although there's
123              * not much questioning as to what to do in such a situation
124              */
125             if (fgets(buffer, sizeof(buffer), fi) == NULL)
126                 break;
127         }
128 
129         fprintf(fo,"#define %s\t\t%s\n", id, loc->string);
130         loc->string[0]='\0';
131     }
132     for(unsigned long i = 0 ; i < n ; i++) {
133         struct hash_define * loc = ptr + i;
134         if (loc->string[0] != '\0') {
135             fprintf(stderr, "Warning: replacement string %s not used ; value:\n%s\n", loc->identifier, loc->string);
136         }
137     }
138 
139     fclose(fi);
140     fclose(fo);
141     rename(fname_out, fname);
142 }
143