1 #include "common.h"
2
3 /*
4 * WARNING! This turns all upper case names into lower case
5 * local ones.
6 */
7
8 /* predeclared */
9 static String *getdbfiles(void);
10 static int translate(char*, char**, String*, String*);
11 static int lookup(String**, String*, String*);
12 static int compare(String*, char*);
13 static char* mklower(char*);
14
15 static int debug;
16 static int from;
17 static char *namefiles = "namefiles";
18 #define DEBUG if(debug)
19
20 /* loop through the names to be translated */
21 void
main(int argc,char * argv[])22 main(int argc, char *argv[])
23 {
24 String *s;
25 String *alias; /* the alias for the name */
26 char **names; /* names of this system */
27 String *files; /* list of files to search */
28 int i, rv;
29 char *p;
30
31 ARGBEGIN {
32 case 'd':
33 debug = 1;
34 break;
35 case 'f':
36 from = 1;
37 break;
38 case 'n':
39 namefiles = ARGF();
40 break;
41 } ARGEND
42 if (chdir(UPASLIB) < 0) {
43 perror("translate(chdir):");
44 exit(1);
45 }
46
47 /* get environmental info */
48 names = sysnames_read();
49 files = getdbfiles();
50 alias = s_new();
51
52 /* loop through the names to be translated (from standard input) */
53 for(i=0; i<argc; i++) {
54 s = unescapespecial(s_copy(mklower(argv[i])));
55 if(strchr(s_to_c(s), '!') == 0)
56 rv = translate(s_to_c(s), names, files, alias);
57 else
58 rv = -1;
59 if(from){
60 if (rv >= 0 && *s_to_c(alias) != '\0'){
61 p = strchr(s_to_c(alias), '\n');
62 if(p)
63 *p = 0;
64 p = strchr(s_to_c(alias), '!');
65 if(p) {
66 *p = 0;
67 print("%s", s_to_c(alias));
68 } else {
69 p = strchr(s_to_c(alias), '@');
70 if(p)
71 print("%s", p+1);
72 else
73 print("%s", s_to_c(alias));
74 }
75 }
76 } else {
77 if (rv < 0 || *s_to_c(alias) == '\0')
78 print("local!%s\n", s_to_c(s));
79 else {
80 /* this must be a write, not a print */
81 write(1, s_to_c(alias), strlen(s_to_c(alias)));
82 }
83 }
84 s_free(s);
85 }
86 exits(0);
87 }
88
89 /* get the list of dbfiles to search */
90 static String *
getdbfiles(void)91 getdbfiles(void)
92 {
93 Sinstack *sp;
94 String *files = s_new();
95 char *nf;
96
97 if(from)
98 nf = "fromfiles";
99 else
100 nf = namefiles;
101
102 /* system wide aliases */
103 if ((sp = s_allocinstack(nf)) != 0){
104 while(s_rdinstack(sp, files))
105 s_append(files, " ");
106 s_freeinstack(sp);
107 }
108
109
110 DEBUG print("files are %s\n", s_to_c(files));
111
112 return files;
113 }
114
115 /* loop through the translation files */
116 static int
translate(char * name,char ** namev,String * files,String * alias)117 translate(char *name, /* name to translate */
118 char **namev, /* names of this system */
119 String *files, /* names of system alias files */
120 String *alias) /* where to put the alias */
121 {
122 String *file = s_new();
123 String **fullnamev;
124 int n, rv;
125
126 rv = -1;
127
128 DEBUG print("translate(%s, %s, %s)\n", name,
129 s_to_c(files), s_to_c(alias));
130
131 /* create the full name to avoid loops (system!name) */
132 for(n = 0; namev[n]; n++)
133 ;
134 fullnamev = (String**)malloc(sizeof(String*)*(n+2));
135 n = 0;
136 fullnamev[n++] = s_copy(name);
137 for(; *namev; namev++){
138 fullnamev[n] = s_copy(*namev);
139 s_append(fullnamev[n], "!");
140 s_append(fullnamev[n], name);
141 n++;
142 }
143 fullnamev[n] = 0;
144
145 /* look at system-wide names */
146 s_restart(files);
147 while (s_parse(files, s_restart(file)) != 0) {
148 if (lookup(fullnamev, file, alias)==0) {
149 rv = 0;
150 goto out;
151 }
152 }
153
154 out:
155 for(n = 0; fullnamev[n]; n++)
156 s_free(fullnamev[n]);
157 s_free(file);
158 free(fullnamev);
159 return rv;
160 }
161
162 /*
163 * very dumb conversion to bang format
164 */
165 static String*
attobang(String * token)166 attobang(String *token)
167 {
168 char *p;
169 String *tok;
170
171 p = strchr(s_to_c(token), '@');
172 if(p == 0)
173 return token;
174
175 p++;
176 tok = s_copy(p);
177 s_append(tok, "!");
178 s_nappend(tok, s_to_c(token), p - s_to_c(token) - 1);
179
180 return tok;
181 }
182
183 /* Loop through the entries in a translation file looking for a match.
184 * Return 0 if found, -1 otherwise.
185 */
186 static int
lookup(String ** namev,String * file,String * alias)187 lookup(
188 String **namev,
189 String *file,
190 String *alias) /* returned String */
191 {
192 String *line = s_new();
193 String *token = s_new();
194 String *bangtoken;
195 int i, rv = -1;
196 char *name = s_to_c(namev[0]);
197 Sinstack *sp;
198
199 DEBUG print("lookup(%s, %s, %s, %s)\n", s_to_c(namev[0]), s_to_c(namev[1]),
200 s_to_c(file), s_to_c(alias));
201
202 s_reset(alias);
203 if ((sp = s_allocinstack(s_to_c(file))) == 0)
204 return -1;
205
206 /* look for a match */
207 while (s_rdinstack(sp, s_restart(line))!=0) {
208 DEBUG print("line is %s\n", s_to_c(line));
209 s_restart(token);
210 if (s_parse(s_restart(line), token)==0)
211 continue;
212 if (compare(token, "#include")==0){
213 if(s_parse(line, s_restart(token))!=0) {
214 if(lookup(namev, line, alias) == 0)
215 break;
216 }
217 continue;
218 }
219 if (compare(token, name)!=0)
220 continue;
221 /* match found, get the alias */
222 while(s_parse(line, s_restart(token))!=0) {
223 bangtoken = attobang(token);
224
225 /* avoid definition loops */
226 for(i = 0; namev[i]; i++)
227 if(compare(bangtoken, s_to_c(namev[i]))==0) {
228 s_append(alias, "local");
229 s_append(alias, "!");
230 s_append(alias, name);
231 break;
232 }
233
234 if(namev[i] == 0)
235 s_append(alias, s_to_c(token));
236 s_append(alias, "\n");
237
238 if(bangtoken != token)
239 s_free(bangtoken);
240 }
241 rv = 0;
242 break;
243 }
244 s_free(line);
245 s_free(token);
246 s_freeinstack(sp);
247 return rv;
248 }
249
250 #define lower(c) ((c)>='A' && (c)<='Z' ? (c)-('A'-'a'):(c))
251
252 /* compare two Strings (case insensitive) */
253 static int
compare(String * s1,char * p2)254 compare(String *s1,
255 char *p2)
256 {
257 char *p1 = s_to_c(s1);
258 int rv;
259
260 DEBUG print("comparing %s to %s\n", p1, p2);
261 while((rv = lower(*p1) - lower(*p2)) == 0) {
262 if (*p1 == '\0')
263 break;
264 p1++;
265 p2++;
266 }
267 return rv;
268 }
269
270 static char*
mklower(char * name)271 mklower(char *name)
272 {
273 char *p;
274 char c;
275
276 for(p = name; *p; p++){
277 c = *p;
278 *p = lower(c);
279 }
280 return name;
281 }
282