|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
Copyright(C) 2016, Red Hat, Inc., Jerome Marchand
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
This program is free software: you can redistribute it and/or modify
|
|
Packit Service |
80a84b |
it under the terms of the GNU General Public License as published by
|
|
Packit Service |
80a84b |
the Free Software Foundation, either version 3 of the License, or
|
|
Packit Service |
80a84b |
(at your option) any later version.
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
This program is distributed in the hope that it will be useful,
|
|
Packit Service |
80a84b |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
80a84b |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
80a84b |
GNU General Public License for more details.
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
You should have received a copy of the GNU General Public License
|
|
Packit Service |
80a84b |
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Internal representation and manipulation of symbols
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#ifndef _GNU_SOURCE /* We use GNU basename() that doesn't modify the arg */
|
|
Packit Service |
80a84b |
#error "We need GNU version of basename()!"
|
|
Packit Service |
80a84b |
#endif
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#include <string.h>
|
|
Packit Service |
80a84b |
#include <stdio.h>
|
|
Packit Service |
80a84b |
#include <stdlib.h>
|
|
Packit Service |
80a84b |
#include <stdbool.h>
|
|
Packit Service |
80a84b |
#include <strings.h>
|
|
Packit Service |
80a84b |
#include <limits.h>
|
|
Packit Service |
80a84b |
#include <errno.h>
|
|
Packit Service |
80a84b |
#include <unistd.h>
|
|
Packit Service |
80a84b |
#include <getopt.h>
|
|
Packit Service |
80a84b |
#include <libgen.h>
|
|
Packit Service |
80a84b |
#include <sys/stat.h>
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#include "objects.h"
|
|
Packit Service |
80a84b |
#include "utils.h"
|
|
Packit Service |
80a84b |
#include "main.h"
|
|
Packit Service |
80a84b |
#include "record.h"
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* Indentation offset for c-style and tree debug outputs */
|
|
Packit Service |
80a84b |
#define C_INDENT_OFFSET 8
|
|
Packit Service |
80a84b |
#define DBG_INDENT_OFFSET 4
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
obj_list_t *obj_list_new(obj_t *obj)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_t *list = safe_zmalloc(sizeof(obj_list_t));
|
|
Packit Service |
80a84b |
list->member = obj;
|
|
Packit Service |
80a84b |
list->next = NULL;
|
|
Packit Service |
80a84b |
return list;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void obj_list_init(obj_list_head_t *head, obj_t *obj)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_t *list = obj_list_new(obj);
|
|
Packit Service |
80a84b |
head->first = head->last = list;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
obj_list_head_t *obj_list_head_new(obj_t *obj)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_head_t *h = safe_zmalloc(sizeof(obj_list_head_t));
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
obj_list_init(h, obj);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return h;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static bool obj_list_empty(obj_list_head_t *head)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
return head->first == NULL;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
void obj_list_add(obj_list_head_t *head, obj_t *obj)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_t *list;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (obj_list_empty(head)) {
|
|
Packit Service |
80a84b |
obj_list_init(head, obj);
|
|
Packit Service |
80a84b |
return;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
list = obj_list_new(obj);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (head->last->next)
|
|
Packit Service |
80a84b |
fprintf(stderr, "head->last is not the last\n");
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
head->last->next = list;
|
|
Packit Service |
80a84b |
head->last = list;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
obj_t *obj_new(obj_types type, char *name)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_t *new = safe_zmalloc(sizeof(obj_t));
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
new->type = type;
|
|
Packit Service |
80a84b |
new->name = global_string_get_move(name);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return new;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void _obj_free(obj_t *o, obj_t *skip);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void _obj_list_free(obj_list_head_t *l, obj_t *skip)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_t *list;
|
|
Packit Service |
80a84b |
obj_list_t *next;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (l == NULL)
|
|
Packit Service |
80a84b |
return;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
list = l->first;
|
|
Packit Service |
80a84b |
free(l);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
while (list) {
|
|
Packit Service |
80a84b |
_obj_free(list->member, skip);
|
|
Packit Service |
80a84b |
next = list->next;
|
|
Packit Service |
80a84b |
free(list);
|
|
Packit Service |
80a84b |
list = next;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void obj_list_free(obj_list_head_t *l)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
_obj_list_free(l, NULL);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Free the tree o, but keep the subtree skip.
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
static void _obj_free(obj_t *o, obj_t *skip)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (!o || (o == skip))
|
|
Packit Service |
80a84b |
return;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->type == __type_reffile && o->depend_rec_node) {
|
|
Packit Service |
80a84b |
list_del(o->depend_rec_node);
|
|
Packit Service |
80a84b |
o->depend_rec_node = NULL;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
_obj_list_free(o->member_list, skip);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->ptr)
|
|
Packit Service |
80a84b |
_obj_free(o->ptr, skip);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (is_weak(o))
|
|
Packit Service |
80a84b |
free(o->link);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
free(o);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Free the all object
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
void obj_free(obj_t *o)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
_obj_free(o, NULL);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#define _CREATE_NEW_FUNC(type, suffix) \
|
|
Packit Service |
80a84b |
obj_t *obj_##type##_##suffix(char *name) \
|
|
Packit Service |
80a84b |
{ \
|
|
Packit Service |
80a84b |
obj_t *new = obj_new(__type_##type, name); \
|
|
Packit Service |
80a84b |
return new; \
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
#define CREATE_NEW_FUNC(type) _CREATE_NEW_FUNC(type, new)
|
|
Packit Service |
80a84b |
#define CREATE_NEW_FUNC_NONAME(type) \
|
|
Packit Service |
80a84b |
_CREATE_NEW_FUNC(type, new_) \
|
|
Packit Service |
80a84b |
obj_t *obj_##type##_new() \
|
|
Packit Service |
80a84b |
{ \
|
|
Packit Service |
80a84b |
return obj_##type##_new_(NULL); \
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#define _CREATE_NEW_ADD_FUNC(type, infix) \
|
|
Packit Service |
80a84b |
obj_t *obj_##type##_##infix##_##add(char *name, obj_t *obj) \
|
|
Packit Service |
80a84b |
{ \
|
|
Packit Service |
80a84b |
obj_t *new = obj_new(__type_##type, name); \
|
|
Packit Service |
80a84b |
new->ptr = obj; \
|
|
Packit Service |
80a84b |
return new; \
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
#define CREATE_NEW_ADD_FUNC(type) _CREATE_NEW_ADD_FUNC(type, new)
|
|
Packit Service |
80a84b |
#define CREATE_NEW_ADD_FUNC_NONAME(type) \
|
|
Packit Service |
80a84b |
_CREATE_NEW_ADD_FUNC(type, new_) \
|
|
Packit Service |
80a84b |
obj_t *obj_##type##_new_add(obj_t *obj) \
|
|
Packit Service |
80a84b |
{ \
|
|
Packit Service |
80a84b |
return obj_##type##_new__add(NULL, obj); \
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
CREATE_NEW_FUNC(struct)
|
|
Packit Service |
80a84b |
CREATE_NEW_FUNC(union)
|
|
Packit Service |
80a84b |
CREATE_NEW_FUNC(enum)
|
|
Packit Service |
80a84b |
CREATE_NEW_FUNC(constant)
|
|
Packit Service |
80a84b |
CREATE_NEW_FUNC_NONAME(reffile)
|
|
Packit Service |
80a84b |
CREATE_NEW_ADD_FUNC(func)
|
|
Packit Service |
80a84b |
CREATE_NEW_ADD_FUNC(typedef)
|
|
Packit Service |
80a84b |
CREATE_NEW_ADD_FUNC(var)
|
|
Packit Service |
80a84b |
CREATE_NEW_ADD_FUNC(struct_member)
|
|
Packit Service |
80a84b |
CREATE_NEW_ADD_FUNC_NONAME(ptr)
|
|
Packit Service |
80a84b |
CREATE_NEW_ADD_FUNC_NONAME(array)
|
|
Packit Service |
80a84b |
CREATE_NEW_ADD_FUNC_NONAME(qualifier)
|
|
Packit Service |
80a84b |
CREATE_NEW_FUNC(assembly)
|
|
Packit Service |
80a84b |
CREATE_NEW_FUNC(weak)
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
obj_t *obj_basetype_new(char *base_type)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_t *new = obj_new(__type_base, NULL);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
new->base_type = global_string_get_move(base_type);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return new;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
const char *obj_type_name[NR_OBJ_TYPES+1] = {
|
|
Packit Service |
80a84b |
"reference file",
|
|
Packit Service |
80a84b |
"struct",
|
|
Packit Service |
80a84b |
"union",
|
|
Packit Service |
80a84b |
"enum",
|
|
Packit Service |
80a84b |
"func",
|
|
Packit Service |
80a84b |
"ptr",
|
|
Packit Service |
80a84b |
"typedef",
|
|
Packit Service |
80a84b |
"array",
|
|
Packit Service |
80a84b |
"var",
|
|
Packit Service |
80a84b |
"struct member",
|
|
Packit Service |
80a84b |
"type qualifier",
|
|
Packit Service |
80a84b |
"base",
|
|
Packit Service |
80a84b |
"constant",
|
|
Packit Service |
80a84b |
"assembly",
|
|
Packit Service |
80a84b |
"weak",
|
|
Packit Service |
80a84b |
"unknown type"
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static const char *typetostr(obj_t *o)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int t = o->type;
|
|
Packit Service |
80a84b |
if (t >= NR_OBJ_TYPES)
|
|
Packit Service |
80a84b |
t = NR_OBJ_TYPES;
|
|
Packit Service |
80a84b |
return obj_type_name[t];
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static int c_precedence(obj_t *o)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
switch (o->type) {
|
|
Packit Service |
80a84b |
case __type_func:
|
|
Packit Service |
80a84b |
case __type_array:
|
|
Packit Service |
80a84b |
return 1;
|
|
Packit Service |
80a84b |
case __type_ptr:
|
|
Packit Service |
80a84b |
return 2;
|
|
Packit Service |
80a84b |
default:
|
|
Packit Service |
80a84b |
return INT_MAX;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Returns whether parentheses are needed
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* Pointer have a higher precedence than function and array, so we need to put
|
|
Packit Service |
80a84b |
* parentheses around a pointer to a function of array.
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
static bool is_paren_needed(obj_t *node)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_t *child = node->ptr;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
while (child) {
|
|
Packit Service |
80a84b |
if (c_precedence(child) < c_precedence(node))
|
|
Packit Service |
80a84b |
return true;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
child = child->ptr;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static char *print_margin_offset(const char *prefix, const char *s, int depth)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
size_t len = snprintf(NULL, 0, "%-*s", depth * C_INDENT_OFFSET, s) + 1;
|
|
Packit Service |
80a84b |
char *ret;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (prefix)
|
|
Packit Service |
80a84b |
len += strlen(prefix);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (!len)
|
|
Packit Service |
80a84b |
return NULL;
|
|
Packit Service |
80a84b |
ret = safe_zmalloc(len);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
snprintf(ret, len, "%s%-*s",
|
|
Packit Service |
80a84b |
prefix ? prefix : "", depth * C_INDENT_OFFSET, s);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static char *print_margin(const char *prefix, int depth)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
return print_margin_offset(prefix, "", depth);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Return type for print_* functions
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* Because C mixes prefix and postfix operator, the code generation from a node
|
|
Packit Service |
80a84b |
* may need to add code before, after or in the middle of the code generated by
|
|
Packit Service |
80a84b |
* subtrees. Thus we sometimes need two return two strings.
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* Attention to the precedence and associativity sould be taken when
|
|
Packit Service |
80a84b |
* deciding where a specific string should be inserted
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
typedef struct {
|
|
Packit Service |
80a84b |
char *prefix;
|
|
Packit Service |
80a84b |
char *postfix;
|
|
Packit Service |
80a84b |
} pp_t;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void free_pp(pp_t pp)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
free(pp.prefix);
|
|
Packit Service |
80a84b |
free(pp.postfix);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t _print_tree(obj_t *o, int depth, bool newline, const char *prefix);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Add prefix p at the begining of string s (reallocated)
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* space: add a space between p and s
|
|
Packit Service |
80a84b |
* freep: free the string p
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
static char *_prefix_str(char **s, char *p, bool space, bool freep)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
size_t lenp = strlen(p), lens = 0, newlen;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (*s)
|
|
Packit Service |
80a84b |
lens = strlen(*s);
|
|
Packit Service |
80a84b |
newlen = lens + lenp + 1;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (space)
|
|
Packit Service |
80a84b |
newlen++;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
*s = safe_realloc(*s, newlen);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (lens)
|
|
Packit Service |
80a84b |
memmove(space ? *s+lenp+1 : *s+lenp, *s, lens + 1);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
(*s)[lenp] = '\0';
|
|
Packit Service |
80a84b |
memcpy(*s, p, lenp);
|
|
Packit Service |
80a84b |
if (space)
|
|
Packit Service |
80a84b |
(*s)[lenp] = ' ';
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (freep)
|
|
Packit Service |
80a84b |
free(p);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return *s;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static char *prefix_str(char **s, char *p)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (!p)
|
|
Packit Service |
80a84b |
return *s;
|
|
Packit Service |
80a84b |
return _prefix_str(s, p, false, false);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static char *prefix_str_free(char **s, char *p)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (!p)
|
|
Packit Service |
80a84b |
return *s;
|
|
Packit Service |
80a84b |
return _prefix_str(s, p, false, true);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static char *prefix_str_space(char **s, const char *p)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (!p)
|
|
Packit Service |
80a84b |
return *s;
|
|
Packit Service |
80a84b |
/* freep is false so we can pass const char * */
|
|
Packit Service |
80a84b |
return _prefix_str(s, (char *)p, true, false);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Add suffix p at the end of string s (realocated)
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* space: add a space between p and s
|
|
Packit Service |
80a84b |
* freep: free the string p
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
static char *_postfix_str(char **s, char *p, bool space, bool freep)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int lenp = strlen(p), lens = 0, newlen;
|
|
Packit Service |
80a84b |
if (*s)
|
|
Packit Service |
80a84b |
lens = strlen(*s);
|
|
Packit Service |
80a84b |
newlen = lens + lenp + 1;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (space)
|
|
Packit Service |
80a84b |
newlen++;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
*s = safe_realloc(*s, newlen);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (lens == 0)
|
|
Packit Service |
80a84b |
(*s)[0] = '\0';
|
|
Packit Service |
80a84b |
if (space)
|
|
Packit Service |
80a84b |
strcat(*s, " ");
|
|
Packit Service |
80a84b |
strcat(*s, p);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (freep)
|
|
Packit Service |
80a84b |
free(p);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return *s;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static char *postfix_str(char **s, const char *p)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (!p)
|
|
Packit Service |
80a84b |
return *s;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* freep is false so we can pass const char * */
|
|
Packit Service |
80a84b |
return _postfix_str(s, (char *)p, false, false);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static char *postfix_str_free(char **s, char *p)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (!p)
|
|
Packit Service |
80a84b |
return *s;
|
|
Packit Service |
80a84b |
return _postfix_str(s, p, false, true);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_base(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret = {NULL, NULL};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
safe_asprintf(&ret.prefix, "%s ", o->base_type);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_constant(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret = {NULL, NULL};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
safe_asprintf(&ret.prefix, "%s = %li", o->name, (long)o->constant);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_reffile(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret = {NULL, NULL};
|
|
Packit Service |
80a84b |
char *s = filenametotype(o->base_type);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
s = safe_realloc(s, strlen(s) + 2);
|
|
Packit Service |
80a84b |
strcat(s, " ");
|
|
Packit Service |
80a84b |
ret.prefix = s;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* Print a struct, enum or an union */
|
|
Packit Service |
80a84b |
static pp_t print_structlike(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret = {NULL, NULL}, tmp;
|
|
Packit Service |
80a84b |
obj_list_t *list = NULL;
|
|
Packit Service |
80a84b |
char *s, *margin;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->name)
|
|
Packit Service |
80a84b |
safe_asprintf(&s, "%s %s {\n", typetostr(o), o->name);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
safe_asprintf(&s, "%s {\n", typetostr(o));
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->member_list)
|
|
Packit Service |
80a84b |
list = o->member_list->first;
|
|
Packit Service |
80a84b |
while (list) {
|
|
Packit Service |
80a84b |
tmp = _print_tree(list->member, depth+1, true, prefix);
|
|
Packit Service |
80a84b |
postfix_str_free(&s, tmp.prefix);
|
|
Packit Service |
80a84b |
postfix_str_free(&s, tmp.postfix);
|
|
Packit Service |
80a84b |
postfix_str(&s, o->type == __type_enum ? ",\n" : ";\n");
|
|
Packit Service |
80a84b |
list = list->next;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
margin = print_margin(prefix, depth);
|
|
Packit Service |
80a84b |
postfix_str_free(&s, margin);
|
|
Packit Service |
80a84b |
postfix_str(&s, "}");
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
ret.prefix = s;
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_func(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret = {NULL, NULL}, return_type;
|
|
Packit Service |
80a84b |
obj_list_t *list = NULL;
|
|
Packit Service |
80a84b |
obj_t *next = o->ptr;
|
|
Packit Service |
80a84b |
char *s, *margin;
|
|
Packit Service |
80a84b |
const char *name;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return_type = _print_tree(next, depth, false, prefix);
|
|
Packit Service |
80a84b |
ret.prefix = return_type.prefix;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->name)
|
|
Packit Service |
80a84b |
name = o->name;
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
name = "";
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
safe_asprintf(&s, "%s(\n", name);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->member_list)
|
|
Packit Service |
80a84b |
list = o->member_list->first;
|
|
Packit Service |
80a84b |
while (list) {
|
|
Packit Service |
80a84b |
pp_t arg = _print_tree(list->member, depth+1, true, prefix);
|
|
Packit Service |
80a84b |
postfix_str_free(&s, arg.prefix);
|
|
Packit Service |
80a84b |
postfix_str_free(&s, arg.postfix);
|
|
Packit Service |
80a84b |
list = list->next;
|
|
Packit Service |
80a84b |
postfix_str(&s, list ? ",\n" : "\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
margin = print_margin(prefix, depth);
|
|
Packit Service |
80a84b |
postfix_str_free(&s, margin);
|
|
Packit Service |
80a84b |
postfix_str(&s, ")");
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
ret.postfix = s;
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_array(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret;
|
|
Packit Service |
80a84b |
char *s;
|
|
Packit Service |
80a84b |
obj_t *next = o->ptr;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
ret = _print_tree(next, depth, false, prefix);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
safe_asprintf(&s, "[%lu]", o->constant);
|
|
Packit Service |
80a84b |
prefix_str_free(&ret.postfix, s);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_ptr(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret;
|
|
Packit Service |
80a84b |
bool need_paren = is_paren_needed(o);
|
|
Packit Service |
80a84b |
obj_t *next = o->ptr;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
ret = _print_tree(next, depth, false, prefix);
|
|
Packit Service |
80a84b |
if (need_paren) {
|
|
Packit Service |
80a84b |
postfix_str(&ret.prefix, "(*");
|
|
Packit Service |
80a84b |
prefix_str(&ret.postfix, ")");
|
|
Packit Service |
80a84b |
} else
|
|
Packit Service |
80a84b |
postfix_str(&ret.prefix, "*");
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* Print a var or a struct_member */
|
|
Packit Service |
80a84b |
static pp_t print_varlike(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret;
|
|
Packit Service |
80a84b |
char *s = NULL;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (is_bitfield(o))
|
|
Packit Service |
80a84b |
safe_asprintf(&s, "%s:%i",
|
|
Packit Service |
80a84b |
o->name, o->last_bit - o->first_bit + 1);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
s = (char *)o->name;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
ret = _print_tree(o->ptr, depth, false, prefix);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (s)
|
|
Packit Service |
80a84b |
postfix_str(&ret.prefix, s);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (is_bitfield(o))
|
|
Packit Service |
80a84b |
free(s);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_typedef(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
ret = _print_tree(o->ptr, depth, false, prefix);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
prefix_str(&ret.prefix, "typedef ");
|
|
Packit Service |
80a84b |
postfix_str(&ret.prefix, o->name);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_qualifier(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
ret = _print_tree(o->ptr, depth, false, prefix);
|
|
Packit Service |
80a84b |
prefix_str_space(&ret.prefix, o->base_type);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_assembly(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret = {NULL, NULL};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
prefix_str(&ret.prefix, "assembly ");
|
|
Packit Service |
80a84b |
postfix_str(&ret.prefix, o->name);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static pp_t print_weak(obj_t *o, int depth, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret = {NULL, NULL};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
prefix_str(&ret.prefix, "weak ");
|
|
Packit Service |
80a84b |
postfix_str(&ret.prefix, o->name);
|
|
Packit Service |
80a84b |
postfix_str(&ret.prefix, " -> ");
|
|
Packit Service |
80a84b |
postfix_str(&ret.prefix, o->link);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
#define BASIC_CASE(type) \
|
|
Packit Service |
80a84b |
case __type_##type: \
|
|
Packit Service |
80a84b |
ret = print_##type(o, depth, prefix); \
|
|
Packit Service |
80a84b |
break;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
struct dopt display_options;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Display an object in a c-like format
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* o: object to be displayed
|
|
Packit Service |
80a84b |
* depth: current indentation depth
|
|
Packit Service |
80a84b |
* newline: is this the begining of a new line?
|
|
Packit Service |
80a84b |
* prefix: prefix to be printed at the begining of each line
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
static pp_t _print_tree(obj_t *o, int depth, bool newline, const char *prefix)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t ret = {NULL, NULL};
|
|
Packit Service |
80a84b |
char *margin;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* silence coverity on write-only variable */
|
|
Packit Service |
80a84b |
(void)ret;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (!o)
|
|
Packit Service |
80a84b |
fail("NULL pointer in _print_tree\n");
|
|
Packit Service |
80a84b |
debug("_print_tree(): %s\n", typetostr(o));
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
switch (o->type) {
|
|
Packit Service |
80a84b |
BASIC_CASE(reffile);
|
|
Packit Service |
80a84b |
BASIC_CASE(constant);
|
|
Packit Service |
80a84b |
BASIC_CASE(base);
|
|
Packit Service |
80a84b |
BASIC_CASE(typedef);
|
|
Packit Service |
80a84b |
BASIC_CASE(qualifier);
|
|
Packit Service |
80a84b |
BASIC_CASE(func);
|
|
Packit Service |
80a84b |
BASIC_CASE(array);
|
|
Packit Service |
80a84b |
BASIC_CASE(ptr);
|
|
Packit Service |
80a84b |
BASIC_CASE(assembly);
|
|
Packit Service |
80a84b |
BASIC_CASE(weak);
|
|
Packit Service |
80a84b |
case __type_var:
|
|
Packit Service |
80a84b |
case __type_struct_member:
|
|
Packit Service |
80a84b |
ret = print_varlike(o, depth, prefix);
|
|
Packit Service |
80a84b |
break;
|
|
Packit Service |
80a84b |
case __type_struct:
|
|
Packit Service |
80a84b |
case __type_union:
|
|
Packit Service |
80a84b |
case __type_enum:
|
|
Packit Service |
80a84b |
ret = print_structlike(o, depth, prefix);
|
|
Packit Service |
80a84b |
break;
|
|
Packit Service |
80a84b |
default:
|
|
Packit Service |
80a84b |
fail("WIP: doesn't handle %s\n", typetostr(o));
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (!newline)
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->type == __type_struct_member && !display_options.no_offset) {
|
|
Packit Service |
80a84b |
char *offstr;
|
|
Packit Service |
80a84b |
if (is_bitfield(o))
|
|
Packit Service |
80a84b |
safe_asprintf(&offstr, "0x%lx:%2i-%-2i ",
|
|
Packit Service |
80a84b |
o->offset, o->first_bit, o->last_bit);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
safe_asprintf(&offstr, "0x%lx ", o->offset);
|
|
Packit Service |
80a84b |
margin = print_margin_offset(prefix, offstr, depth);
|
|
Packit Service |
80a84b |
free(offstr);
|
|
Packit Service |
80a84b |
} else
|
|
Packit Service |
80a84b |
margin = print_margin(prefix, depth);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
prefix_str_free(&ret.prefix, margin);
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
void obj_print_tree__prefix(obj_t *root, const char *prefix, FILE *stream)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
pp_t s = _print_tree(root, 0, true, prefix);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
fprintf(stream, "%s%s;\n",
|
|
Packit Service |
80a84b |
s.prefix ? s.prefix : "",
|
|
Packit Service |
80a84b |
s.postfix ? s.postfix : "");
|
|
Packit Service |
80a84b |
free_pp(s);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
void obj_print_tree(obj_t *root)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_print_tree__prefix(root, NULL, stdout);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void fill_parent_rec(obj_t *o, obj_t *parent)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_t *list = NULL;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
o->parent = parent;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->member_list)
|
|
Packit Service |
80a84b |
list = o->member_list->first;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
while (list) {
|
|
Packit Service |
80a84b |
fill_parent_rec(list->member, o);
|
|
Packit Service |
80a84b |
list = list->next;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->ptr)
|
|
Packit Service |
80a84b |
fill_parent_rec(o->ptr, o);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Walk the tree and fill all the parents field
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
void obj_fill_parent(obj_t *root)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fill_parent_rec(root, NULL);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static int walk_list(obj_list_t *list, cb_t cb_pre, cb_t cb_in, cb_t cb_post,
|
|
Packit Service |
80a84b |
void *args, bool ptr_first)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int ret = CB_CONT;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
while (list) {
|
|
Packit Service |
80a84b |
ret = obj_walk_tree3(list->member, cb_pre, cb_in, cb_post,
|
|
Packit Service |
80a84b |
args, ptr_first);
|
|
Packit Service |
80a84b |
if (ret == CB_FAIL)
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
ret = CB_CONT;
|
|
Packit Service |
80a84b |
list = list->next;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static int walk_ptr(obj_t *o, cb_t cb_pre, cb_t cb_in, cb_t cb_post,
|
|
Packit Service |
80a84b |
void *args, bool ptr_first)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int ret = CB_CONT;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->ptr) {
|
|
Packit Service |
80a84b |
ret = obj_walk_tree3(o->ptr, cb_pre, cb_in, cb_post,
|
|
Packit Service |
80a84b |
args, ptr_first);
|
|
Packit Service |
80a84b |
if (ret == CB_FAIL)
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
ret = CB_CONT;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Tree walk with prefix, infix and postfix callbacks
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* o: walked tree
|
|
Packit Service |
80a84b |
* cb_pre: callback function called before walking the subtrees
|
|
Packit Service |
80a84b |
* cb_in: callback function called between walking the subtrees
|
|
Packit Service |
80a84b |
* cp_post: callback function called between walking the subtrees
|
|
Packit Service |
80a84b |
* args: argument passed to the callbacks
|
|
Packit Service |
80a84b |
* ptr_first: whether we walk member_list of ptr first
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
int obj_walk_tree3(obj_t *o, cb_t cb_pre, cb_t cb_in, cb_t cb_post,
|
|
Packit Service |
80a84b |
void *args, bool ptr_first)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_t *list = NULL;
|
|
Packit Service |
80a84b |
int ret = CB_CONT;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (cb_pre) {
|
|
Packit Service |
80a84b |
ret = cb_pre(o, args);
|
|
Packit Service |
80a84b |
if (ret)
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->member_list)
|
|
Packit Service |
80a84b |
list = o->member_list->first;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (ptr_first)
|
|
Packit Service |
80a84b |
ret = walk_ptr(o, cb_pre, cb_in, cb_post, args, ptr_first);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
ret = walk_list(list, cb_pre, cb_in, cb_post, args, ptr_first);
|
|
Packit Service |
80a84b |
if (ret == CB_FAIL)
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (cb_in) {
|
|
Packit Service |
80a84b |
ret = cb_in(o, args);
|
|
Packit Service |
80a84b |
if (ret)
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (ptr_first)
|
|
Packit Service |
80a84b |
ret = walk_list(list, cb_pre, cb_in, cb_post, args, ptr_first);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
ret = walk_ptr(o, cb_pre, cb_in, cb_post, args, ptr_first);
|
|
Packit Service |
80a84b |
if (ret == CB_FAIL)
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (cb_post) {
|
|
Packit Service |
80a84b |
ret = cb_post(o, args);
|
|
Packit Service |
80a84b |
if (ret)
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return ret;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Simple tree walk with a prefix callback
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* It walks the member_list subtree first.
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
int obj_walk_tree(obj_t *root, cb_t cb, void *args)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
return obj_walk_tree3(root, cb, NULL, NULL, args, false);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void _show_node(FILE *f, obj_t *o, int margin)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (o)
|
|
Packit Service |
80a84b |
fprintf(f,
|
|
Packit Service |
80a84b |
"\%*s<%s, \"%s\", \"%s\", %p, %p, %p, %lu, %i, %i>\n",
|
|
Packit Service |
80a84b |
margin, "", typetostr(o), o->name, o->base_type,
|
|
Packit Service |
80a84b |
o, o->parent, o->ptr,
|
|
Packit Service |
80a84b |
o->offset, o->first_bit, o->last_bit);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
fprintf(f, "\%*s<(nil)>\n", margin, "");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void show_node(obj_t *o, int margin)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
_show_node(stdout, o, margin);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static int debug_node(obj_t *node, void *args)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int *depth = (int *) args;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
show_node(node, *depth * DBG_INDENT_OFFSET);
|
|
Packit Service |
80a84b |
(*depth)++;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return CB_CONT;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static int dec_depth(obj_t *node, void *args)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int *depth = (int *) args;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
(*depth)--;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return CB_CONT;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Print a raw representation of the internal object tree
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
int obj_debug_tree(obj_t *root)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int depth = 0;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return obj_walk_tree3(root, debug_node, NULL, dec_depth, &depth, false);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* Hide some RH_KABI magic
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* WARNING: this code is ugly and full of add-hoc hacks, but I'm
|
|
Packit Service |
80a84b |
* afraid it can't be fixed. It has to follow the internals of
|
|
Packit Service |
80a84b |
* RH_KABI_* macros. Also, it may have to change if RH_KABI_*
|
|
Packit Service |
80a84b |
* functions change in the future.
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* RH_KABI_REPLACE the old field by a complex construction of union
|
|
Packit Service |
80a84b |
* and struct used to check that the new field didn't change the
|
|
Packit Service |
80a84b |
* alignement. It is of the form:
|
|
Packit Service |
80a84b |
* union {
|
|
Packit Service |
80a84b |
* _new;
|
|
Packit Service |
80a84b |
* struct {
|
|
Packit Service |
80a84b |
* _orig;
|
|
Packit Service |
80a84b |
* } __UNIQUE_ID_rh_kabi_hideXX
|
|
Packit Service |
80a84b |
* union {};
|
|
Packit Service |
80a84b |
* }
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* RH_KABI_USE2(_P) replace a single field by two field that fits in
|
|
Packit Service |
80a84b |
* the same space. It puts the two new field into an unnamed
|
|
Packit Service |
80a84b |
* struct. We don't hide that as we have no way to know if that struct
|
|
Packit Service |
80a84b |
* is an artifact from RH_KABI_USE2 or was added deliberately.
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* RH_KABI_DEPRECATE(_FN) prefix the field name with
|
|
Packit Service |
80a84b |
* rh_reserved_. This is not the most specific string. It currently
|
|
Packit Service |
80a84b |
* appears in a few places that deprecates the field by hand, in which
|
|
Packit Service |
80a84b |
* it's OK to hide it too, but for some reason in
|
|
Packit Service |
80a84b |
* block_device_operations the reserved fields are of the form "void
|
|
Packit Service |
80a84b |
* *rh_reserved_ptrsX" instead of the usual "unsigned long
|
|
Packit Service |
80a84b |
* rh_reservedX". Treat this case as an exception.
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* Most RH_KABI_* functions, don't add any recognizable code so we
|
|
Packit Service |
80a84b |
* can't hide them here.
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
static int hide_kabi_cb(obj_t *o, void *args)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_t *kabi_struct, *new, *old, *parent = o->parent, *keeper;
|
|
Packit Service |
80a84b |
obj_list_head_t *lh;
|
|
Packit Service |
80a84b |
obj_list_t *l;
|
|
Packit Service |
80a84b |
bool show_new_field = (bool) args;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->name) {
|
|
Packit Service |
80a84b |
if (!strncmp(o->name, RH_KABI_HIDE, RH_KABI_HIDE_LEN))
|
|
Packit Service |
80a84b |
fail("Missed a kabi unique ID\n");
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* Hide RH_KABI_DEPRECATE* */
|
|
Packit Service |
80a84b |
if (!strncmp(o->name, "rh_reserved_", 12) &&
|
|
Packit Service |
80a84b |
strncmp(o->name, "rh_reserved_ptrs", 16)) {
|
|
Packit Service |
80a84b |
char *tmp = strdup(o->name+12);
|
|
Packit Service |
80a84b |
o->name = global_string_get_move(tmp);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* Hide RH_KABI_REPLACE */
|
|
Packit Service |
80a84b |
if ((o->type != __type_union) || o->name ||
|
|
Packit Service |
80a84b |
!(lh = o->member_list) || obj_list_empty(lh) ||
|
|
Packit Service |
80a84b |
!(l = lh->first) || !(new = l->member) ||
|
|
Packit Service |
80a84b |
!(l = l->next) || !(kabi_struct = l->member) ||
|
|
Packit Service |
80a84b |
(kabi_struct->type != __type_var) ||
|
|
Packit Service |
80a84b |
!kabi_struct->name ||
|
|
Packit Service |
80a84b |
strncmp(kabi_struct->name, RH_KABI_HIDE, RH_KABI_HIDE_LEN))
|
|
Packit Service |
80a84b |
return CB_CONT;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (!kabi_struct->ptr || kabi_struct->ptr->type != __type_struct ||
|
|
Packit Service |
80a84b |
!(lh = kabi_struct->ptr->member_list) || obj_list_empty(lh) ||
|
|
Packit Service |
80a84b |
!(l = lh->first) || !(old = l->member))
|
|
Packit Service |
80a84b |
fail("Unexpeted rh_kabi_hide struct format\n");
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* It is a rh_kabi_hide union
|
|
Packit Service |
80a84b |
* old is the first member of kabi_struct
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* Need to replace that:
|
|
Packit Service |
80a84b |
* <struct member, "(null)", "(null)", 0x1ea9840 16 0 0> (parent)
|
|
Packit Service |
80a84b |
* <union, "(null)", "(null)", (nil) 0 0 0> (o)
|
|
Packit Service |
80a84b |
* <var, "new_field", "(null)", 0x1ea9540 0 0 0> (new)
|
|
Packit Service |
80a84b |
* <base, "(null)", "int", (nil) 0 0 0>
|
|
Packit Service |
80a84b |
* <var, "__UNIQUE_ID_rh_kabi_hide55", "(null)", 0x1ea9700 0 0 0>
|
|
Packit Service |
80a84b |
* <struct, "(null)", "(null)", (nil) 0 0 0>
|
|
Packit Service |
80a84b |
* <struct member, "old_field", "(null)", 0x1ea9640 0 0 0>
|
|
Packit Service |
80a84b |
* <base, "(null)", "int", (nil) 0 0 0> ^(old)
|
|
Packit Service |
80a84b |
* <var, "(null)", "(null)", 0x1ea97a0 0 0 0>
|
|
Packit Service |
80a84b |
* <union, "(null)", "(null)", (nil) 0 0 0>
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* by that:
|
|
Packit Service |
80a84b |
* <struct member, "new_field", "(null)", 0x1ea9540 16 0 0>
|
|
Packit Service |
80a84b |
* <base, "(null)", "int", (nil) 0 0 0>
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* or that:
|
|
Packit Service |
80a84b |
* <struct member, "old_field", "(null)", 0x1ea9640 0 0 0>
|
|
Packit Service |
80a84b |
* <base, "(null)", "int", (nil) 0 0 0>
|
|
Packit Service |
80a84b |
*
|
|
Packit Service |
80a84b |
* Parent is always an unary node, struct_member or var
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (!parent ||
|
|
Packit Service |
80a84b |
!((parent->type == __type_var) ||
|
|
Packit Service |
80a84b |
(parent->type == __type_struct_member)) ||
|
|
Packit Service |
80a84b |
(parent->ptr != o) || parent->name) {
|
|
Packit Service |
80a84b |
_show_node(stderr, parent, 0);
|
|
Packit Service |
80a84b |
fail("Unexpected parent\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
if (new->type != __type_var) {
|
|
Packit Service |
80a84b |
_show_node(stderr, new, 0);
|
|
Packit Service |
80a84b |
fail("Unexpected new field\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
if (old->type != __type_struct_member) {
|
|
Packit Service |
80a84b |
_show_node(stderr, old, 0);
|
|
Packit Service |
80a84b |
fail("Unexpected old field\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
keeper = show_new_field ? new : old;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
parent->name = keeper->name;
|
|
Packit Service |
80a84b |
parent->ptr = keeper->ptr;
|
|
Packit Service |
80a84b |
parent->ptr->parent = parent;
|
|
Packit Service |
80a84b |
_obj_free(o, keeper);
|
|
Packit Service |
80a84b |
free(keeper);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return CB_SKIP;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
int obj_hide_kabi(obj_t *root, bool show_new_field)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
return obj_walk_tree(root, hide_kabi_cb, (void *)show_new_field);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static bool obj_is_declaration(obj_t *obj)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (obj->type != __type_reffile || obj->ref_record == NULL)
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return record_is_declaration(obj->ref_record);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static bool obj_is_kabi_hide(obj_t *obj)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (obj->name == NULL)
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return strncmp(obj->name, RH_KABI_HIDE, RH_KABI_HIDE_LEN) == 0;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
bool obj_eq(obj_t *o1, obj_t *o2, bool ignore_versions)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (o1->type != o2->type)
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1->type == __type_reffile) {
|
|
Packit Service |
80a84b |
if (ignore_versions) {
|
|
Packit Service |
80a84b |
return record_get_key(o1->ref_record) ==
|
|
Packit Service |
80a84b |
record_get_key(o2->ref_record);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return o1->ref_record == o2->ref_record;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* borrow parts from cmp_nodes */
|
|
Packit Service |
80a84b |
if ((o1->name != o2->name) ||
|
|
Packit Service |
80a84b |
((o1->ptr == NULL) != (o2->ptr == NULL)) ||
|
|
Packit Service |
80a84b |
(has_constant(o1) && (o1->constant != o2->constant)) ||
|
|
Packit Service |
80a84b |
(has_index(o1) && (o1->index != o2->index)) ||
|
|
Packit Service |
80a84b |
(is_bitfield(o1) != is_bitfield(o2)) ||
|
|
Packit Service |
80a84b |
(o1->alignment != o2->alignment) ||
|
|
Packit Service |
80a84b |
(o1->byte_size != o2->byte_size))
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* just compare bitfields */
|
|
Packit Service |
80a84b |
if (is_bitfield(o1) &&
|
|
Packit Service |
80a84b |
((o1->last_bit != o2->last_bit) ||
|
|
Packit Service |
80a84b |
(o1->first_bit != o2->first_bit)))
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if ((o1->member_list == NULL) !=
|
|
Packit Service |
80a84b |
(o2->member_list == NULL))
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1->base_type != o2->base_type)
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return true;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static obj_t *obj_copy(obj_t *o1)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_t *o;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
o = safe_zmalloc(sizeof(*o));
|
|
Packit Service |
80a84b |
*o = *o1;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
o->ptr = NULL;
|
|
Packit Service |
80a84b |
o->member_list = NULL;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1->type == __type_reffile && o1->depend_rec_node)
|
|
Packit Service |
80a84b |
o->depend_rec_node = list_node_add(o1->depend_rec_node, o);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return o;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
obj_t *obj_merge(obj_t *o1, obj_t *o2, unsigned int flags);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static obj_list_head_t *obj_members_merge(obj_list_head_t *list1,
|
|
Packit Service |
80a84b |
obj_list_head_t *list2,
|
|
Packit Service |
80a84b |
unsigned int flags)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_head_t *res = NULL;
|
|
Packit Service |
80a84b |
obj_list_t *l1;
|
|
Packit Service |
80a84b |
obj_list_t *l2;
|
|
Packit Service |
80a84b |
obj_t *o;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (list1 == NULL || list2 == NULL)
|
|
Packit Service |
80a84b |
return NULL;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
l1 = list1->first;
|
|
Packit Service |
80a84b |
l2 = list2->first;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
while (l1 && l2) {
|
|
Packit Service |
80a84b |
o = obj_merge(l1->member, l2->member, flags);
|
|
Packit Service |
80a84b |
if (o == NULL)
|
|
Packit Service |
80a84b |
goto cleanup;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (res == NULL)
|
|
Packit Service |
80a84b |
res = obj_list_head_new(o);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
obj_list_add(res, o);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
l1 = l1->next;
|
|
Packit Service |
80a84b |
l2 = l2->next;
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (l1 || l2)
|
|
Packit Service |
80a84b |
goto cleanup;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return res;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
cleanup:
|
|
Packit Service |
80a84b |
obj_list_free(res);
|
|
Packit Service |
80a84b |
return NULL;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static inline bool obj_can_merge_two_lines(obj_t *o1, obj_t *o2,
|
|
Packit Service |
80a84b |
unsigned int flags)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* We cannot merge two lines if:
|
|
Packit Service |
80a84b |
* - their states of being declarations are not equivalent,
|
|
Packit Service |
80a84b |
* and we require them to be
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
if (flags & MERGE_FLAG_DECL_EQ &&
|
|
Packit Service |
80a84b |
(obj_is_declaration(o1) != obj_is_declaration(o2)))
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/*
|
|
Packit Service |
80a84b |
* We can merge the two lines if:
|
|
Packit Service |
80a84b |
* - they are the same, or
|
|
Packit Service |
80a84b |
* - they are both RH_KABI_HIDE, or
|
|
Packit Service |
80a84b |
* - at least one of them is a declaration,
|
|
Packit Service |
80a84b |
* and we can merge declarations
|
|
Packit Service |
80a84b |
*/
|
|
Packit Service |
80a84b |
if (obj_eq(o1, o2, flags & MERGE_FLAG_VER_IGNORE))
|
|
Packit Service |
80a84b |
return true;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (obj_is_kabi_hide(o1) && obj_is_kabi_hide(o2))
|
|
Packit Service |
80a84b |
return true;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (flags & MERGE_FLAG_DECL_MERGE &&
|
|
Packit Service |
80a84b |
(obj_is_declaration(o1) || obj_is_declaration(o2)))
|
|
Packit Service |
80a84b |
return true;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
obj_t *obj_merge(obj_t *o1, obj_t *o2, unsigned int flags)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_t *merged_ptr;
|
|
Packit Service |
80a84b |
obj_list_head_t *merged_members;
|
|
Packit Service |
80a84b |
obj_t *res = NULL;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1 == NULL || o2 == NULL)
|
|
Packit Service |
80a84b |
return NULL;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (!obj_can_merge_two_lines(o1, o2, flags))
|
|
Packit Service |
80a84b |
goto no_merge;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
merged_ptr = obj_merge(o1->ptr, o2->ptr, flags);
|
|
Packit Service |
80a84b |
if (o1->ptr && !merged_ptr)
|
|
Packit Service |
80a84b |
goto no_merge_ptr;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
merged_members = obj_members_merge(o1->member_list,
|
|
Packit Service |
80a84b |
o2->member_list,
|
|
Packit Service |
80a84b |
flags);
|
|
Packit Service |
80a84b |
if (o1->member_list && !merged_members)
|
|
Packit Service |
80a84b |
goto no_merge_members;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (obj_is_declaration(o1))
|
|
Packit Service |
80a84b |
res = obj_copy(o2);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
res = obj_copy(o1);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
res->ptr = merged_ptr;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (merged_members != NULL)
|
|
Packit Service |
80a84b |
merged_members->object = res;
|
|
Packit Service |
80a84b |
res->member_list = merged_members;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return res;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
no_merge_members:
|
|
Packit Service |
80a84b |
obj_list_free(merged_members);
|
|
Packit Service |
80a84b |
no_merge_ptr:
|
|
Packit Service |
80a84b |
obj_free(merged_ptr);
|
|
Packit Service |
80a84b |
no_merge:
|
|
Packit Service |
80a84b |
return NULL;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_reffile(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
int version = record_get_version(o->ref_record);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
fprintf(f, "@\"%s", record_get_key(o->ref_record));
|
|
Packit Service |
80a84b |
if (version > 0)
|
|
Packit Service |
80a84b |
fprintf(f, "-%i", version);
|
|
Packit Service |
80a84b |
fprintf(f, ".txt\"\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void _dump_members(obj_t *o, FILE *f, void (*dumper)(obj_t *, FILE *))
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
obj_list_head_t *l = o->member_list;
|
|
Packit Service |
80a84b |
obj_list_t *list;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (l == NULL)
|
|
Packit Service |
80a84b |
return;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
list = l->first;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
while (list) {
|
|
Packit Service |
80a84b |
dumper(list->member, f);
|
|
Packit Service |
80a84b |
list = list->next;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_arg(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "%s ", o->name);
|
|
Packit Service |
80a84b |
obj_dump(o->ptr, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_members(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
_dump_members(o, f, obj_dump);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_args(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
_dump_members(o, f, dump_arg);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_struct(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "struct %s {\n", o->name);
|
|
Packit Service |
80a84b |
dump_members(o, f);
|
|
Packit Service |
80a84b |
fprintf(f, "}\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
static void dump_union(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "union %s {\n", o->name);
|
|
Packit Service |
80a84b |
dump_args(o, f);
|
|
Packit Service |
80a84b |
fprintf(f, "}\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_enum(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "enum %s {\n", o->name);
|
|
Packit Service |
80a84b |
dump_members(o, f);
|
|
Packit Service |
80a84b |
fprintf(f, "}\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_func(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "func %s (\n", o->name);
|
|
Packit Service |
80a84b |
dump_args(o, f);
|
|
Packit Service |
80a84b |
fprintf(f, ")\n");
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
obj_dump(o->ptr, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_ptr(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "* ");
|
|
Packit Service |
80a84b |
obj_dump(o->ptr, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_typedef(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "typedef %s\n", o->name);
|
|
Packit Service |
80a84b |
obj_dump(o->ptr, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_array(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "[%lu]", o->index);
|
|
Packit Service |
80a84b |
obj_dump(o->ptr, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_var(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "var %s ", o->name);
|
|
Packit Service |
80a84b |
obj_dump(o->ptr, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_struct_member(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "0x%lx", o->offset);
|
|
Packit Service |
80a84b |
if (o->is_bitfield)
|
|
Packit Service |
80a84b |
fprintf(f, ":%d-%d", o->first_bit, o->last_bit);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->alignment != 0)
|
|
Packit Service |
80a84b |
fprintf(f, " %u", o->alignment);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
fprintf(f, " %s ", o->name);
|
|
Packit Service |
80a84b |
obj_dump(o->ptr, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_qualifier(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "%s ", o->base_type);
|
|
Packit Service |
80a84b |
obj_dump(o->ptr, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_base(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
const char *type = o->base_type;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
/* variable args (...) is a special base case */
|
|
Packit Service |
80a84b |
if (type[0] == '.')
|
|
Packit Service |
80a84b |
fprintf(f, "%s\n", o->base_type);
|
|
Packit Service |
80a84b |
else
|
|
Packit Service |
80a84b |
fprintf(f, "\"%s\"\n", o->base_type);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_constant(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fprintf(f, "%s = 0x%lx\n", o->name, o->constant);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static void dump_fail(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
fail("Dump call for this type unsupported!\n");
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
struct dumper {
|
|
Packit Service |
80a84b |
void (*dumper)(obj_t *o, FILE *f);
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
static struct dumper dumpers[] = {
|
|
Packit Service |
80a84b |
[__type_reffile].dumper = dump_reffile,
|
|
Packit Service |
80a84b |
[__type_struct].dumper = dump_struct,
|
|
Packit Service |
80a84b |
[__type_union].dumper = dump_union,
|
|
Packit Service |
80a84b |
[__type_enum].dumper = dump_enum,
|
|
Packit Service |
80a84b |
[__type_func].dumper = dump_func,
|
|
Packit Service |
80a84b |
[__type_ptr].dumper = dump_ptr,
|
|
Packit Service |
80a84b |
[__type_typedef].dumper = dump_typedef,
|
|
Packit Service |
80a84b |
[__type_array].dumper = dump_array,
|
|
Packit Service |
80a84b |
[__type_var].dumper = dump_var,
|
|
Packit Service |
80a84b |
[__type_struct_member].dumper = dump_struct_member,
|
|
Packit Service |
80a84b |
[__type_qualifier].dumper = dump_qualifier,
|
|
Packit Service |
80a84b |
[__type_base].dumper = dump_base,
|
|
Packit Service |
80a84b |
[__type_constant].dumper = dump_constant,
|
|
Packit Service |
80a84b |
[__type_assembly].dumper = dump_fail,
|
|
Packit Service |
80a84b |
[__type_weak].dumper = dump_fail,
|
|
Packit Service |
80a84b |
};
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
void obj_dump(obj_t *o, FILE *f)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
if (o == NULL)
|
|
Packit Service |
80a84b |
return;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o->type >= NR_OBJ_TYPES)
|
|
Packit Service |
80a84b |
fail("Wrong object type %d", o->type);
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
dumpers[o->type].dumper(o, f);
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
bool obj_same_declarations(obj_t *o1, obj_t *o2,
|
|
Packit Service |
80a84b |
struct set *processed)
|
|
Packit Service |
80a84b |
{
|
|
Packit Service |
80a84b |
const int ignore_versions = true;
|
|
Packit Service |
80a84b |
obj_list_t *list1;
|
|
Packit Service |
80a84b |
obj_list_t *list2;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1 == o2)
|
|
Packit Service |
80a84b |
return true;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (!obj_eq(o1, o2, ignore_versions))
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1->type != o2->type ||
|
|
Packit Service |
80a84b |
(o1->ptr == NULL) != (o2->ptr == NULL) ||
|
|
Packit Service |
80a84b |
(o1->member_list == NULL) != (o2->member_list == NULL)) {
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1->type == __type_reffile &&
|
|
Packit Service |
80a84b |
!record_same_declarations(o1->ref_record, o2->ref_record,
|
|
Packit Service |
80a84b |
processed)) {
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1->ptr &&
|
|
Packit Service |
80a84b |
!obj_same_declarations(o1->ptr, o2->ptr, processed)) {
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (o1->member_list) {
|
|
Packit Service |
80a84b |
list1 = o1->member_list->first;
|
|
Packit Service |
80a84b |
list2 = o2->member_list->first;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
while (list1) {
|
|
Packit Service |
80a84b |
if (list2 == NULL)
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (!obj_same_declarations(list1->member,
|
|
Packit Service |
80a84b |
list2->member,
|
|
Packit Service |
80a84b |
processed))
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
list1 = list1->next;
|
|
Packit Service |
80a84b |
list2 = list2->next;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
if (list1 != list2) {
|
|
Packit Service |
80a84b |
/* different member_list lengths */
|
|
Packit Service |
80a84b |
return false;
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
}
|
|
Packit Service |
80a84b |
|
|
Packit Service |
80a84b |
return true;
|
|
Packit Service |
80a84b |
}
|