symbols_test.c revision fc2512cfb727d49529d8ed99164db871f4829b73
/*
* This file and its contents are supplied under the terms of the
* Common Development and Distribution License ("CDDL"), version 1.0.
* You may only use this file in accordance with the terms of version
* 1.0 of the CDDL.
*
* A full copy of the text of the CDDL should have accompanied this
* source. A copy of the CDDL is also available via the Internet at
*/
/*
* Copyright 2015 Garrett D'Amore <garrett@damore.org>
* Copyright 2016 Joyent, Inc.
*/
/*
* This program tests symbol visibility in different compilation environments.
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <err.h>
#include <unistd.h>
#include <note.h>
#include <libcmdutils.h>
#include "test_common.h"
char *dname;
char *cfile;
char *ofile;
char *lfile;
char *efile;
static int good_count = 0;
static int fail_count = 0;
static int full_count = 0;
static int extra_debug = 0;
static char *compilation = "compilation.cfg";
#if defined(_LP64)
#define MFLAG "-m64"
#define MFLAG "-m32"
#endif
const char *compilers[] = {
"cc",
"gcc",
"/opt/sunstudio12.1/bin/cc",
};
#define WS " \t"
static int next_env = 0;
struct compile_env {
char *ce_name;
char *ce_lang;
char *ce_defs;
int ce_index;
};
struct env_group {
char *eg_name;
};
typedef enum {
} sym_type_t;
struct sym_test {
char *st_name;
char *st_rtype;
char *st_defval;
const char *st_prog;
};
static char *
mystrdup(const char *s)
{
char *r;
perror("strdup");
exit(1);
}
return (r);
}
static void *
{
void *buf;
perror("calloc");
exit(1);
}
return (buf);
}
static void
{
int rv;
if (rv < 0) {
perror("vasprintf");
exit(1);
}
}
static void
{
*sym_insert = st;
}
static int
{
for (int i = 0; i < MAXENV; i++) {
*mask |= (1ULL << i);
return (0);
}
}
return (0);
}
}
return (-1);
}
static int
{
char *item;
}
return (-1);
}
}
return (0);
}
static int
{
int act;
char *item;
switch (item[0]) {
case '+':
act = 1;
item++;
break;
case '-':
act = 0;
item++;
break;
default:
act = 1;
break;
}
mask = 0;
}
return (-1);
}
if (act) {
} else {
}
}
return (0);
}
static int
{
char *name;
char *lang;
char *defs;
if (nfields != 3) {
return (-1);
}
return (-1);
}
next_env++;
return (0);
}
static int
{
char *name;
char *list;
char *item;
if (nfields != 2) {
return (-1);
}
mask = 0;
return (-1);
}
env_groups = eg;
return (0);
}
static void
addprogch(char c)
{
perror("custr_appendc");
exit(1);
}
}
static void
addprogstr(char *s)
{
perror("custr_append");
exit(1);
}
}
static void
addprogfmt(const char *fmt, ...)
{
perror("custr_append_vprintf");
exit(1);
}
}
static void
{
char *s = NULL;
}
addprogch(*s);
if (*s == '(') {
s++;
addprogch(*s);
s++;
break;
}
}
addprogch(' ');
}
/* for function pointers, s is closing suffix, otherwise empty */
case SYM_TYPE:
addprogstr("test_type;");
break;
case SYM_VALUE:
addprogstr("void\ntest_func(void)\n{\n");
break;
case SYM_DEFINE:
addprogfmt("\n#error %s is not defined or has the wrong value",
addprogfmt("\n#endif\n");
break;
case SYM_FUNC:
addprogstr("\ntest_func(");
int didname = 0;
if (i > 0) {
addprogstr(", ");
}
didname = 1;
}
didname = 1;
addprogstr("void");
}
/* print the argument list */
addprogfmt("(*a%d", i);
didname = 1;
a++;
} else if (*a == '[' && !didname) {
addprogfmt("a%d[", i);
didname = 1;
} else {
addprogch(*a);
}
}
if (!didname) {
addprogfmt(" a%d", i);
}
}
addprogstr("void");
}
/*
* Close argument list, and closing ")" for func ptrs.
* Note that for non-function pointers, s will be empty
* below, otherwise it points to the trailing argument
* list.
*/
addprogfmt(")%s\n{\n\t", s);
addprogstr("return ");
}
/* add the function call */
}
}
addprogstr(");\n}");
break;
}
addprogch('\n');
}
static int
{
char *item;
&item) < 0) {
return (-1);
}
return (0);
}
static int
{
int i = 0;
if (i >= MAXHDR) {
return (-1);
}
test_trim(&h);
}
return (0);
}
static int
{
int i = 0;
char *a;
if (i >= MAXARG) {
return (-1);
}
test_trim(&a);
}
return (0);
}
static int
{
char *decl;
char *hdrs;
char *envs;
if (nfields != 3) {
return (-1);
}
return (-1);
}
return (0);
}
static int
{
char *name;
char *type;
char *hdrs;
char *envs;
if (nfields != 4) {
return (-1);
}
return (-1);
}
return (0);
}
static int
{
if (nfields != 4) {
return (-1);
}
/*
* A value to compare against is optional. trim will leave it as a null
* pointer if there's nothing there.
*/
if (*value != '\0')
return (-1);
}
return (0);
}
static int
{
char *name;
char *rtype;
char *atype;
char *hdrs;
char *envs;
if (nfields != 5) {
return (-1);
}
return (-1);
}
return (0);
}
struct sym_test *
{
}
const char *
{
}
}
const char *
{
}
/*
* Iterate through tests. Pass in NULL for cenv to begin the iteration. For
* subsequent iterations, use the return value from the previous iteration.
* Returns NULL when there are no more environments.
*/
struct compile_env *
{
uint64_t b = 1ULL << i;
while ((i < MAXENV) && (b != 0)) {
cenv = &compile_env[i];
if (b & st->st_test_mask) {
return (cenv);
}
b <<= 1;
i++;
}
return (NULL);
}
const char *
{
}
const char *
{
}
const char *
{
}
static void
{
FILE *f;
int line = 1;
if (f == NULL) {
return;
}
line++;
}
(void) fclose(f);
}
static void
cleanup(void)
{
}
}
}
}
if (dname) {
}
}
static int
mkworkdir(void)
{
char b[32];
char *d;
cleanup();
(void) strlcpy(b, "/tmp/symbols_testXXXXXX", sizeof (b));
perror("mkdtemp");
return (-1);
}
return (0);
}
void
find_compiler(void)
{
test_t t;
int i;
t = test_start("finding compiler");
return;
}
char cmd[256];
int rv;
continue;
} else {
rv = -1;
}
switch (rv) {
case 51: /* STUDIO */
test_debugf(t, "Found Studio C");
if (extra_debug) {
}
test_passed(t);
break;
case 52: /* GCC */
test_debugf(t, "Found GNU C");
c89flags = "-Wall -Werror -std=c89 -nostdinc "
c99flags = "-Wall -Werror -std=c99 -nostdinc "
c11flags = "-Wall -Werror -std=c11 -nostdinc "
if (extra_debug) {
}
test_passed(t);
break;
case 99:
test_debugf(t, "Found unknown (unsupported) compiler");
continue;
default:
continue;
}
return;
}
test_failed(t, "No compiler found.");
}
int
{
char *cmd;
full_count++;
return (-1);
}
return (-1);
}
return (-1);
}
lang = "c99";
lang = "c11";
} else {
lang = "c89";
}
lang);
return (-1);
}
if (extra_debug) {
}
return (-1);
}
case -1:
return (-1);
case 0:
if (!need) {
fail_count++;
return (-1);
}
break;
default:
if (need) {
fail_count++;
return (-1);
}
break;
}
good_count++;
return (0);
}
void
test_compile(void)
{
struct compile_env *cenv;
test_t t;
int need;
continue;
}
/* XXX: we really want a sym_test_desc() */
test_passed(t);
}
}
}
if (full_count > 0) {
test_summary();
}
}
int
{
int optc;
int optC = 0;
switch (optc) {
case 'd':
break;
case 'f':
break;
case 'D':
extra_debug++;
break;
case 'c':
break;
case 'C':
optC++;
break;
case 's':
break;
default:
exit(1);
}
}
exit(1);
}
"type", do_type,
"value", do_value,
"define", do_define,
"func", do_func,
NULL) < 0) {
exit(1);
}
}
perror("atexit");
exit(1);
}
perror("custr");
exit(1);
}
if (mkworkdir() < 0) {
perror("mkdir");
exit(1);
}
if (!optC)
test_compile();
exit(0);
}