comparison macro.c @ 18:c08a947d8f30

deal with macro parameters
author David A. Holland
date Mon, 20 Dec 2010 01:51:47 -0500
parents 76da41da923f
children f9792a9ec704
comparison
equal deleted inserted replaced
17:76da41da923f 18:c08a947d8f30
9 struct macro { 9 struct macro {
10 struct place defplace; 10 struct place defplace;
11 struct place expansionplace; 11 struct place expansionplace;
12 unsigned hash; 12 unsigned hash;
13 char *name; 13 char *name;
14 bool hasparams;
15 struct stringarray params;
14 char *expansion; 16 char *expansion;
15 }; 17 };
16 DECLARRAY(macro); 18 DECLARRAY(macro);
17 DEFARRAY(macro, ); 19 DEFARRAY(macro, );
18 DECLARRAY(macroarray); 20 DECLARRAY(macroarray);
25 //////////////////////////////////////////////////////////// 27 ////////////////////////////////////////////////////////////
26 // macro structure ops 28 // macro structure ops
27 29
28 static 30 static
29 struct macro * 31 struct macro *
30 macro_create(struct place *p1, struct place *p2, unsigned hash, 32 macro_create(struct place *p1, const char *name, unsigned hash,
31 const char *name, const char *expansion) 33 struct place *p2, const char *expansion)
32 { 34 {
33 struct macro *m; 35 struct macro *m;
34 36
35 m = domalloc(sizeof(*m)); 37 m = domalloc(sizeof(*m));
36 m->defplace = *p1; 38 m->defplace = *p1;
37 m->expansionplace = *p2; 39 m->expansionplace = *p2;
38 m->hash = hash; 40 m->hash = hash;
39 m->name = dostrdup(name); 41 m->name = dostrdup(name);
42 m->hasparams = false;
43 stringarray_init(&m->params);
40 m->expansion = dostrdup(expansion); 44 m->expansion = dostrdup(expansion);
41 return m; 45 return m;
42 } 46 }
43 47
44 static 48 static
46 macro_destroy(struct macro *m) 50 macro_destroy(struct macro *m)
47 { 51 {
48 free(m->name); 52 free(m->name);
49 free(m->expansion); 53 free(m->expansion);
50 free(m); 54 free(m);
55 }
56
57 static
58 bool
59 macro_eq(const struct macro *m1, const struct macro *m2)
60 {
61 unsigned num1, num2, i;
62 const char *p1, *p2;
63
64 if (strcmp(m1->name, m2->name) != 0) {
65 return false;
66 }
67
68 if (m1->hasparams != m2->hasparams) {
69 return false;
70 }
71
72 if (strcmp(m1->expansion, m2->expansion) != 0) {
73 return false;
74 }
75
76 num1 = stringarray_num(&m1->params);
77 num2 = stringarray_num(&m2->params);
78 if (num1 != num2) {
79 return false;
80 }
81
82 for (i=0; i<num1; i++) {
83 p1 = stringarray_get(&m1->params, i);
84 p2 = stringarray_get(&m2->params, i);
85 if (strcmp(p1, p2) != 0) {
86 return false;
87 }
88 }
89 return true;
51 } 90 }
52 91
53 //////////////////////////////////////////////////////////// 92 ////////////////////////////////////////////////////////////
54 // macro table 93 // macro table
55 94
236 } 275 }
237 276
238 //////////////////////////////////////////////////////////// 277 ////////////////////////////////////////////////////////////
239 // external macro definition interface 278 // external macro definition interface
240 279
241 void 280 static
242 macro_define(struct place *p1, const char *macro, 281 struct macro *
243 struct place *p2, const char *expansion) 282 macro_define_common_start(struct place *p1, const char *macro,
244 { 283 struct place *p2, const char *expansion)
245 struct macro *m; 284 {
246 285 struct macro *m;
247 m = macrotable_find(macro, false); 286
248 if (m != NULL) { 287 if (!is_identifier(macro)) {
249 if (!strcmp(expansion, m->expansion)) { 288 complain(p1, "Invalid macro name %s", macro);
250 complain(p1, "Warning: redefinition of %s", macro); 289 complain_fail();
290 }
291
292 m = macro_create(p1, macro, hashfunc(macro), p2, expansion);
293 return m;
294 }
295
296 static
297 void
298 macro_define_common_end(struct macro *m)
299 {
300 struct macro *oldm;
301 bool ok;
302
303 oldm = macrotable_find(m->name, false);
304 if (oldm != NULL) {
305 ok = macro_eq(m, oldm);
306 if (ok) {
307 complain(&m->defplace,
308 "Warning: redefinition of %s", m->name);
251 if (mode.werror) { 309 if (mode.werror) {
252 complain_fail(); 310 complain_fail();
253 } 311 }
254 return; 312 } else {
255 } 313 complain(&m->defplace,
256 complain(p1, "Redefinition of %s is not identical", macro); 314 "Redefinition of %s is not identical",
257 complain_fail(); 315 m->name);
316 complain_fail();
317 }
318 complain(&oldm->defplace, "Previous definition was here");
319 macro_destroy(m);
258 return; 320 return;
259 } 321 }
260
261 m = macro_create(p1, p2, hashfunc(macro), macro, expansion);
262 macrotable_add(m); 322 macrotable_add(m);
323 }
324
325 static
326 void
327 macro_parse_parameters(struct macro *m, struct place *p, const char *params)
328 {
329 size_t len;
330 const char *s;
331 char *param;
332
333 while (params != NULL) {
334 len = strspn(params, ws);
335 params += len;
336 p->column += len;
337 s = strchr(params, ',');
338 if (s) {
339 len = s-params;
340 param = dostrndup(params, len);
341 s++;
342 } else {
343 len = strlen(params);
344 param = dostrndup(params, len);
345 }
346 notrailingws(param, strlen(param));
347 if (!is_identifier(param)) {
348 complain(p, "Invalid macro parameter name %s", param);
349 complain_fail();
350 } else {
351 stringarray_add(&m->params, param, NULL);
352 }
353 params = s;
354 p->column += len;
355 }
356 }
357
358 void
359 macro_define_plain(struct place *p1, const char *macro,
360 struct place *p2, const char *expansion)
361 {
362 struct macro *m;
363
364 m = macro_define_common_start(p1, macro, p2, expansion);
365 macro_define_common_end(m);
366 }
367
368 void
369 macro_define_params(struct place *p1, const char *macro,
370 struct place *p2, const char *params,
371 struct place *p3, const char *expansion)
372 {
373 struct macro *m;
374
375 m = macro_define_common_start(p1, macro, p3, expansion);
376 macro_parse_parameters(m, p2, params);
377 macro_define_common_end(m);
263 } 378 }
264 379
265 void 380 void
266 macro_undef(const char *macro) 381 macro_undef(const char *macro)
267 { 382 {