Print this page
2nd round review feedback from rmustacc.
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/test/libc-tests/tests/symbols/symbols_test.c
+++ new/usr/src/test/libc-tests/tests/symbols/symbols_test.c
1 1 /*
2 2 * This file and its contents are supplied under the terms of the
3 3 * Common Development and Distribution License ("CDDL"), version 1.0.
4 4 * You may only use this file in accordance with the terms of version
5 5 * 1.0 of the CDDL.
6 6 *
7 7 * A full copy of the text of the CDDL should have accompanied this
8 8 * source. A copy of the CDDL is also available via the Internet at
9 9 * http://www.illumos.org/license/CDDL.
10 10 */
11 11
12 12 /*
13 13 * Copyright 2015 Garrett D'Amore <garrett@damore.org>
14 14 */
15 15
16 16 /*
17 17 * This program tests symbol visibility using the /usr/bin/c89 and
18 18 * /usr/bin/c99 programs.
19 19 */
20 20
21 21 #include <stdio.h>
22 22 #include <stdlib.h>
23 23 #include <string.h>
24 24 #include <errno.h>
25 25 #include <err.h>
26 26 #include <unistd.h>
27 27 #include <sys/types.h>
28 28 #include <sys/stat.h>
29 29 #include <note.h>
30 30 #include <sys/wait.h>
31 31 #include "test_common.h"
32 32
33 33 char *dname;
34 34 char *cfile;
35 35 char *ofile;
36 36 char *lfile;
37 37 char *efile;
38 38
39 39 const char *sym = NULL;
40 40
41 41 static int good_count = 0;
42 42 static int fail_count = 0;
43 43 static int full_count = 0;
44 44 static int extra_debug = 0;
45 45 static char *compilation = "compilation.cfg";
46 46
47 47 #if defined(_LP64)
48 48 #define MFLAG "-m64"
49 49 #elif defined(_ILP32)
50 50 #define MFLAG "-m32"
51 51 #endif
52 52
53 53 const char *compilers[] = {
54 54 "cc",
55 55 "gcc",
56 56 "/opt/SUNWspro/bin/cc",
57 57 "/opt/gcc/4.4.4/bin/gcc",
58 58 "/opt/sunstudio12.1/bin/cc",
59 59 "/opt/sfw/bin/gcc",
60 60 "/usr/local/bin/gcc",
61 61 NULL
62 62 };
63 63
64 64 char *compiler = NULL;
65 65 const char *c89flags = NULL;
66 66 const char *c99flags = NULL;
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
67 67
68 68 #define MAXENV 64 /* maximum number of environments (bitmask width) */
69 69 #define MAXHDR 10 /* maximum # headers to require to access symbol */
70 70 #define MAXARG 20 /* maximum # of arguments */
71 71
72 72 #define WS " \t"
73 73
74 74 static int next_env = 0;
75 75
76 76 struct compile_env {
77 - char *name;
78 - char *lang;
79 - char *defs;
80 - int index;
77 + char *ce_name;
78 + char *ce_lang;
79 + char *ce_defs;
80 + int ce_index;
81 81 };
82 82
83 83 static struct compile_env compile_env[MAXENV];
84 84
85 85 struct env_group {
86 - char *name;
87 - uint64_t mask;
88 - struct env_group *next;
86 + char *eg_name;
87 + uint64_t eg_mask;
88 + struct env_group *eg_next;
89 89 };
90 90
91 91 typedef enum { SYM_TYPE, SYM_VALUE, SYM_FUNC } sym_type_t;
92 92
93 93 struct sym_test {
94 - char *name;
95 - sym_type_t type;
96 - char *hdrs[MAXHDR];
97 - char *rtype;
98 - char *atypes[MAXARG];
99 - uint64_t test_mask;
100 - uint64_t need_mask;
101 - char *prog;
102 - struct sym_test *next;
94 + char *st_name;
95 + sym_type_t st_type;
96 + char *st_hdrs[MAXHDR];
97 + char *st_rtype;
98 + char *st_atypes[MAXARG];
99 + uint64_t st_test_mask;
100 + uint64_t st_need_mask;
101 + char *st_prog;
102 + struct sym_test *st_next;
103 103 };
104 104
105 105 struct env_group *env_groups = NULL;
106 106
107 107 struct sym_test *sym_tests = NULL;
108 108 struct sym_test **sym_insert = &sym_tests;
109 109
110 110 static char *
111 111 mystrdup(const char *s)
112 112 {
113 113 char *r;
114 114 if ((r = strdup(s)) == NULL) {
115 115 perror("strdup");
116 116 exit(1);
117 117 }
118 118 return (r);
119 119 }
120 120
121 121 static void *
122 122 myzalloc(size_t sz)
123 123 {
124 124 void *buf;
125 125 if ((buf = calloc(1, sz)) == NULL) {
126 126 perror("calloc");
127 127 exit(1);
128 128 }
129 129 return (buf);
130 130 }
131 131
132 132 static void
133 133 myasprintf(char **buf, const char *fmt, ...)
134 134 {
135 135 int rv;
136 136 va_list va;
137 137 va_start(va, fmt);
138 138 rv = vasprintf(buf, fmt, va);
139 139 va_end(va);
↓ open down ↓ |
27 lines elided |
↑ open up ↑ |
140 140 if (rv < 0) {
141 141 perror("vasprintf");
142 142 exit(1);
143 143 }
144 144 }
145 145
146 146 static void
147 147 append_sym_test(struct sym_test *st)
148 148 {
149 149 *sym_insert = st;
150 - sym_insert = &st->next;
150 + sym_insert = &st->st_next;
151 151 }
152 152
153 153 static int
154 154 find_env_mask(const char *name, uint64_t *mask)
155 155 {
156 - for (int i = 0; i < 64; i++) {
157 - if (compile_env[i].name != NULL &&
158 - strcmp(compile_env[i].name, name) == 0) {
156 + for (int i = 0; i < MAXENV; i++) {
157 + if (compile_env[i].ce_name != NULL &&
158 + strcmp(compile_env[i].ce_name, name) == 0) {
159 159 *mask |= (1ULL << i);
160 160 return (0);
161 161 }
162 162 }
163 163
164 - for (struct env_group *eg = env_groups; eg != NULL; eg = eg->next) {
165 - if (strcmp(name, eg->name) == 0) {
166 - *mask |= eg->mask;
164 + for (struct env_group *eg = env_groups; eg != NULL; eg = eg->eg_next) {
165 + if (strcmp(name, eg->eg_name) == 0) {
166 + *mask |= eg->eg_mask;
167 167 return (0);
168 168 }
169 169 }
170 170 return (-1);
171 171 }
172 172
173 173
174 174 static int
175 175 expand_env(char *list, uint64_t *mask, char **erritem)
176 176 {
177 177 char *item;
178 178 for (item = strtok(list, WS); item != NULL; item = strtok(NULL, WS)) {
179 179 if (find_env_mask(item, mask) < 0) {
180 180 if (erritem != NULL) {
181 181 *erritem = item;
182 182 }
183 183 return (-1);
184 184 }
185 185 }
186 186 return (0);
187 187 }
188 188
189 189 static int
190 190 expand_env_list(char *list, uint64_t *test, uint64_t *need, char **erritem)
191 191 {
192 192 uint64_t mask = 0;
193 193 int act;
194 194 char *item;
195 195 for (item = strtok(list, WS); item != NULL; item = strtok(NULL, WS)) {
196 196 switch (item[0]) {
197 197 case '+':
198 198 act = 1;
199 199 item++;
200 200 break;
201 201 case '-':
202 202 act = 0;
203 203 item++;
204 204 break;
205 205 default:
206 206 act = 1;
207 207 break;
208 208 }
209 209
210 210 mask = 0;
211 211 if (find_env_mask(item, &mask) < 0) {
212 212 if (erritem != NULL) {
213 213 *erritem = item;
214 214 }
215 215 return (-1);
216 216 }
217 217 *test |= mask;
218 218 if (act) {
219 219 *need |= mask;
220 220 } else {
221 221 *need &= ~(mask);
222 222 }
223 223 }
224 224 return (0);
225 225 }
226 226
227 227 static int
228 228 do_env(char **fields, int nfields, char **err)
229 229 {
230 230 char *name;
231 231 char *lang;
232 232 char *defs;
233 233
234 234 if (nfields != 3) {
235 235 myasprintf(err, "number of fields (%d) != 3", nfields);
236 236 return (-1);
237 237 }
↓ open down ↓ |
61 lines elided |
↑ open up ↑ |
238 238
239 239 if (next_env >= MAXENV) {
240 240 myasprintf(err, "too many environments");
241 241 return (-1);
242 242 }
243 243
244 244 name = fields[0];
245 245 lang = fields[1];
246 246 defs = fields[2];
247 247
248 - compile_env[next_env].name = mystrdup(name);
249 - compile_env[next_env].lang = mystrdup(lang);
250 - compile_env[next_env].defs = mystrdup(defs);
251 - compile_env[next_env].index = next_env;
248 + compile_env[next_env].ce_name = mystrdup(name);
249 + compile_env[next_env].ce_lang = mystrdup(lang);
250 + compile_env[next_env].ce_defs = mystrdup(defs);
251 + compile_env[next_env].ce_index = next_env;
252 252 next_env++;
253 253 return (0);
254 254 }
255 255
256 256 static int
257 257 do_env_group(char **fields, int nfields, char **err)
258 258 {
259 259 char *name;
260 260 char *list;
261 261 struct env_group *eg;
262 262 uint64_t mask;
263 263 char *item;
264 264
265 265 if (nfields != 2) {
266 266 myasprintf(err, "number of fields (%d) != 2", nfields);
267 267 return (-1);
268 268 }
269 269
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
270 270 name = fields[0];
271 271 list = fields[1];
272 272 mask = 0;
273 273
274 274 if (expand_env(list, &mask, &item) < 0) {
275 275 myasprintf(err, "reference to undefined env %s", item);
276 276 return (-1);
277 277 }
278 278
279 279 eg = myzalloc(sizeof (*eg));
280 - eg->name = mystrdup(name);
281 - eg->mask = mask;
282 - eg->next = env_groups;
280 + eg->eg_name = mystrdup(name);
281 + eg->eg_mask = mask;
282 + eg->eg_next = env_groups;
283 283 env_groups = eg;
284 284 return (0);
285 285 }
286 286
287 287 static char *progbuf = NULL;
288 288 size_t proglen = 0;
289 289 size_t progsiz = 0;
290 290
291 291 static void
292 292 addprogch(char c)
293 293 {
294 294 while (progsiz <= (proglen + 1)) {
295 295 progbuf = realloc(progbuf, progsiz + 4096);
296 296 if (progbuf == NULL) {
297 297 perror("realloc");
298 298 exit(1);
299 299 }
300 300 progsiz += 1024;
301 301 }
302 302 progbuf[proglen++] = c;
303 303 progbuf[proglen] = 0;
304 304 }
305 305
306 306 static void
307 307 addprogstr(char *s)
308 308 {
309 309 while (*s != NULL) {
310 310 addprogch(*s);
311 311 s++;
312 312 }
313 313 }
314 314
315 315 static void
316 316 addprogfmt(const char *fmt, ...)
317 317 {
318 318 va_list va;
319 319 char *buf = NULL;
320 320 va_start(va, fmt);
321 321 if (vasprintf(&buf, fmt, va) < 0) {
322 322 perror("vasprintf");
323 323 exit(1);
324 324 }
325 325 va_end(va);
326 326 addprogstr(buf);
↓ open down ↓ |
34 lines elided |
↑ open up ↑ |
327 327 free(buf);
328 328 }
329 329
330 330 static void
331 331 mkprog(struct sym_test *st)
332 332 {
333 333 char *s;
334 334
335 335 proglen = 0;
336 336
337 - for (int i = 0; i < MAXHDR && st->hdrs[i] != NULL; i++) {
338 - addprogfmt("#include <%s>\n", st->hdrs[i]);
337 + for (int i = 0; i < MAXHDR && st->st_hdrs[i] != NULL; i++) {
338 + addprogfmt("#include <%s>\n", st->st_hdrs[i]);
339 339 }
340 340
341 - for (s = st->rtype; *s; s++) {
341 + for (s = st->st_rtype; *s; s++) {
342 342 addprogch(*s);
343 343 if (*s == '(') {
344 344 s++;
345 345 addprogch(*s);
346 346 s++;
347 347 break;
348 348 }
349 349 }
350 350 addprogch(' ');
351 351
352 352 /* for function pointers, s is closing suffix, otherwise empty */
353 353
354 - switch (st->type) {
354 + switch (st->st_type) {
355 355 case SYM_TYPE:
356 356 addprogstr("test_type;");
357 357 break;
358 358
359 359 case SYM_VALUE:
360 360 addprogfmt("test_value%s;\n", s); /* s usually empty */
361 361 addprogstr("void\ntest_func(void)\n{\n");
362 - addprogfmt("\ttest_value = %s;\n}", st->name);
362 + addprogfmt("\ttest_value = %s;\n}", st->st_name);
363 363 break;
364 364
365 365 case SYM_FUNC:
366 366 addprogstr("\ntest_func(");
367 - for (int i = 0; st->atypes[i] != NULL && i < MAXARG; i++) {
367 + for (int i = 0; st->st_atypes[i] != NULL && i < MAXARG; i++) {
368 368 int didname = 0;
369 369 if (i > 0) {
370 370 addprogstr(", ");
371 371 }
372 - if (strcmp(st->atypes[i], "void") == 0) {
372 + if (strcmp(st->st_atypes[i], "void") == 0) {
373 373 didname = 1;
374 374 }
375 - if (strcmp(st->atypes[i], "") == 0) {
375 + if (strcmp(st->st_atypes[i], "") == 0) {
376 376 didname = 1;
377 377 addprogstr("void");
378 378 }
379 379
380 380 /* print the argument list */
381 - for (char *a = st->atypes[i]; *a; a++) {
381 + for (char *a = st->st_atypes[i]; *a; a++) {
382 382 if (*a == '(' && a[1] == '*' && !didname) {
383 383 addprogfmt("(*a%d", i);
384 384 didname = 1;
385 385 a++;
386 386 } else if (*a == '[' && !didname) {
387 387 addprogfmt("a%d[", i);
388 388 didname = 1;
389 389 } else {
390 390 addprogch(*a);
391 391 }
392 392 }
393 393 if (!didname) {
394 394 addprogfmt(" a%d", i);
395 395 }
396 396 }
397 397
398 - if (st->atypes[0] == NULL) {
398 + if (st->st_atypes[0] == NULL) {
399 399 addprogstr("void");
400 400 }
401 401
402 - /* close argument list, and closing ")" for func ptrs */
403 - addprogfmt(")%s\n{\n\t", s); /* NB: s is normally empty */
402 + /*
403 + * Close argument list, and closing ")" for func ptrs.
404 + * Note that for non-function pointers, s will be empty
405 + * below, otherwise it points to the trailing argument
406 + * list.
407 + */
408 + addprogfmt(")%s\n{\n\t", s);
404 409
405 - if (strcmp(st->rtype, "") != 0 &&
406 - strcmp(st->rtype, "void") != 0) {
410 + if (strcmp(st->st_rtype, "") != 0 &&
411 + strcmp(st->st_rtype, "void") != 0) {
407 412 addprogstr("return ");
408 413 }
409 414
410 415 /* add the function call */
411 - addprogfmt("%s(", st->name);
412 - for (int i = 0; st->atypes[i] != NULL && i < MAXARG; i++) {
413 - if (strcmp(st->atypes[i], "") != 0 &&
414 - strcmp(st->atypes[i], "void") != 0) {
416 + addprogfmt("%s(", st->st_name);
417 + for (int i = 0; st->st_atypes[i] != NULL && i < MAXARG; i++) {
418 + if (strcmp(st->st_atypes[i], "") != 0 &&
419 + strcmp(st->st_atypes[i], "void") != 0) {
415 420 addprogfmt("%sa%d", i > 0 ? ", " : "", i);
416 421 }
417 422 }
418 423
419 424 addprogstr(");\n}");
420 425 break;
421 426 }
422 427
423 428 addprogch('\n');
424 429
425 - st->prog = progbuf;
430 + st->st_prog = progbuf;
426 431 }
427 432
428 433 static int
429 434 add_envs(struct sym_test *st, char *envs, char **err)
430 435 {
431 436 char *item;
432 - if (expand_env_list(envs, &st->test_mask, &st->need_mask, &item) < 0) {
437 + if (expand_env_list(envs, &st->st_test_mask, &st->st_need_mask,
438 + &item) < 0) {
433 439 myasprintf(err, "bad env action %s", item);
434 440 return (-1);
435 441 }
436 442 return (0);
437 443 }
438 444
439 445 static int
440 446 add_headers(struct sym_test *st, char *hdrs, char **err)
441 447 {
442 448 int i = 0;
443 449
444 450 for (char *h = strsep(&hdrs, ";"); h != NULL; h = strsep(&hdrs, ";")) {
445 451 if (i >= MAXHDR) {
446 452 myasprintf(err, "too many headers");
447 453 return (-1);
448 454 }
449 455 test_trim(&h);
450 - st->hdrs[i++] = mystrdup(h);
456 + st->st_hdrs[i++] = mystrdup(h);
451 457 }
452 458
453 459 return (0);
454 460 }
455 461
456 462 static int
457 463 add_arg_types(struct sym_test *st, char *atype, char **err)
458 464 {
459 465 int i = 0;
460 466 char *a;
461 467 for (a = strsep(&atype, ";"); a != NULL; a = strsep(&atype, ";")) {
462 468 if (i >= MAXARG) {
463 469 myasprintf(err, "too many arguments");
464 470 return (-1);
465 471 }
466 472 test_trim(&a);
467 - st->atypes[i++] = mystrdup(a);
473 + st->st_atypes[i++] = mystrdup(a);
468 474 }
469 475
470 476 return (0);
471 477 }
472 478
473 479 static int
474 480 do_type(char **fields, int nfields, char **err)
475 481 {
476 482 char *decl;
477 483 char *hdrs;
478 484 char *envs;
479 485 struct sym_test *st;
↓ open down ↓ |
2 lines elided |
↑ open up ↑ |
480 486
481 487 if (nfields != 3) {
482 488 myasprintf(err, "number of fields (%d) != 3", nfields);
483 489 return (-1);
484 490 }
485 491 decl = fields[0];
486 492 hdrs = fields[1];
487 493 envs = fields[2];
488 494
489 495 st = myzalloc(sizeof (*st));
490 - st->type = SYM_TYPE;
491 - st->name = mystrdup(decl);
492 - st->rtype = mystrdup(decl);
496 + st->st_type = SYM_TYPE;
497 + st->st_name = mystrdup(decl);
498 + st->st_rtype = mystrdup(decl);
493 499
494 500 if ((add_envs(st, envs, err) < 0) ||
495 501 (add_headers(st, hdrs, err) < 0)) {
496 502 return (-1);
497 503 }
498 504 append_sym_test(st);
499 505
500 506 return (0);
501 507 }
502 508
503 509 static int
504 510 do_value(char **fields, int nfields, char **err)
505 511 {
506 512 char *name;
507 513 char *type;
508 514 char *hdrs;
509 515 char *envs;
510 516 struct sym_test *st;
511 517
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
512 518 if (nfields != 4) {
513 519 myasprintf(err, "number of fields (%d) != 4", nfields);
514 520 return (-1);
515 521 }
516 522 name = fields[0];
517 523 type = fields[1];
518 524 hdrs = fields[2];
519 525 envs = fields[3];
520 526
521 527 st = myzalloc(sizeof (*st));
522 - st->type = SYM_VALUE;
523 - st->name = mystrdup(name);
524 - st->rtype = mystrdup(type);
528 + st->st_type = SYM_VALUE;
529 + st->st_name = mystrdup(name);
530 + st->st_rtype = mystrdup(type);
525 531
526 532 if ((add_envs(st, envs, err) < 0) ||
527 533 (add_headers(st, hdrs, err) < 0)) {
528 534 return (-1);
529 535 }
530 536 append_sym_test(st);
531 537
532 538 return (0);
533 539 }
534 540
535 541 static int
536 542 do_func(char **fields, int nfields, char **err)
537 543 {
538 544 char *name;
539 545 char *rtype;
540 546 char *atype;
541 547 char *hdrs;
542 548 char *envs;
543 549 struct sym_test *st;
544 550
545 551 if (nfields != 5) {
↓ open down ↓ |
11 lines elided |
↑ open up ↑ |
546 552 myasprintf(err, "number of fields (%d) != 5", nfields);
547 553 return (-1);
548 554 }
549 555 name = fields[0];
550 556 rtype = fields[1];
551 557 atype = fields[2];
552 558 hdrs = fields[3];
553 559 envs = fields[4];
554 560
555 561 st = myzalloc(sizeof (*st));
556 - st->type = SYM_FUNC;
557 - st->name = mystrdup(name);
558 - st->rtype = mystrdup(rtype);
562 + st->st_type = SYM_FUNC;
563 + st->st_name = mystrdup(name);
564 + st->st_rtype = mystrdup(rtype);
559 565
560 566 if ((add_envs(st, envs, err) < 0) ||
561 567 (add_headers(st, hdrs, err) < 0) ||
562 568 (add_arg_types(st, atype, err) < 0)) {
563 569 return (-1);
564 570 }
565 571 append_sym_test(st);
566 572
567 573 return (0);
568 574 }
569 575
570 576 struct sym_test *
571 577 next_sym_test(struct sym_test *st)
572 578 {
573 - return (st == NULL ? sym_tests : st->next);
579 + return (st == NULL ? sym_tests : st->st_next);
574 580 }
575 581
576 582 const char *
577 583 sym_test_prog(struct sym_test *st)
578 584 {
579 - if (st->prog == NULL) {
585 + if (st->st_prog == NULL) {
580 586 mkprog(st);
581 587 }
582 - return (st->prog);
588 + return (st->st_prog);
583 589 }
584 590
585 591 const char *
586 592 sym_test_name(struct sym_test *st)
587 593 {
588 - return (st->name);
594 + return (st->st_name);
589 595 }
590 596
591 597 /*
592 598 * Iterate through tests. Pass in NULL for cenv to begin the iteration. For
593 599 * subsequent iterations, use the return value from the previous iteration.
594 600 * Returns NULL when there are no more environments.
595 601 */
596 602 struct compile_env *
597 603 sym_test_env(struct sym_test *st, struct compile_env *cenv, int *need)
598 604 {
599 - int i = cenv ? cenv->index + 1: 0;
605 + int i = cenv ? cenv->ce_index + 1: 0;
600 606 uint64_t b = 1ULL << i;
601 607
602 608 while ((i < MAXENV) && (b != 0)) {
603 609 cenv = &compile_env[i];
604 - if (b & st->test_mask) {
605 - *need = (st->need_mask & b) ? 1 : 0;
610 + if (b & st->st_test_mask) {
611 + *need = (st->st_need_mask & b) ? 1 : 0;
606 612 return (cenv);
607 613 }
608 614 b <<= 1;
609 615 i++;
610 616 }
611 617 return (NULL);
612 618 }
613 619
614 620 const char *
615 621 env_name(struct compile_env *cenv)
616 622 {
617 - return (cenv->name);
623 + return (cenv->ce_name);
618 624 }
619 625
620 626 const char *
621 627 env_lang(struct compile_env *cenv)
622 628 {
623 - return (cenv->lang);
629 + return (cenv->ce_lang);
624 630 }
625 631
626 632 const char *
627 633 env_defs(struct compile_env *cenv)
628 634 {
629 - return (cenv->defs);
635 + return (cenv->ce_defs);
630 636 }
631 637
632 638 static void
633 639 show_file(test_t t, const char *path)
634 640 {
635 641 FILE *f;
636 642 char *buf = NULL;
637 643 size_t cap = 0;
638 644 int line = 1;
639 645
640 646 f = fopen(path, "r");
641 647 if (f == NULL) {
642 648 test_debugf(t, "fopen(%s): %s", path, strerror(errno));
643 649 return;
644 650 }
645 651
646 652 test_debugf(t, "----->> begin (%s) <<------", path);
647 653 while (getline(&buf, &cap, f) >= 0) {
648 654 (void) strtok(buf, "\r\n");
649 655 test_debugf(t, "%d: %s", line, buf);
650 656 line++;
651 657 }
652 658 test_debugf(t, "----->> end (%s) <<------", path);
653 659 (void) fclose(f);
654 660 }
655 661
656 662 static void
657 663 cleanup(void)
658 664 {
659 665 if (ofile != NULL) {
660 666 (void) unlink(ofile);
661 667 free(ofile);
662 668 ofile = NULL;
663 669 }
664 670 if (lfile != NULL) {
665 671 (void) unlink(lfile);
666 672 free(lfile);
667 673 lfile = NULL;
668 674 }
669 675 if (cfile != NULL) {
670 676 (void) unlink(cfile);
671 677 free(cfile);
672 678 cfile = NULL;
673 679 }
674 680 if (efile != NULL) {
675 681 (void) unlink(efile);
676 682 free(efile);
677 683 efile = NULL;
678 684 }
679 685 if (dname) {
680 686 (void) rmdir(dname);
681 687 free(dname);
682 688 dname = NULL;
683 689 }
684 690 }
685 691
686 692 static int
687 693 mkworkdir(void)
688 694 {
689 695 char b[32];
690 696 char *d;
691 697
692 698 cleanup();
693 699
694 700 (void) strlcpy(b, "/tmp/symbols_testXXXXXX", sizeof (b));
695 701 if ((d = mkdtemp(b)) == NULL) {
696 702 perror("mkdtemp");
697 703 return (-1);
698 704 }
699 705 dname = mystrdup(d);
700 706 myasprintf(&cfile, "%s/compile_test.c", d);
701 707 myasprintf(&ofile, "%s/compile_test.o", d);
702 708 myasprintf(&lfile, "%s/compile_test.log", d);
703 709 myasprintf(&efile, "%s/compile_test.exe", d);
704 710 return (0);
705 711 }
706 712
707 713 void
708 714 find_compiler(void)
709 715 {
710 716 test_t t;
711 717 int i;
712 718 FILE *cf;
713 719
714 720 t = test_start("finding compiler");
715 721
716 722 if ((cf = fopen(cfile, "w+")) == NULL) {
717 723 test_failed(t, "Unable to open %s for write: %s", cfile,
718 724 strerror(errno));
719 725 return;
720 726 }
721 727 (void) fprintf(cf, "#include <stdio.h>\n");
722 728 (void) fprintf(cf, "int main(int argc, char **argv) {\n");
723 729 (void) fprintf(cf, "#if defined(__SUNPRO_C)\n");
724 730 (void) fprintf(cf, "exit(51);\n");
725 731 (void) fprintf(cf, "#elif defined(__GNUC__)\n");
726 732 (void) fprintf(cf, "exit(52);\n");
727 733 (void) fprintf(cf, "#else\n");
728 734 (void) fprintf(cf, "exit(99)\n");
729 735 (void) fprintf(cf, "#endif\n}\n");
730 736 (void) fclose(cf);
731 737
732 738 for (i = 0; compilers[i] != NULL; i++) {
733 739 char cmd[256];
734 740 int rv;
735 741
736 742 (void) snprintf(cmd, sizeof (cmd),
737 743 "%s %s %s -o %s >/dev/null 2>&1",
738 744 compilers[i], MFLAG, cfile, efile);
739 745 test_debugf(t, "trying %s", cmd);
740 746 rv = system(cmd);
741 747
742 748 test_debugf(t, "result: %d", rv);
743 749
744 750 if ((rv < 0) || !WIFEXITED(rv) || WEXITSTATUS(rv) != 0)
745 751 continue;
746 752
747 753 rv = system(efile);
748 754 if (rv >= 0 && WIFEXITED(rv)) {
749 755 rv = WEXITSTATUS(rv);
750 756 } else {
751 757 rv = -1;
752 758 }
753 759
754 760 switch (rv) {
755 761 case 51: /* STUDIO */
756 762 test_debugf(t, "Found Studio C");
757 763 c89flags = "-Xc -errwarn=%all -v -xc99=%none " MFLAG;
758 764 c99flags = "-Xc -errwarn=%all -v -xc99=%all " MFLAG;
759 765 if (extra_debug) {
760 766 test_debugf(t, "c89flags: %s", c89flags);
761 767 test_debugf(t, "c99flags: %s", c99flags);
762 768 }
763 769 test_passed(t);
764 770 break;
↓ open down ↓ |
125 lines elided |
↑ open up ↑ |
765 771 case 52: /* GCC */
766 772 test_debugf(t, "Found GNU C");
767 773 c89flags = "-Wall -Werror -std=c89 " MFLAG;
768 774 c99flags = "-Wall -Werror -std=c99 " MFLAG;
769 775 if (extra_debug) {
770 776 test_debugf(t, "c89flags: %s", c89flags);
771 777 test_debugf(t, "c99flags: %s", c99flags);
772 778 }
773 779 test_passed(t);
774 780 break;
781 + case 99:
782 + test_debugf(t, "Found unknown (unsupported) compiler");
783 + continue;
775 784 default:
776 785 continue;
777 786 }
778 787 myasprintf(&compiler, "%s", compilers[i]);
779 788 test_debugf(t, "compiler: %s", compiler);
780 789 return;
781 790 }
782 791 test_failed(t, "No compiler found.");
783 792 }
784 793
785 794 int
786 795 do_compile(test_t t, struct sym_test *st, struct compile_env *cenv, int need)
787 796 {
788 797 char *cmd;
789 798 FILE *logf;
790 799 FILE *dotc;
791 800 const char *prog;
792 801
793 802 full_count++;
794 803
795 804 if ((dotc = fopen(cfile, "w+")) == NULL) {
796 805 test_failed(t, "fopen(%s): %s", cfile, strerror(errno));
797 806 return (-1);
798 807 }
799 808 prog = sym_test_prog(st);
800 809 if (fwrite(prog, 1, strlen(prog), dotc) < strlen(prog)) {
801 810 test_failed(t, "fwrite: %s", strerror(errno));
802 811 (void) fclose(dotc);
803 812 return (-1);
804 813 }
805 814 if (fclose(dotc) < 0) {
806 815 test_failed(t, "fclose: %s", strerror(errno));
807 816 return (-1);
808 817 }
809 818
810 819 (void) unlink(ofile);
811 820
812 821 myasprintf(&cmd, "%s %s %s -c %s -o %s >>%s 2>&1",
813 822 compiler, strcmp(env_lang(cenv), "c99") == 0 ? c99flags : c89flags,
814 823 env_defs(cenv), cfile, ofile, lfile);
815 824
816 825 if (extra_debug) {
817 826 test_debugf(t, "command: %s", cmd);
818 827 }
819 828
820 829 if ((logf = fopen(lfile, "w+")) == NULL) {
821 830 test_failed(t, "fopen: %s", strerror(errno));
822 831 return (-1);
823 832 }
824 833 (void) fprintf(logf, "===================\n");
825 834 (void) fprintf(logf, "PROGRAM:\n%s\n", sym_test_prog(st));
826 835 (void) fprintf(logf, "COMMAND: %s\n", cmd);
827 836 (void) fprintf(logf, "EXPECT: %s\n", need ? "OK" : "FAIL");
828 837 (void) fclose(logf);
829 838
830 839 switch (system(cmd)) {
831 840 case -1:
832 841 test_failed(t, "error compiling in %s: %s", env_name(cenv),
833 842 strerror(errno));
834 843 return (-1);
835 844 case 0:
836 845 if (!need) {
837 846 fail_count++;
838 847 show_file(t, lfile);
839 848 test_failed(t, "symbol visible in %s", env_name(cenv));
840 849 return (-1);
841 850 }
842 851 break;
843 852 default:
844 853 if (need) {
845 854 fail_count++;
846 855 show_file(t, lfile);
847 856 test_failed(t, "error compiling in %s", env_name(cenv));
848 857 return (-1);
849 858 }
850 859 break;
851 860 }
852 861 good_count++;
853 862 return (0);
854 863 }
855 864
856 865 void
857 866 test_compile(void)
858 867 {
859 868 struct sym_test *st;
860 869 struct compile_env *cenv;
861 870 test_t t;
↓ open down ↓ |
77 lines elided |
↑ open up ↑ |
862 871 int need;
863 872
864 873 for (st = next_sym_test(NULL); st; st = next_sym_test(st)) {
865 874 if ((sym != NULL) && strcmp(sym, sym_test_name(st))) {
866 875 continue;
867 876 }
868 877 /* XXX: we really want a sym_test_desc() */
869 878 for (cenv = sym_test_env(st, NULL, &need);
870 879 cenv != NULL;
871 880 cenv = sym_test_env(st, cenv, &need)) {
872 - t = test_start("%s : %c%s", st->name,
881 + t = test_start("%s : %c%s", sym_test_name(st),
873 882 need ? '+' : '-', env_name(cenv));
874 883 if (do_compile(t, st, cenv, need) == 0) {
875 884 test_passed(t);
876 885 }
877 886 }
878 887 }
879 888
880 889 if (full_count > 0) {
881 890 test_summary();
882 891 }
883 892 }
884 893
885 894 int
886 895 main(int argc, char **argv)
887 896 {
888 897 int optc;
889 898 int optC = 0;
890 899
891 900 while ((optc = getopt(argc, argv, "DdfCs:c:")) != EOF) {
892 901 switch (optc) {
893 902 case 'd':
894 903 test_set_debug();
895 904 break;
896 905 case 'f':
897 906 test_set_force();
898 907 break;
899 908 case 'D':
900 909 test_set_debug();
901 910 extra_debug++;
902 911 break;
903 912 case 'c':
904 913 compilation = optarg;
905 914 break;
906 915 case 'C':
907 916 optC++;
908 917 break;
909 918 case 's':
910 919 sym = optarg;
911 920 break;
912 921 default:
913 922 (void) fprintf(stderr, "Usage: %s [-df]\n", argv[0]);
914 923 exit(1);
915 924 }
916 925 }
917 926
918 927 if (test_load_config(NULL, compilation,
919 928 "env", do_env, "env_group", do_env_group, NULL) < 0) {
920 929 exit(1);
921 930 }
922 931
923 932 while (optind < argc) {
924 933 if (test_load_config(NULL, argv[optind++],
925 934 "type", do_type,
926 935 "value", do_value,
927 936 "func", do_func,
928 937 NULL) < 0) {
929 938 exit(1);
930 939 }
931 940 }
932 941
933 942 if (atexit(cleanup) != 0) {
934 943 perror("atexit");
935 944 exit(1);
936 945 }
937 946
938 947 if (mkworkdir() < 0) {
939 948 perror("mkdir");
940 949 exit(1);
941 950 }
942 951
943 952 find_compiler();
944 953 if (!optC)
945 954 test_compile();
946 955
947 956 exit(0);
948 957 }
↓ open down ↓ |
66 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX