1 /* -*- c-file-style: "java"; indent-tabs-mode: nil; tab-width: 4; fill-column: 78 -*-
2 *
3 * Copyright 2005 Google Inc.
4 *
5 * This program is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU General Public License
7 * as published by the Free Software Foundation; either version 2
8 * of the License, or (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
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
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
18 * USA.
19 */
20
21 #include <config.h>
22
23 #include <stdio.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <limits.h>
27 #include <assert.h>
28
29 #include "stringmap.h"
30
31 #ifndef NULL
32 #define NULL 0
33 #endif
34
35 #ifndef PATH_MAX
36 #define PATH_MAX 4096
37 #endif
38
39 /* Load the given list of strings into the key/value map.
40 * The key for each string is the numFinalWordsToMatch of the string;
41 * the value for each string is the entire string.
42 * FIXME: doesn't work for utf-8 strings, since it scans raw chars for /
43 */
stringmap_load(const char * filename,int numFinalWordsToMatch)44 stringmap_t *stringmap_load(const char *filename, int numFinalWordsToMatch)
45 {
46 stringmap_t *result;
47 FILE *fp;
48 char buf[2*PATH_MAX];
49 int n;
50
51 result = calloc(1, sizeof(*result));
52 if (!result)
53 return NULL;
54 result->numFinalWordsToMatch = numFinalWordsToMatch;
55 fp = fopen(filename, "r");
56 if (!fp) {
57 free(result);
58 return NULL;
59 }
60 n=0;
61 while (fgets(buf, sizeof(buf), fp))
62 n++;
63 result->n = n;
64 result->map = malloc(n * sizeof(result->map[0]));
65
66 rewind(fp);
67 n=0;
68 while (fgets(buf, sizeof(buf), fp)) {
69 int pos, w;
70
71 int len = strlen(buf);
72 /* strip trailing \n */
73 if (len > 0 && buf[len-1] == '\n') {
74 buf[len-1] = 0;
75 len--;
76 }
77 /* set pos to the start of the significant part of the string */
78 for (pos=len-1, w=0; pos>0; pos--) {
79 if (buf[pos] == '/') {
80 w++;
81 if (w >= numFinalWordsToMatch) {
82 pos++;
83 break;
84 }
85 }
86 }
87
88 result->map[n].value = strdup(buf);
89 result->map[n].key = strdup(buf+pos);
90 n++;
91 } fclose(fp);
92 return result;
93 }
94
stringmap_lookup(const stringmap_t * map,const char * string)95 const char *stringmap_lookup(const stringmap_t *map, const char *string)
96 {
97 int i, w;
98 int len = strlen(string);
99 int pos;
100 for (pos=len-1, w=0; pos>0; pos--) {
101 if (string[pos] == '/') {
102 w++;
103 if (w >= map->numFinalWordsToMatch) {
104 pos++;
105 break;
106 }
107 }
108 }
109 for (i=0; i<map->n; i++) {
110 /*printf("Comparing %s and %s\n", map->map[i].key, string+pos);*/
111 if (!strcmp(map->map[i].key, string+pos))
112 return map->map[i].value;
113 }
114 return NULL;
115 }
116
117 #if 0
118
119 void dumpMap(stringmap_t *sm)
120 {
121 int i;
122 printf("map has %d elements, and numFinalWordsToMatch is %d\n", sm->n, sm->numFinalWordsToMatch);
123 for (i=0; i < sm->n; i++) {
124 printf("row %d: key %s, value %s\n", i, sm->map[i].key, sm->map[i].value);
125 }
126 }
127
128 #define verifyMap(sm, a, b) { \
129 const char *c = stringmap_lookup(sm, a); \
130 if (!b) \
131 assert(!c); \
132 else { \
133 assert(c); \
134 assert(!strcmp(b, c)); } }
135
136 int main(int argc, char **argv)
137 {
138 FILE *fp;
139 stringmap_t *sm;
140
141 fp = fopen("stringmap_test.dat", "w");
142 fprintf(fp, "/foo/bar/bletch\n");
143 fclose(fp);
144 sm = stringmap_load("stringmap_test.dat", 1);
145 dumpMap(sm);
146 verifyMap(sm, "/bar/bletch", "/foo/bar/bletch");
147 verifyMap(sm, "bletch", "/foo/bar/bletch");
148 verifyMap(sm, "/whatever/bletch", "/foo/bar/bletch");
149 verifyMap(sm, "baz", NULL);
150 verifyMap(sm, "/foo/bar/bletch", "/foo/bar/bletch");
151
152 fp = fopen("stringmap_test.dat", "w");
153 fprintf(fp, "/usr/bin/gcc\n");
154 fprintf(fp, "/usr/bin/cc\n");
155 fclose(fp);
156 sm = stringmap_load("stringmap_test.dat", 1);
157 dumpMap(sm);
158 verifyMap(sm, "/usr/bin/gcc", "/usr/bin/gcc");
159 verifyMap(sm, "/usr/bin/cc", "/usr/bin/cc");
160 verifyMap(sm, "gcc", "/usr/bin/gcc");
161 verifyMap(sm, "cc", "/usr/bin/cc");
162 verifyMap(sm, "g77", NULL);
163
164 fp = fopen("stringmap_test.dat", "w");
165 fprintf(fp, "/usr/bin/i686-blah-blah/gcc\n");
166 fprintf(fp, "/usr/bin/i386-blah-blah/gcc\n");
167 fclose(fp);
168 sm = stringmap_load("stringmap_test.dat", 2);
169 dumpMap(sm);
170 verifyMap(sm, "/usr/bin/i686-blah-blah/gcc",
171 "/usr/bin/i686-blah-blah/gcc");
172 verifyMap(sm, "/usr/bin/i386-blah-blah/gcc",
173 "/usr/bin/i386-blah-blah/gcc");
174 verifyMap(sm, "i686-blah-blah/gcc", "/usr/bin/i686-blah-blah/gcc");
175 verifyMap(sm, "i386-blah-blah/gcc", "/usr/bin/i386-blah-blah/gcc");
176 verifyMap(sm, "gcc", NULL);
177 verifyMap(sm, "g77", NULL);
178
179 return 0;
180 }
181
182 #endif
183