2007-02-02 14:56:53 +01:00
|
|
|
/*
|
2019-01-15 18:28:24 +01:00
|
|
|
* SPDX-License-Identifier: GPL-2.0-only
|
2008-10-01 17:47:42 +02:00
|
|
|
*
|
2007-02-02 14:56:53 +01:00
|
|
|
* Copyright (C) 2007 Davi E. M. Arnaut <davi@haxent.com.br>
|
|
|
|
*/
|
|
|
|
|
2007-03-30 16:33:17 +02:00
|
|
|
#include <argp.h>
|
2007-02-02 14:56:53 +01:00
|
|
|
#include <malloc.h>
|
|
|
|
#include <search.h>
|
|
|
|
#include <stdio.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
|
|
|
|
#include "dwarves.h"
|
2007-12-16 17:47:59 +01:00
|
|
|
#include "dutil.h"
|
2007-02-02 14:56:53 +01:00
|
|
|
|
|
|
|
static int verbose;
|
|
|
|
|
|
|
|
struct extvar {
|
|
|
|
struct extvar *next;
|
|
|
|
const char *name;
|
|
|
|
const struct variable *var;
|
|
|
|
const struct cu *cu;
|
|
|
|
};
|
|
|
|
|
|
|
|
struct extfun {
|
|
|
|
struct extfun *next;
|
|
|
|
const char *name;
|
|
|
|
const struct function *fun;
|
|
|
|
const struct cu *cu;
|
|
|
|
};
|
|
|
|
|
|
|
|
static void *tree;
|
|
|
|
|
|
|
|
static void oom(const char *msg)
|
|
|
|
{
|
|
|
|
fprintf(stderr, "pglobal: out of memory (%s)\n", msg);
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct extvar *extvar__new(const struct variable *var,
|
|
|
|
const struct cu *cu)
|
|
|
|
{
|
|
|
|
struct extvar *gvar = malloc(sizeof(*gvar));
|
|
|
|
|
|
|
|
if (gvar != NULL) {
|
|
|
|
gvar->next = NULL;
|
|
|
|
gvar->var = var;
|
|
|
|
gvar->cu = cu;
|
2009-04-02 17:40:33 +02:00
|
|
|
gvar->name = variable__name(var, cu);
|
2007-02-02 14:56:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
return gvar;
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct extfun *extfun__new(struct function *fun,
|
|
|
|
const struct cu *cu)
|
|
|
|
{
|
|
|
|
struct extfun *gfun = malloc(sizeof(*gfun));
|
|
|
|
|
|
|
|
if (gfun != NULL) {
|
|
|
|
gfun->next = NULL;
|
|
|
|
gfun->fun = fun;
|
|
|
|
gfun->cu = cu;
|
|
|
|
gfun->name = function__name(fun, cu);
|
|
|
|
}
|
|
|
|
|
|
|
|
return gfun;
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extvar__compare(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const struct extvar *ga = a, *gb = b;
|
|
|
|
return strcmp(ga->name, gb->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int extfun__compare(const void *a, const void *b)
|
|
|
|
{
|
|
|
|
const struct extfun *ga = a, *gb = b;
|
|
|
|
return strcmp(ga->name, gb->name);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void extvar__add(const struct variable *var, const struct cu *cu)
|
|
|
|
{
|
|
|
|
struct extvar **nodep, *gvar = extvar__new(var, cu);
|
|
|
|
|
|
|
|
if (gvar != NULL) {
|
|
|
|
nodep = tsearch(gvar, &tree, extvar__compare);
|
|
|
|
if (nodep == NULL)
|
|
|
|
oom("tsearch");
|
2019-07-02 17:30:50 +02:00
|
|
|
else if (*nodep != gvar) {
|
2007-02-02 14:56:53 +01:00
|
|
|
if (gvar->var->declaration) {
|
|
|
|
gvar->next = (*nodep)->next;
|
|
|
|
(*nodep)->next = gvar;
|
|
|
|
} else {
|
|
|
|
gvar->next = *nodep;
|
|
|
|
*nodep = gvar;
|
|
|
|
}
|
2019-07-02 17:30:50 +02:00
|
|
|
}
|
2007-02-02 14:56:53 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void extfun__add(struct function *fun, const struct cu *cu)
|
|
|
|
{
|
|
|
|
struct extfun **nodep, *gfun = extfun__new(fun, cu);
|
|
|
|
|
|
|
|
if (gfun != NULL) {
|
|
|
|
nodep = tsearch(gfun, &tree, extfun__compare);
|
|
|
|
if (nodep == NULL)
|
|
|
|
oom("tsearch");
|
|
|
|
else if (*nodep != gfun) {
|
|
|
|
gfun->next = (*nodep)->next;
|
|
|
|
(*nodep)->next = gfun;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2009-04-01 16:39:43 +02:00
|
|
|
static int cu_extvar_iterator(struct cu *cu, void *cookie __unused)
|
2007-02-02 14:56:53 +01:00
|
|
|
{
|
2009-04-01 16:39:43 +02:00
|
|
|
struct tag *pos;
|
|
|
|
uint32_t id;
|
2007-02-02 14:56:53 +01:00
|
|
|
|
2009-04-01 16:39:43 +02:00
|
|
|
cu__for_each_variable(cu, id, pos) {
|
|
|
|
struct variable *var = tag__variable(pos);
|
|
|
|
if (var->external)
|
|
|
|
extvar__add(var, cu);
|
|
|
|
}
|
2007-02-02 14:56:53 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2009-04-01 16:39:43 +02:00
|
|
|
static int cu_extfun_iterator(struct cu *cu, void *cookie __unused)
|
2007-02-02 14:56:53 +01:00
|
|
|
{
|
2009-04-01 16:39:43 +02:00
|
|
|
struct function *pos;
|
|
|
|
uint32_t id;
|
2007-02-02 14:56:53 +01:00
|
|
|
|
2009-04-01 16:39:43 +02:00
|
|
|
cu__for_each_function(cu, id, pos)
|
|
|
|
if (pos->external)
|
|
|
|
extfun__add(pos, cu);
|
|
|
|
return 0;
|
2007-02-02 14:56:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct extvar *node__variable(const void *nodep)
|
|
|
|
{
|
|
|
|
return *((const struct extvar **)nodep);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline const struct extfun *node__function(const void *nodep)
|
|
|
|
{
|
|
|
|
return *((const struct extfun **)nodep);
|
|
|
|
}
|
|
|
|
|
2007-07-02 02:00:21 +02:00
|
|
|
static inline struct tag *extvar__tag(const struct extvar *gvar)
|
2007-02-02 14:56:53 +01:00
|
|
|
{
|
2007-07-02 02:00:21 +02:00
|
|
|
return (struct tag *)gvar->var;
|
2007-02-02 14:56:53 +01:00
|
|
|
}
|
|
|
|
|
2007-07-02 02:00:21 +02:00
|
|
|
static inline struct tag *extfun__tag(const struct extfun *gfun)
|
2007-02-02 14:56:53 +01:00
|
|
|
{
|
2007-07-02 02:00:21 +02:00
|
|
|
return (struct tag *)gfun->fun;
|
2007-02-02 14:56:53 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
static void declaration_action__walk(const void *nodep, const VISIT which,
|
|
|
|
const int depth __unused)
|
|
|
|
{
|
|
|
|
uint32_t count = 0;
|
2007-07-02 02:00:21 +02:00
|
|
|
struct tag *tag;
|
2007-02-02 14:56:53 +01:00
|
|
|
const struct extvar *pos, *gvar = NULL;
|
|
|
|
|
|
|
|
switch(which) {
|
|
|
|
case preorder:
|
|
|
|
break;
|
|
|
|
case postorder:
|
|
|
|
gvar = node__variable(nodep);
|
|
|
|
break;
|
|
|
|
case endorder:
|
|
|
|
break;
|
|
|
|
case leaf:
|
|
|
|
gvar = node__variable(nodep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gvar == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tag = extvar__tag(gvar);
|
|
|
|
|
2007-04-28 21:13:35 +02:00
|
|
|
tag__fprintf(tag, gvar->cu, NULL, stdout);
|
2007-02-02 14:56:53 +01:00
|
|
|
|
|
|
|
for (pos = gvar->next; pos; pos = pos->next)
|
|
|
|
count++;
|
|
|
|
|
|
|
|
printf("; /* %u */\n\n", count);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void function_action__walk(const void *nodep, const VISIT which,
|
|
|
|
const int depth __unused)
|
|
|
|
{
|
2007-07-02 02:00:21 +02:00
|
|
|
struct tag *tag;
|
2007-02-02 14:56:53 +01:00
|
|
|
const struct extfun *gfun = NULL;
|
|
|
|
|
|
|
|
switch(which) {
|
|
|
|
case preorder:
|
|
|
|
break;
|
|
|
|
case postorder:
|
|
|
|
gfun = node__function(nodep);
|
|
|
|
break;
|
|
|
|
case endorder:
|
|
|
|
break;
|
|
|
|
case leaf:
|
|
|
|
gfun = node__function(nodep);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (gfun == NULL)
|
|
|
|
return;
|
|
|
|
|
|
|
|
tag = extfun__tag(gfun);
|
|
|
|
|
2007-04-28 21:13:35 +02:00
|
|
|
tag__fprintf(tag, gfun->cu, NULL, stdout);
|
2007-02-02 14:56:53 +01:00
|
|
|
|
|
|
|
fputs("\n\n", stdout);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void free_node(void *nodep)
|
|
|
|
{
|
|
|
|
void **node = nodep;
|
|
|
|
free(*node);
|
|
|
|
}
|
|
|
|
|
2009-02-13 13:57:23 +01:00
|
|
|
/* Name and version of program. */
|
|
|
|
ARGP_PROGRAM_VERSION_HOOK_DEF = dwarves_print_version;
|
|
|
|
|
2007-03-30 16:33:17 +02:00
|
|
|
static const struct argp_option pglobal__options[] = {
|
|
|
|
{
|
|
|
|
.key = 'v',
|
|
|
|
.name = "variables",
|
|
|
|
.doc = "show global variables",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.key = 'f',
|
|
|
|
.name = "functions",
|
|
|
|
.doc = "show global functions",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.key = 'V',
|
|
|
|
.name = "verbose",
|
|
|
|
.doc = "be verbose",
|
|
|
|
},
|
|
|
|
{
|
|
|
|
.name = NULL,
|
|
|
|
}
|
2007-02-02 14:56:53 +01:00
|
|
|
};
|
|
|
|
|
2007-03-30 16:33:17 +02:00
|
|
|
static int walk_var, walk_fun;
|
|
|
|
|
|
|
|
static error_t pglobal__options_parser(int key, char *arg __unused,
|
2007-03-30 19:02:33 +02:00
|
|
|
struct argp_state *state)
|
2007-02-02 14:56:53 +01:00
|
|
|
{
|
2007-03-30 16:33:17 +02:00
|
|
|
switch (key) {
|
2008-11-18 17:09:13 +01:00
|
|
|
case ARGP_KEY_INIT:
|
|
|
|
if (state->child_inputs != NULL)
|
|
|
|
state->child_inputs[0] = state->input;
|
|
|
|
break;
|
2007-03-30 16:33:17 +02:00
|
|
|
case 'v': walk_var = 1; break;
|
|
|
|
case 'f': walk_fun = 1; break;
|
|
|
|
case 'V': verbose = 1; break;
|
|
|
|
default: return ARGP_ERR_UNKNOWN;
|
|
|
|
}
|
|
|
|
return 0;
|
2007-02-02 14:56:53 +01:00
|
|
|
}
|
|
|
|
|
2008-01-31 12:30:55 +01:00
|
|
|
static const char pglobal__args_doc[] = "FILE";
|
2007-03-30 16:33:17 +02:00
|
|
|
|
|
|
|
static struct argp pglobal__argp = {
|
|
|
|
.options = pglobal__options,
|
|
|
|
.parser = pglobal__options_parser,
|
|
|
|
.args_doc = pglobal__args_doc,
|
|
|
|
};
|
|
|
|
|
2007-02-02 14:56:53 +01:00
|
|
|
int main(int argc, char *argv[])
|
|
|
|
{
|
2009-03-11 16:31:17 +01:00
|
|
|
int err, remaining, rc = EXIT_FAILURE;
|
2007-02-02 14:56:53 +01:00
|
|
|
|
2009-02-10 00:43:56 +01:00
|
|
|
if (argp_parse(&pglobal__argp, argc, argv, 0, &remaining, NULL) ||
|
|
|
|
remaining == argc) {
|
|
|
|
argp_help(&pglobal__argp, stderr, ARGP_HELP_SEE, argv[0]);
|
2009-03-11 16:31:17 +01:00
|
|
|
goto out;
|
|
|
|
}
|
|
|
|
|
all: Fix possible uninitialized variable uses
I wasn't especifying the optimization level and the default, despite
using -Wall, was for this so simple case not to be warned about, so
now I'm using -O2.
Alexandre provided a patch initializing the variables to NULL, so that
when we called cus__delete it would bail out and not possibly act on
a random value, I preferred to add extra goto labels and do the exit
path only on the resources that were successfully allocated/initialized,
avoiding, for instance, to call dwarves_exit() if dwarves_init() wasn't
called, which wasn't a problem so far, but could be in the future.
Reported-by: Alexandre Vassalotti <alexandre@peadrop.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2009-05-04 20:50:06 +02:00
|
|
|
if (dwarves__init(0)) {
|
2009-03-11 16:31:17 +01:00
|
|
|
fputs("pglobal: insufficient memory\n", stderr);
|
|
|
|
goto out;
|
2009-02-10 00:43:56 +01:00
|
|
|
}
|
|
|
|
|
all: Fix possible uninitialized variable uses
I wasn't especifying the optimization level and the default, despite
using -Wall, was for this so simple case not to be warned about, so
now I'm using -O2.
Alexandre provided a patch initializing the variables to NULL, so that
when we called cus__delete it would bail out and not possibly act on
a random value, I preferred to add extra goto labels and do the exit
path only on the resources that were successfully allocated/initialized,
avoiding, for instance, to call dwarves_exit() if dwarves_init() wasn't
called, which wasn't a problem so far, but could be in the future.
Reported-by: Alexandre Vassalotti <alexandre@peadrop.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2009-05-04 20:50:06 +02:00
|
|
|
struct cus *cus = cus__new();
|
|
|
|
if (cus == NULL) {
|
|
|
|
fputs("pglobal: insufficient memory\n", stderr);
|
|
|
|
goto out_dwarves_exit;
|
|
|
|
}
|
|
|
|
|
2009-03-13 14:49:01 +01:00
|
|
|
err = cus__load_files(cus, NULL, argv + remaining);
|
2016-03-15 18:29:57 +01:00
|
|
|
if (err != 0) {
|
|
|
|
cus__fprintf_load_files_err(cus, "pglobal", argv + remaining, err, stderr);
|
all: Fix possible uninitialized variable uses
I wasn't especifying the optimization level and the default, despite
using -Wall, was for this so simple case not to be warned about, so
now I'm using -O2.
Alexandre provided a patch initializing the variables to NULL, so that
when we called cus__delete it would bail out and not possibly act on
a random value, I preferred to add extra goto labels and do the exit
path only on the resources that were successfully allocated/initialized,
avoiding, for instance, to call dwarves_exit() if dwarves_init() wasn't
called, which wasn't a problem so far, but could be in the future.
Reported-by: Alexandre Vassalotti <alexandre@peadrop.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2009-05-04 20:50:06 +02:00
|
|
|
goto out_cus_delete;
|
2016-03-15 18:29:57 +01:00
|
|
|
}
|
2007-03-30 19:02:33 +02:00
|
|
|
|
2007-02-02 14:56:53 +01:00
|
|
|
if (walk_var) {
|
|
|
|
cus__for_each_cu(cus, cu_extvar_iterator, NULL, NULL);
|
|
|
|
twalk(tree, declaration_action__walk);
|
|
|
|
} else if (walk_fun) {
|
|
|
|
cus__for_each_cu(cus, cu_extfun_iterator, NULL, NULL);
|
|
|
|
twalk(tree, function_action__walk);
|
|
|
|
}
|
|
|
|
|
|
|
|
tdestroy(tree, free_node);
|
2009-03-11 16:31:17 +01:00
|
|
|
rc = EXIT_SUCCESS;
|
all: Fix possible uninitialized variable uses
I wasn't especifying the optimization level and the default, despite
using -Wall, was for this so simple case not to be warned about, so
now I'm using -O2.
Alexandre provided a patch initializing the variables to NULL, so that
when we called cus__delete it would bail out and not possibly act on
a random value, I preferred to add extra goto labels and do the exit
path only on the resources that were successfully allocated/initialized,
avoiding, for instance, to call dwarves_exit() if dwarves_init() wasn't
called, which wasn't a problem so far, but could be in the future.
Reported-by: Alexandre Vassalotti <alexandre@peadrop.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2009-05-04 20:50:06 +02:00
|
|
|
out_cus_delete:
|
2009-03-11 16:31:17 +01:00
|
|
|
cus__delete(cus);
|
all: Fix possible uninitialized variable uses
I wasn't especifying the optimization level and the default, despite
using -Wall, was for this so simple case not to be warned about, so
now I'm using -O2.
Alexandre provided a patch initializing the variables to NULL, so that
when we called cus__delete it would bail out and not possibly act on
a random value, I preferred to add extra goto labels and do the exit
path only on the resources that were successfully allocated/initialized,
avoiding, for instance, to call dwarves_exit() if dwarves_init() wasn't
called, which wasn't a problem so far, but could be in the future.
Reported-by: Alexandre Vassalotti <alexandre@peadrop.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2009-05-04 20:50:06 +02:00
|
|
|
out_dwarves_exit:
|
2009-03-11 16:31:17 +01:00
|
|
|
dwarves__exit();
|
all: Fix possible uninitialized variable uses
I wasn't especifying the optimization level and the default, despite
using -Wall, was for this so simple case not to be warned about, so
now I'm using -O2.
Alexandre provided a patch initializing the variables to NULL, so that
when we called cus__delete it would bail out and not possibly act on
a random value, I preferred to add extra goto labels and do the exit
path only on the resources that were successfully allocated/initialized,
avoiding, for instance, to call dwarves_exit() if dwarves_init() wasn't
called, which wasn't a problem so far, but could be in the future.
Reported-by: Alexandre Vassalotti <alexandre@peadrop.com>
Signed-off-by: Arnaldo Carvalho de Melo <acme@redhat.com>
2009-05-04 20:50:06 +02:00
|
|
|
out:
|
2009-03-11 16:31:17 +01:00
|
|
|
return rc;
|
2007-02-02 14:56:53 +01:00
|
|
|
}
|