57 "/opt/gcc/4.4.4/bin/gcc",
58 "/opt/sunstudio12.1/bin/cc",
59 "/opt/sfw/bin/gcc",
60 "/usr/local/bin/gcc",
61 NULL
62 };
63
64 char *compiler = NULL;
65 const char *c89flags = NULL;
66 const char *c99flags = NULL;
67
68 #define MAXENV 64 /* maximum number of environments (bitmask width) */
69 #define MAXHDR 10 /* maximum # headers to require to access symbol */
70 #define MAXARG 20 /* maximum # of arguments */
71
72 #define WS " \t"
73
74 static int next_env = 0;
75
76 struct compile_env {
77 char *name;
78 char *lang;
79 char *defs;
80 int index;
81 };
82
83 static struct compile_env compile_env[MAXENV];
84
85 struct env_group {
86 char *name;
87 uint64_t mask;
88 struct env_group *next;
89 };
90
91 typedef enum { SYM_TYPE, SYM_VALUE, SYM_FUNC } sym_type_t;
92
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;
103 };
104
105 struct env_group *env_groups = NULL;
106
107 struct sym_test *sym_tests = NULL;
108 struct sym_test **sym_insert = &sym_tests;
109
110 static char *
111 mystrdup(const char *s)
112 {
113 char *r;
114 if ((r = strdup(s)) == NULL) {
115 perror("strdup");
116 exit(1);
117 }
118 return (r);
119 }
120
121 static void *
122 myzalloc(size_t sz)
130 }
131
132 static void
133 myasprintf(char **buf, const char *fmt, ...)
134 {
135 int rv;
136 va_list va;
137 va_start(va, fmt);
138 rv = vasprintf(buf, fmt, va);
139 va_end(va);
140 if (rv < 0) {
141 perror("vasprintf");
142 exit(1);
143 }
144 }
145
146 static void
147 append_sym_test(struct sym_test *st)
148 {
149 *sym_insert = st;
150 sym_insert = &st->next;
151 }
152
153 static int
154 find_env_mask(const char *name, uint64_t *mask)
155 {
156 for (int i = 0; i < 64; i++) {
157 if (compile_env[i].name != NULL &&
158 strcmp(compile_env[i].name, name) == 0) {
159 *mask |= (1ULL << i);
160 return (0);
161 }
162 }
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;
167 return (0);
168 }
169 }
170 return (-1);
171 }
172
173
174 static int
175 expand_env(char *list, uint64_t *mask, char **erritem)
176 {
177 char *item;
178 for (item = strtok(list, WS); item != NULL; item = strtok(NULL, WS)) {
179 if (find_env_mask(item, mask) < 0) {
180 if (erritem != NULL) {
181 *erritem = item;
182 }
183 return (-1);
184 }
185 }
186 return (0);
228 do_env(char **fields, int nfields, char **err)
229 {
230 char *name;
231 char *lang;
232 char *defs;
233
234 if (nfields != 3) {
235 myasprintf(err, "number of fields (%d) != 3", nfields);
236 return (-1);
237 }
238
239 if (next_env >= MAXENV) {
240 myasprintf(err, "too many environments");
241 return (-1);
242 }
243
244 name = fields[0];
245 lang = fields[1];
246 defs = fields[2];
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;
252 next_env++;
253 return (0);
254 }
255
256 static int
257 do_env_group(char **fields, int nfields, char **err)
258 {
259 char *name;
260 char *list;
261 struct env_group *eg;
262 uint64_t mask;
263 char *item;
264
265 if (nfields != 2) {
266 myasprintf(err, "number of fields (%d) != 2", nfields);
267 return (-1);
268 }
269
270 name = fields[0];
271 list = fields[1];
272 mask = 0;
273
274 if (expand_env(list, &mask, &item) < 0) {
275 myasprintf(err, "reference to undefined env %s", item);
276 return (-1);
277 }
278
279 eg = myzalloc(sizeof (*eg));
280 eg->name = mystrdup(name);
281 eg->mask = mask;
282 eg->next = env_groups;
283 env_groups = eg;
284 return (0);
285 }
286
287 static char *progbuf = NULL;
288 size_t proglen = 0;
289 size_t progsiz = 0;
290
291 static void
292 addprogch(char c)
293 {
294 while (progsiz <= (proglen + 1)) {
295 progbuf = realloc(progbuf, progsiz + 4096);
296 if (progbuf == NULL) {
297 perror("realloc");
298 exit(1);
299 }
300 progsiz += 1024;
301 }
302 progbuf[proglen++] = c;
317 {
318 va_list va;
319 char *buf = NULL;
320 va_start(va, fmt);
321 if (vasprintf(&buf, fmt, va) < 0) {
322 perror("vasprintf");
323 exit(1);
324 }
325 va_end(va);
326 addprogstr(buf);
327 free(buf);
328 }
329
330 static void
331 mkprog(struct sym_test *st)
332 {
333 char *s;
334
335 proglen = 0;
336
337 for (int i = 0; i < MAXHDR && st->hdrs[i] != NULL; i++) {
338 addprogfmt("#include <%s>\n", st->hdrs[i]);
339 }
340
341 for (s = st->rtype; *s; s++) {
342 addprogch(*s);
343 if (*s == '(') {
344 s++;
345 addprogch(*s);
346 s++;
347 break;
348 }
349 }
350 addprogch(' ');
351
352 /* for function pointers, s is closing suffix, otherwise empty */
353
354 switch (st->type) {
355 case SYM_TYPE:
356 addprogstr("test_type;");
357 break;
358
359 case SYM_VALUE:
360 addprogfmt("test_value%s;\n", s); /* s usually empty */
361 addprogstr("void\ntest_func(void)\n{\n");
362 addprogfmt("\ttest_value = %s;\n}", st->name);
363 break;
364
365 case SYM_FUNC:
366 addprogstr("\ntest_func(");
367 for (int i = 0; st->atypes[i] != NULL && i < MAXARG; i++) {
368 int didname = 0;
369 if (i > 0) {
370 addprogstr(", ");
371 }
372 if (strcmp(st->atypes[i], "void") == 0) {
373 didname = 1;
374 }
375 if (strcmp(st->atypes[i], "") == 0) {
376 didname = 1;
377 addprogstr("void");
378 }
379
380 /* print the argument list */
381 for (char *a = st->atypes[i]; *a; a++) {
382 if (*a == '(' && a[1] == '*' && !didname) {
383 addprogfmt("(*a%d", i);
384 didname = 1;
385 a++;
386 } else if (*a == '[' && !didname) {
387 addprogfmt("a%d[", i);
388 didname = 1;
389 } else {
390 addprogch(*a);
391 }
392 }
393 if (!didname) {
394 addprogfmt(" a%d", i);
395 }
396 }
397
398 if (st->atypes[0] == NULL) {
399 addprogstr("void");
400 }
401
402 /* close argument list, and closing ")" for func ptrs */
403 addprogfmt(")%s\n{\n\t", s); /* NB: s is normally empty */
404
405 if (strcmp(st->rtype, "") != 0 &&
406 strcmp(st->rtype, "void") != 0) {
407 addprogstr("return ");
408 }
409
410 /* 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) {
415 addprogfmt("%sa%d", i > 0 ? ", " : "", i);
416 }
417 }
418
419 addprogstr(");\n}");
420 break;
421 }
422
423 addprogch('\n');
424
425 st->prog = progbuf;
426 }
427
428 static int
429 add_envs(struct sym_test *st, char *envs, char **err)
430 {
431 char *item;
432 if (expand_env_list(envs, &st->test_mask, &st->need_mask, &item) < 0) {
433 myasprintf(err, "bad env action %s", item);
434 return (-1);
435 }
436 return (0);
437 }
438
439 static int
440 add_headers(struct sym_test *st, char *hdrs, char **err)
441 {
442 int i = 0;
443
444 for (char *h = strsep(&hdrs, ";"); h != NULL; h = strsep(&hdrs, ";")) {
445 if (i >= MAXHDR) {
446 myasprintf(err, "too many headers");
447 return (-1);
448 }
449 test_trim(&h);
450 st->hdrs[i++] = mystrdup(h);
451 }
452
453 return (0);
454 }
455
456 static int
457 add_arg_types(struct sym_test *st, char *atype, char **err)
458 {
459 int i = 0;
460 char *a;
461 for (a = strsep(&atype, ";"); a != NULL; a = strsep(&atype, ";")) {
462 if (i >= MAXARG) {
463 myasprintf(err, "too many arguments");
464 return (-1);
465 }
466 test_trim(&a);
467 st->atypes[i++] = mystrdup(a);
468 }
469
470 return (0);
471 }
472
473 static int
474 do_type(char **fields, int nfields, char **err)
475 {
476 char *decl;
477 char *hdrs;
478 char *envs;
479 struct sym_test *st;
480
481 if (nfields != 3) {
482 myasprintf(err, "number of fields (%d) != 3", nfields);
483 return (-1);
484 }
485 decl = fields[0];
486 hdrs = fields[1];
487 envs = fields[2];
488
489 st = myzalloc(sizeof (*st));
490 st->type = SYM_TYPE;
491 st->name = mystrdup(decl);
492 st->rtype = mystrdup(decl);
493
494 if ((add_envs(st, envs, err) < 0) ||
495 (add_headers(st, hdrs, err) < 0)) {
496 return (-1);
497 }
498 append_sym_test(st);
499
500 return (0);
501 }
502
503 static int
504 do_value(char **fields, int nfields, char **err)
505 {
506 char *name;
507 char *type;
508 char *hdrs;
509 char *envs;
510 struct sym_test *st;
511
512 if (nfields != 4) {
513 myasprintf(err, "number of fields (%d) != 4", nfields);
514 return (-1);
515 }
516 name = fields[0];
517 type = fields[1];
518 hdrs = fields[2];
519 envs = fields[3];
520
521 st = myzalloc(sizeof (*st));
522 st->type = SYM_VALUE;
523 st->name = mystrdup(name);
524 st->rtype = mystrdup(type);
525
526 if ((add_envs(st, envs, err) < 0) ||
527 (add_headers(st, hdrs, err) < 0)) {
528 return (-1);
529 }
530 append_sym_test(st);
531
532 return (0);
533 }
534
535 static int
536 do_func(char **fields, int nfields, char **err)
537 {
538 char *name;
539 char *rtype;
540 char *atype;
541 char *hdrs;
542 char *envs;
543 struct sym_test *st;
544
545 if (nfields != 5) {
546 myasprintf(err, "number of fields (%d) != 5", nfields);
547 return (-1);
548 }
549 name = fields[0];
550 rtype = fields[1];
551 atype = fields[2];
552 hdrs = fields[3];
553 envs = fields[4];
554
555 st = myzalloc(sizeof (*st));
556 st->type = SYM_FUNC;
557 st->name = mystrdup(name);
558 st->rtype = mystrdup(rtype);
559
560 if ((add_envs(st, envs, err) < 0) ||
561 (add_headers(st, hdrs, err) < 0) ||
562 (add_arg_types(st, atype, err) < 0)) {
563 return (-1);
564 }
565 append_sym_test(st);
566
567 return (0);
568 }
569
570 struct sym_test *
571 next_sym_test(struct sym_test *st)
572 {
573 return (st == NULL ? sym_tests : st->next);
574 }
575
576 const char *
577 sym_test_prog(struct sym_test *st)
578 {
579 if (st->prog == NULL) {
580 mkprog(st);
581 }
582 return (st->prog);
583 }
584
585 const char *
586 sym_test_name(struct sym_test *st)
587 {
588 return (st->name);
589 }
590
591 /*
592 * Iterate through tests. Pass in NULL for cenv to begin the iteration. For
593 * subsequent iterations, use the return value from the previous iteration.
594 * Returns NULL when there are no more environments.
595 */
596 struct compile_env *
597 sym_test_env(struct sym_test *st, struct compile_env *cenv, int *need)
598 {
599 int i = cenv ? cenv->index + 1: 0;
600 uint64_t b = 1ULL << i;
601
602 while ((i < MAXENV) && (b != 0)) {
603 cenv = &compile_env[i];
604 if (b & st->test_mask) {
605 *need = (st->need_mask & b) ? 1 : 0;
606 return (cenv);
607 }
608 b <<= 1;
609 i++;
610 }
611 return (NULL);
612 }
613
614 const char *
615 env_name(struct compile_env *cenv)
616 {
617 return (cenv->name);
618 }
619
620 const char *
621 env_lang(struct compile_env *cenv)
622 {
623 return (cenv->lang);
624 }
625
626 const char *
627 env_defs(struct compile_env *cenv)
628 {
629 return (cenv->defs);
630 }
631
632 static void
633 show_file(test_t t, const char *path)
634 {
635 FILE *f;
636 char *buf = NULL;
637 size_t cap = 0;
638 int line = 1;
639
640 f = fopen(path, "r");
641 if (f == NULL) {
642 test_debugf(t, "fopen(%s): %s", path, strerror(errno));
643 return;
644 }
645
646 test_debugf(t, "----->> begin (%s) <<------", path);
647 while (getline(&buf, &cap, f) >= 0) {
648 (void) strtok(buf, "\r\n");
649 test_debugf(t, "%d: %s", line, buf);
755 case 51: /* STUDIO */
756 test_debugf(t, "Found Studio C");
757 c89flags = "-Xc -errwarn=%all -v -xc99=%none " MFLAG;
758 c99flags = "-Xc -errwarn=%all -v -xc99=%all " MFLAG;
759 if (extra_debug) {
760 test_debugf(t, "c89flags: %s", c89flags);
761 test_debugf(t, "c99flags: %s", c99flags);
762 }
763 test_passed(t);
764 break;
765 case 52: /* GCC */
766 test_debugf(t, "Found GNU C");
767 c89flags = "-Wall -Werror -std=c89 " MFLAG;
768 c99flags = "-Wall -Werror -std=c99 " MFLAG;
769 if (extra_debug) {
770 test_debugf(t, "c89flags: %s", c89flags);
771 test_debugf(t, "c99flags: %s", c99flags);
772 }
773 test_passed(t);
774 break;
775 default:
776 continue;
777 }
778 myasprintf(&compiler, "%s", compilers[i]);
779 test_debugf(t, "compiler: %s", compiler);
780 return;
781 }
782 test_failed(t, "No compiler found.");
783 }
784
785 int
786 do_compile(test_t t, struct sym_test *st, struct compile_env *cenv, int need)
787 {
788 char *cmd;
789 FILE *logf;
790 FILE *dotc;
791 const char *prog;
792
793 full_count++;
794
852 good_count++;
853 return (0);
854 }
855
856 void
857 test_compile(void)
858 {
859 struct sym_test *st;
860 struct compile_env *cenv;
861 test_t t;
862 int need;
863
864 for (st = next_sym_test(NULL); st; st = next_sym_test(st)) {
865 if ((sym != NULL) && strcmp(sym, sym_test_name(st))) {
866 continue;
867 }
868 /* XXX: we really want a sym_test_desc() */
869 for (cenv = sym_test_env(st, NULL, &need);
870 cenv != NULL;
871 cenv = sym_test_env(st, cenv, &need)) {
872 t = test_start("%s : %c%s", st->name,
873 need ? '+' : '-', env_name(cenv));
874 if (do_compile(t, st, cenv, need) == 0) {
875 test_passed(t);
876 }
877 }
878 }
879
880 if (full_count > 0) {
881 test_summary();
882 }
883 }
884
885 int
886 main(int argc, char **argv)
887 {
888 int optc;
889 int optC = 0;
890
891 while ((optc = getopt(argc, argv, "DdfCs:c:")) != EOF) {
892 switch (optc) {
|
57 "/opt/gcc/4.4.4/bin/gcc",
58 "/opt/sunstudio12.1/bin/cc",
59 "/opt/sfw/bin/gcc",
60 "/usr/local/bin/gcc",
61 NULL
62 };
63
64 char *compiler = NULL;
65 const char *c89flags = NULL;
66 const char *c99flags = NULL;
67
68 #define MAXENV 64 /* maximum number of environments (bitmask width) */
69 #define MAXHDR 10 /* maximum # headers to require to access symbol */
70 #define MAXARG 20 /* maximum # of arguments */
71
72 #define WS " \t"
73
74 static int next_env = 0;
75
76 struct compile_env {
77 char *ce_name;
78 char *ce_lang;
79 char *ce_defs;
80 int ce_index;
81 };
82
83 static struct compile_env compile_env[MAXENV];
84
85 struct env_group {
86 char *eg_name;
87 uint64_t eg_mask;
88 struct env_group *eg_next;
89 };
90
91 typedef enum { SYM_TYPE, SYM_VALUE, SYM_FUNC } sym_type_t;
92
93 struct sym_test {
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 };
104
105 struct env_group *env_groups = NULL;
106
107 struct sym_test *sym_tests = NULL;
108 struct sym_test **sym_insert = &sym_tests;
109
110 static char *
111 mystrdup(const char *s)
112 {
113 char *r;
114 if ((r = strdup(s)) == NULL) {
115 perror("strdup");
116 exit(1);
117 }
118 return (r);
119 }
120
121 static void *
122 myzalloc(size_t sz)
130 }
131
132 static void
133 myasprintf(char **buf, const char *fmt, ...)
134 {
135 int rv;
136 va_list va;
137 va_start(va, fmt);
138 rv = vasprintf(buf, fmt, va);
139 va_end(va);
140 if (rv < 0) {
141 perror("vasprintf");
142 exit(1);
143 }
144 }
145
146 static void
147 append_sym_test(struct sym_test *st)
148 {
149 *sym_insert = st;
150 sym_insert = &st->st_next;
151 }
152
153 static int
154 find_env_mask(const char *name, uint64_t *mask)
155 {
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 *mask |= (1ULL << i);
160 return (0);
161 }
162 }
163
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 return (0);
168 }
169 }
170 return (-1);
171 }
172
173
174 static int
175 expand_env(char *list, uint64_t *mask, char **erritem)
176 {
177 char *item;
178 for (item = strtok(list, WS); item != NULL; item = strtok(NULL, WS)) {
179 if (find_env_mask(item, mask) < 0) {
180 if (erritem != NULL) {
181 *erritem = item;
182 }
183 return (-1);
184 }
185 }
186 return (0);
228 do_env(char **fields, int nfields, char **err)
229 {
230 char *name;
231 char *lang;
232 char *defs;
233
234 if (nfields != 3) {
235 myasprintf(err, "number of fields (%d) != 3", nfields);
236 return (-1);
237 }
238
239 if (next_env >= MAXENV) {
240 myasprintf(err, "too many environments");
241 return (-1);
242 }
243
244 name = fields[0];
245 lang = fields[1];
246 defs = fields[2];
247
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 next_env++;
253 return (0);
254 }
255
256 static int
257 do_env_group(char **fields, int nfields, char **err)
258 {
259 char *name;
260 char *list;
261 struct env_group *eg;
262 uint64_t mask;
263 char *item;
264
265 if (nfields != 2) {
266 myasprintf(err, "number of fields (%d) != 2", nfields);
267 return (-1);
268 }
269
270 name = fields[0];
271 list = fields[1];
272 mask = 0;
273
274 if (expand_env(list, &mask, &item) < 0) {
275 myasprintf(err, "reference to undefined env %s", item);
276 return (-1);
277 }
278
279 eg = myzalloc(sizeof (*eg));
280 eg->eg_name = mystrdup(name);
281 eg->eg_mask = mask;
282 eg->eg_next = env_groups;
283 env_groups = eg;
284 return (0);
285 }
286
287 static char *progbuf = NULL;
288 size_t proglen = 0;
289 size_t progsiz = 0;
290
291 static void
292 addprogch(char c)
293 {
294 while (progsiz <= (proglen + 1)) {
295 progbuf = realloc(progbuf, progsiz + 4096);
296 if (progbuf == NULL) {
297 perror("realloc");
298 exit(1);
299 }
300 progsiz += 1024;
301 }
302 progbuf[proglen++] = c;
317 {
318 va_list va;
319 char *buf = NULL;
320 va_start(va, fmt);
321 if (vasprintf(&buf, fmt, va) < 0) {
322 perror("vasprintf");
323 exit(1);
324 }
325 va_end(va);
326 addprogstr(buf);
327 free(buf);
328 }
329
330 static void
331 mkprog(struct sym_test *st)
332 {
333 char *s;
334
335 proglen = 0;
336
337 for (int i = 0; i < MAXHDR && st->st_hdrs[i] != NULL; i++) {
338 addprogfmt("#include <%s>\n", st->st_hdrs[i]);
339 }
340
341 for (s = st->st_rtype; *s; s++) {
342 addprogch(*s);
343 if (*s == '(') {
344 s++;
345 addprogch(*s);
346 s++;
347 break;
348 }
349 }
350 addprogch(' ');
351
352 /* for function pointers, s is closing suffix, otherwise empty */
353
354 switch (st->st_type) {
355 case SYM_TYPE:
356 addprogstr("test_type;");
357 break;
358
359 case SYM_VALUE:
360 addprogfmt("test_value%s;\n", s); /* s usually empty */
361 addprogstr("void\ntest_func(void)\n{\n");
362 addprogfmt("\ttest_value = %s;\n}", st->st_name);
363 break;
364
365 case SYM_FUNC:
366 addprogstr("\ntest_func(");
367 for (int i = 0; st->st_atypes[i] != NULL && i < MAXARG; i++) {
368 int didname = 0;
369 if (i > 0) {
370 addprogstr(", ");
371 }
372 if (strcmp(st->st_atypes[i], "void") == 0) {
373 didname = 1;
374 }
375 if (strcmp(st->st_atypes[i], "") == 0) {
376 didname = 1;
377 addprogstr("void");
378 }
379
380 /* print the argument list */
381 for (char *a = st->st_atypes[i]; *a; a++) {
382 if (*a == '(' && a[1] == '*' && !didname) {
383 addprogfmt("(*a%d", i);
384 didname = 1;
385 a++;
386 } else if (*a == '[' && !didname) {
387 addprogfmt("a%d[", i);
388 didname = 1;
389 } else {
390 addprogch(*a);
391 }
392 }
393 if (!didname) {
394 addprogfmt(" a%d", i);
395 }
396 }
397
398 if (st->st_atypes[0] == NULL) {
399 addprogstr("void");
400 }
401
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);
409
410 if (strcmp(st->st_rtype, "") != 0 &&
411 strcmp(st->st_rtype, "void") != 0) {
412 addprogstr("return ");
413 }
414
415 /* add the function call */
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) {
420 addprogfmt("%sa%d", i > 0 ? ", " : "", i);
421 }
422 }
423
424 addprogstr(");\n}");
425 break;
426 }
427
428 addprogch('\n');
429
430 st->st_prog = progbuf;
431 }
432
433 static int
434 add_envs(struct sym_test *st, char *envs, char **err)
435 {
436 char *item;
437 if (expand_env_list(envs, &st->st_test_mask, &st->st_need_mask,
438 &item) < 0) {
439 myasprintf(err, "bad env action %s", item);
440 return (-1);
441 }
442 return (0);
443 }
444
445 static int
446 add_headers(struct sym_test *st, char *hdrs, char **err)
447 {
448 int i = 0;
449
450 for (char *h = strsep(&hdrs, ";"); h != NULL; h = strsep(&hdrs, ";")) {
451 if (i >= MAXHDR) {
452 myasprintf(err, "too many headers");
453 return (-1);
454 }
455 test_trim(&h);
456 st->st_hdrs[i++] = mystrdup(h);
457 }
458
459 return (0);
460 }
461
462 static int
463 add_arg_types(struct sym_test *st, char *atype, char **err)
464 {
465 int i = 0;
466 char *a;
467 for (a = strsep(&atype, ";"); a != NULL; a = strsep(&atype, ";")) {
468 if (i >= MAXARG) {
469 myasprintf(err, "too many arguments");
470 return (-1);
471 }
472 test_trim(&a);
473 st->st_atypes[i++] = mystrdup(a);
474 }
475
476 return (0);
477 }
478
479 static int
480 do_type(char **fields, int nfields, char **err)
481 {
482 char *decl;
483 char *hdrs;
484 char *envs;
485 struct sym_test *st;
486
487 if (nfields != 3) {
488 myasprintf(err, "number of fields (%d) != 3", nfields);
489 return (-1);
490 }
491 decl = fields[0];
492 hdrs = fields[1];
493 envs = fields[2];
494
495 st = myzalloc(sizeof (*st));
496 st->st_type = SYM_TYPE;
497 st->st_name = mystrdup(decl);
498 st->st_rtype = mystrdup(decl);
499
500 if ((add_envs(st, envs, err) < 0) ||
501 (add_headers(st, hdrs, err) < 0)) {
502 return (-1);
503 }
504 append_sym_test(st);
505
506 return (0);
507 }
508
509 static int
510 do_value(char **fields, int nfields, char **err)
511 {
512 char *name;
513 char *type;
514 char *hdrs;
515 char *envs;
516 struct sym_test *st;
517
518 if (nfields != 4) {
519 myasprintf(err, "number of fields (%d) != 4", nfields);
520 return (-1);
521 }
522 name = fields[0];
523 type = fields[1];
524 hdrs = fields[2];
525 envs = fields[3];
526
527 st = myzalloc(sizeof (*st));
528 st->st_type = SYM_VALUE;
529 st->st_name = mystrdup(name);
530 st->st_rtype = mystrdup(type);
531
532 if ((add_envs(st, envs, err) < 0) ||
533 (add_headers(st, hdrs, err) < 0)) {
534 return (-1);
535 }
536 append_sym_test(st);
537
538 return (0);
539 }
540
541 static int
542 do_func(char **fields, int nfields, char **err)
543 {
544 char *name;
545 char *rtype;
546 char *atype;
547 char *hdrs;
548 char *envs;
549 struct sym_test *st;
550
551 if (nfields != 5) {
552 myasprintf(err, "number of fields (%d) != 5", nfields);
553 return (-1);
554 }
555 name = fields[0];
556 rtype = fields[1];
557 atype = fields[2];
558 hdrs = fields[3];
559 envs = fields[4];
560
561 st = myzalloc(sizeof (*st));
562 st->st_type = SYM_FUNC;
563 st->st_name = mystrdup(name);
564 st->st_rtype = mystrdup(rtype);
565
566 if ((add_envs(st, envs, err) < 0) ||
567 (add_headers(st, hdrs, err) < 0) ||
568 (add_arg_types(st, atype, err) < 0)) {
569 return (-1);
570 }
571 append_sym_test(st);
572
573 return (0);
574 }
575
576 struct sym_test *
577 next_sym_test(struct sym_test *st)
578 {
579 return (st == NULL ? sym_tests : st->st_next);
580 }
581
582 const char *
583 sym_test_prog(struct sym_test *st)
584 {
585 if (st->st_prog == NULL) {
586 mkprog(st);
587 }
588 return (st->st_prog);
589 }
590
591 const char *
592 sym_test_name(struct sym_test *st)
593 {
594 return (st->st_name);
595 }
596
597 /*
598 * Iterate through tests. Pass in NULL for cenv to begin the iteration. For
599 * subsequent iterations, use the return value from the previous iteration.
600 * Returns NULL when there are no more environments.
601 */
602 struct compile_env *
603 sym_test_env(struct sym_test *st, struct compile_env *cenv, int *need)
604 {
605 int i = cenv ? cenv->ce_index + 1: 0;
606 uint64_t b = 1ULL << i;
607
608 while ((i < MAXENV) && (b != 0)) {
609 cenv = &compile_env[i];
610 if (b & st->st_test_mask) {
611 *need = (st->st_need_mask & b) ? 1 : 0;
612 return (cenv);
613 }
614 b <<= 1;
615 i++;
616 }
617 return (NULL);
618 }
619
620 const char *
621 env_name(struct compile_env *cenv)
622 {
623 return (cenv->ce_name);
624 }
625
626 const char *
627 env_lang(struct compile_env *cenv)
628 {
629 return (cenv->ce_lang);
630 }
631
632 const char *
633 env_defs(struct compile_env *cenv)
634 {
635 return (cenv->ce_defs);
636 }
637
638 static void
639 show_file(test_t t, const char *path)
640 {
641 FILE *f;
642 char *buf = NULL;
643 size_t cap = 0;
644 int line = 1;
645
646 f = fopen(path, "r");
647 if (f == NULL) {
648 test_debugf(t, "fopen(%s): %s", path, strerror(errno));
649 return;
650 }
651
652 test_debugf(t, "----->> begin (%s) <<------", path);
653 while (getline(&buf, &cap, f) >= 0) {
654 (void) strtok(buf, "\r\n");
655 test_debugf(t, "%d: %s", line, buf);
761 case 51: /* STUDIO */
762 test_debugf(t, "Found Studio C");
763 c89flags = "-Xc -errwarn=%all -v -xc99=%none " MFLAG;
764 c99flags = "-Xc -errwarn=%all -v -xc99=%all " MFLAG;
765 if (extra_debug) {
766 test_debugf(t, "c89flags: %s", c89flags);
767 test_debugf(t, "c99flags: %s", c99flags);
768 }
769 test_passed(t);
770 break;
771 case 52: /* GCC */
772 test_debugf(t, "Found GNU C");
773 c89flags = "-Wall -Werror -std=c89 " MFLAG;
774 c99flags = "-Wall -Werror -std=c99 " MFLAG;
775 if (extra_debug) {
776 test_debugf(t, "c89flags: %s", c89flags);
777 test_debugf(t, "c99flags: %s", c99flags);
778 }
779 test_passed(t);
780 break;
781 case 99:
782 test_debugf(t, "Found unknown (unsupported) compiler");
783 continue;
784 default:
785 continue;
786 }
787 myasprintf(&compiler, "%s", compilers[i]);
788 test_debugf(t, "compiler: %s", compiler);
789 return;
790 }
791 test_failed(t, "No compiler found.");
792 }
793
794 int
795 do_compile(test_t t, struct sym_test *st, struct compile_env *cenv, int need)
796 {
797 char *cmd;
798 FILE *logf;
799 FILE *dotc;
800 const char *prog;
801
802 full_count++;
803
861 good_count++;
862 return (0);
863 }
864
865 void
866 test_compile(void)
867 {
868 struct sym_test *st;
869 struct compile_env *cenv;
870 test_t t;
871 int need;
872
873 for (st = next_sym_test(NULL); st; st = next_sym_test(st)) {
874 if ((sym != NULL) && strcmp(sym, sym_test_name(st))) {
875 continue;
876 }
877 /* XXX: we really want a sym_test_desc() */
878 for (cenv = sym_test_env(st, NULL, &need);
879 cenv != NULL;
880 cenv = sym_test_env(st, cenv, &need)) {
881 t = test_start("%s : %c%s", sym_test_name(st),
882 need ? '+' : '-', env_name(cenv));
883 if (do_compile(t, st, cenv, need) == 0) {
884 test_passed(t);
885 }
886 }
887 }
888
889 if (full_count > 0) {
890 test_summary();
891 }
892 }
893
894 int
895 main(int argc, char **argv)
896 {
897 int optc;
898 int optC = 0;
899
900 while ((optc = getopt(argc, argv, "DdfCs:c:")) != EOF) {
901 switch (optc) {
|