~ubuntu-branches/debian/jessie/ccache/jessie

« back to all changes in this revision

Viewing changes to unify.c

  • Committer: Bazaar Package Importer
  • Author(s): Loïc Minier
  • Date: 2010-10-13 17:14:13 UTC
  • mfrom: (5.1.1 sid)
  • Revision ID: james.westby@ubuntu.com-20101013171413-4ehrj1y89huf069u
Tags: 3.0.1-1ubuntu1
* Merge with Debian; remaining changes:
  - Add gcc/g++-4.4 and -4.5 symlinks.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
   Copyright (C) Andrew Tridgell 2002
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 as published by
6
 
   the Free Software Foundation; either version 2 of the License, or
7
 
   (at your option) any later version.
8
 
   
9
 
   This program is distributed in the hope that it will be useful,
10
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12
 
   GNU General Public License for more details.
13
 
   
14
 
   You should have received a copy of the GNU General Public License
15
 
   along with this program; if not, write to the Free Software
16
 
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
2
 * Copyright (C) 2002 Andrew Tridgell
 
3
 *
 
4
 * This program is free software; you can redistribute it and/or modify it
 
5
 * under the terms of the GNU General Public License as published by the Free
 
6
 * Software Foundation; either version 3 of the License, or (at your option)
 
7
 * any later version.
 
8
 *
 
9
 * This program is distributed in the hope that it will be useful, but WITHOUT
 
10
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 
11
 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
 
12
 * more details.
 
13
 *
 
14
 * You should have received a copy of the GNU General Public License along with
 
15
 * this program; if not, write to the Free Software Foundation, Inc., 51
 
16
 * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17
17
*/
 
18
 
18
19
/*
19
 
  C/C++ unifier
20
 
 
21
 
  the idea is that changes that don't affect the resulting C code
22
 
  should not change the hash. This is achieved by folding white-space
23
 
  and other non-semantic fluff in the input into a single unified format.
24
 
 
25
 
  This unifier was design to match the output of the unifier in
26
 
  compilercache, which is flex based. The major difference is that
27
 
  this unifier is much faster (about 2x) and more forgiving of
28
 
  syntactic errors. Continuing on syntactic errors is important to
29
 
  cope with C/C++ extensions in the local compiler (for example,
30
 
  inline assembly systems).  
31
 
*/
 
20
 * C/C++ unifier
 
21
 *
 
22
 * The idea is that changes that don't affect the resulting C code should not
 
23
 * change the hash. This is achieved by folding white-space and other
 
24
 * non-semantic fluff in the input into a single unified format.
 
25
 *
 
26
 * This unifier was design to match the output of the unifier in compilercache,
 
27
 * which is flex based. The major difference is that this unifier is much
 
28
 * faster (about 2x) and more forgiving of syntactic errors. Continuing on
 
29
 * syntactic errors is important to cope with C/C++ extensions in the local
 
30
 * compiler (for example, inline assembly systems).
 
31
 */
32
32
 
33
33
#include "ccache.h"
34
34
 
35
 
static char *s_tokens[] = {
 
35
#include <sys/types.h>
 
36
#include <sys/stat.h>
 
37
#include <sys/mman.h>
 
38
#include <ctype.h>
 
39
#include <fcntl.h>
 
40
#include <string.h>
 
41
#include <unistd.h>
 
42
 
 
43
static const char *const s_tokens[] = {
36
44
        "...",  ">>=",  "<<=",  "+=",   "-=",   "*=",   "/=",   "%=",   "&=",   "^=",
37
45
        "|=",   ">>",   "<<",   "++",   "--",   "->",   "&&",   "||",   "<=",   ">=",
38
46
        "==",   "!=",   ";",    "{",    "<%",   "}",    "%>",   ",",    ":",    "=",
53
61
static struct {
54
62
        unsigned char type;
55
63
        unsigned char num_toks;
56
 
        char *toks[7];
 
64
        const char *toks[7];
57
65
} tokens[256];
58
66
 
59
67
/* build up the table used by the unifier */
94
102
}
95
103
 
96
104
/* buffer up characters before hashing them */
97
 
static void pushchar(unsigned char c)
 
105
static void pushchar(struct mdfour *hash, unsigned char c)
98
106
{
99
107
        static unsigned char buf[64];
100
 
        static int len;
 
108
        static size_t len;
101
109
 
102
110
        if (c == 0) {
103
111
                if (len > 0) {
104
 
                        hash_buffer((char *)buf, len);
 
112
                        hash_buffer(hash, (char *)buf, len);
105
113
                        len = 0;
106
114
                }
107
 
                hash_buffer(NULL, 0);
 
115
                hash_buffer(hash, NULL, 0);
108
116
                return;
109
117
        }
110
118
 
111
119
        buf[len++] = c;
112
120
        if (len == 64) {
113
 
                hash_buffer((char *)buf, len);
 
121
                hash_buffer(hash, (char *)buf, len);
114
122
                len = 0;
115
123
        }
116
124
}
117
125
 
118
126
/* hash some C/C++ code after unifying */
119
 
static void unify(unsigned char *p, size_t size)
 
127
static void unify(struct mdfour *hash, unsigned char *p, size_t size)
120
128
{
121
129
        size_t ofs;
122
130
        unsigned char q;
133
141
                                ofs++;
134
142
                        } else {
135
143
                                do {
136
 
                                        pushchar(p[ofs]);
 
144
                                        pushchar(hash, p[ofs]);
137
145
                                        ofs++;
138
146
                                } while (ofs < size && p[ofs] != '\n');
139
 
                                pushchar('\n');
 
147
                                pushchar(hash, '\n');
140
148
                                ofs++;
141
149
                        }
142
150
                        continue;
144
152
 
145
153
                if (tokens[p[ofs]].type & C_ALPHA) {
146
154
                        do {
147
 
                                pushchar(p[ofs]);
 
155
                                pushchar(hash, p[ofs]);
148
156
                                ofs++;
149
 
                        } while (ofs < size && 
 
157
                        } while (ofs < size &&
150
158
                                 (tokens[p[ofs]].type & (C_ALPHA|C_DIGIT)));
151
 
                        pushchar('\n');
 
159
                        pushchar(hash, '\n');
152
160
                        continue;
153
161
                }
154
162
 
155
163
                if (tokens[p[ofs]].type & C_DIGIT) {
156
164
                        do {
157
 
                                pushchar(p[ofs]);
 
165
                                pushchar(hash, p[ofs]);
158
166
                                ofs++;
159
 
                        } while (ofs < size && 
 
167
                        } while (ofs < size &&
160
168
                                 ((tokens[p[ofs]].type & C_DIGIT) || p[ofs] == '.'));
161
169
                        if (ofs < size && (p[ofs] == 'x' || p[ofs] == 'X')) {
162
170
                                do {
163
 
                                        pushchar(p[ofs]);
 
171
                                        pushchar(hash, p[ofs]);
164
172
                                        ofs++;
165
173
                                } while (ofs < size && (tokens[p[ofs]].type & C_HEX));
166
174
                        }
167
175
                        if (ofs < size && (p[ofs] == 'E' || p[ofs] == 'e')) {
168
 
                                pushchar(p[ofs]);
 
176
                                pushchar(hash, p[ofs]);
169
177
                                ofs++;
170
 
                                while (ofs < size && 
 
178
                                while (ofs < size &&
171
179
                                       (tokens[p[ofs]].type & (C_DIGIT|C_SIGN))) {
172
 
                                        pushchar(p[ofs]);
 
180
                                        pushchar(hash, p[ofs]);
173
181
                                        ofs++;
174
182
                                }
175
183
                        }
176
184
                        while (ofs < size && (tokens[p[ofs]].type & C_FLOAT)) {
177
 
                                pushchar(p[ofs]);
 
185
                                pushchar(hash, p[ofs]);
178
186
                                ofs++;
179
187
                        }
180
 
                        pushchar('\n');
 
188
                        pushchar(hash, '\n');
181
189
                        continue;
182
190
                }
183
191
 
187
195
                        } while (ofs < size && (tokens[p[ofs]].type & C_SPACE));
188
196
                        continue;
189
197
                }
190
 
                        
 
198
 
191
199
                if (tokens[p[ofs]].type & C_QUOTE) {
192
200
                        q = p[ofs];
193
 
                        pushchar(p[ofs]);
 
201
                        pushchar(hash, p[ofs]);
194
202
                        do {
195
203
                                ofs++;
196
204
                                while (ofs < size-1 && p[ofs] == '\\') {
197
 
                                        pushchar(p[ofs]);
198
 
                                        pushchar(p[ofs+1]);
 
205
                                        pushchar(hash, p[ofs]);
 
206
                                        pushchar(hash, p[ofs+1]);
199
207
                                        ofs+=2;
200
208
                                }
201
 
                                pushchar(p[ofs]);
 
209
                                pushchar(hash, p[ofs]);
202
210
                        } while (ofs < size && p[ofs] != q);
203
 
                        pushchar('\n');
 
211
                        pushchar(hash, '\n');
204
212
                        ofs++;
205
213
                        continue;
206
214
                }
213
221
                                if (size >= ofs+len && memcmp(&p[ofs], s, len) == 0) {
214
222
                                        int j;
215
223
                                        for (j=0;s[j];j++) {
216
 
                                                pushchar(s[j]);
 
224
                                                pushchar(hash, s[j]);
217
225
                                                ofs++;
218
226
                                        }
219
 
                                        pushchar('\n');
 
227
                                        pushchar(hash, '\n');
220
228
                                        break;
221
229
                                }
222
230
                        }
225
233
                        }
226
234
                }
227
235
 
228
 
                pushchar(p[ofs]);
229
 
                pushchar('\n');
 
236
                pushchar(hash, p[ofs]);
 
237
                pushchar(hash, '\n');
230
238
                ofs++;
231
239
        }
232
 
        pushchar(0);
 
240
        pushchar(hash, 0);
233
241
}
234
242
 
235
243
 
236
 
/* hash a file that consists of preprocessor output, but remove any line 
 
244
/* hash a file that consists of preprocessor output, but remove any line
237
245
   number information from the hash
238
246
*/
239
 
int unify_hash(const char *fname)
 
247
int unify_hash(struct mdfour *hash, const char *fname)
240
248
{
241
249
        int fd;
242
 
        struct stat st; 
 
250
        struct stat st;
243
251
        char *map;
244
252
 
245
253
        fd = open(fname, O_RDONLY|O_BINARY);
246
254
        if (fd == -1 || fstat(fd, &st) != 0) {
247
 
                cc_log("Failed to open preprocessor output %s\n", fname);
 
255
                cc_log("Failed to open preprocessor output %s", fname);
248
256
                stats_update(STATS_PREPROCESSOR);
249
257
                return -1;
250
258
        }
253
261
           lines in preprocessor output. I have seen lines of over
254
262
           100k in length, so this is well worth it */
255
263
        map = mmap(NULL, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
 
264
        close(fd);
256
265
        if (map == (char *)-1) {
257
 
                cc_log("Failed to mmap %s\n", fname);
 
266
                cc_log("Failed to mmap %s", fname);
258
267
                return -1;
259
268
        }
260
 
        close(fd);
261
269
 
262
270
        /* pass it through the unifier */
263
 
        unify((unsigned char *)map, st.st_size);
 
271
        unify(hash, (unsigned char *)map, st.st_size);
264
272
 
265
273
        munmap(map, st.st_size);
266
274
 
267
275
        return 0;
268
276
}
269