Blame src/output/amgc_output_compound.c

397226
/**********************************************************/
397226
/*  apimagic: cparser-based API normalization utility     */
84312f
/*  Copyright (C) 2015--2021  SysDeer Technologies, LLC   */
397226
/*  Released under GPLv2 and GPLv3; see COPYING.APIMAGIC. */
397226
/**********************************************************/
397226
397226
#include <stdio.h>
397226
397226
#include <cparser/ast/ast_t.h>
397226
#include <cparser/ast/type.h>
397226
#include <cparser/ast/type_t.h>
397226
#include <cparser/ast/entity_t.h>
397226
#include <cparser/ast/symbol_t.h>
397226
397226
#include <apimagic/apimagic.h>
397226
#include "apimagic_driver_impl.h"
397226
397226
static int output_string(
b8225b
	int *		fdout,
397226
	const char *	fmt,
397226
	const char *	string,
397226
	const char *	brace,
397226
	int *		len)
397226
{
b8225b
	int ret = fdout
b8225b
		? amgc_dprintf(*fdout,fmt,string,brace)
397226
		: snprintf(0,0,fmt,string,brace);
397226
397226
	if (len && (ret > 0))
397226
		*len += ret;
397226
397226
	return ret;
397226
}
397226
397226
static int output_compound(
397226
	union entity_t const *		entity,
397226
	int				depth,
397226
	const struct amgc_layout *	layout,
b8225b
	int *				fdout)
397226
{
397226
	struct compound_t const *	compound;
397226
	type_qualifiers_t		tquals;
397226
	union entity_t const *		subentity;
397226
	const union type_t *		type;
397226
	const struct declaration_t *	decl;
397226
	const char *			fmt;
397226
	const char *			name;
397226
	const char *			brace;
397226
	bool				ftabs;
397226
	bool				fspace;
397226
	int				len;
397226
	int				width;
397226
	int				ptrdepth;
397226
	int				symwidth;
397226
	int				i;
397226
397226
	if (entity->base.symbol && (depth == 0)) {
397226
		name  = entity->base.symbol->string;
397226
		brace = " {";
397226
	} else {
397226
		name  = "";
397226
		brace = "{";
397226
	}
397226
397226
	compound = 0;
397226
397226
	if (entity->kind == ENTITY_STRUCT)
397226
		fmt = "struct %s%s\n";
397226
	else if (entity->kind == ENTITY_UNION)
397226
		fmt = "union %s%s\n";
397226
	else if (entity->kind != ENTITY_COMPOUND_MEMBER)
397226
		return -1;
397226
	else if (entity->declaration.type->kind == TYPE_COMPOUND_STRUCT)
397226
		fmt = "struct %s%s\n";
397226
	else if (entity->declaration.type->kind == TYPE_COMPOUND_UNION)
397226
		fmt = "union %s%s\n";
397226
	else if (entity->declaration.type->kind == TYPE_POINTER) {
397226
		type = entity->declaration.type;
397226
397226
		for (; type->kind == TYPE_POINTER; )
397226
			type = type->pointer.points_to;
397226
397226
		compound = type->compound.compound;
397226
		entity   = compound->members.first_entity;
397226
397226
		if (type->kind == TYPE_COMPOUND_STRUCT)
397226
			fmt = "struct %s%s\n";
397226
		else if (type->kind == TYPE_COMPOUND_UNION)
397226
			fmt = "union %s%s\n";
397226
		else
397226
			return -1;
397226
	} else
397226
		return -1;
397226
397226
397226
	if (compound)
397226
		(void)0;
397226
	else if (entity->kind == ENTITY_COMPOUND_MEMBER) {
397226
		compound = entity->declaration.type->compound.compound;
397226
		entity = compound->members.first_entity;
397226
	} else {
397226
		compound = &entity->compound;
397226
		entity = compound->members.first_entity;
397226
	}
397226
397226
b8225b
	if (depth && fdout && (amgc_dprintf(*fdout,"\n") < 0))
397226
		return -1;
397226
397226
	for (i=0; i
b8225b
		if (output_string(fdout,"\t","","",0) < 0)
397226
			return -1;
397226
b8225b
	if (output_string(fdout,fmt,name,brace,&len) < 0)
397226
		return -1;
397226
397226
397226
	for (width=0,depth++; entity; entity=entity->base.next) {
397226
		type = entity->declaration.type;
397226
		len  = 0;
397226
397226
		while (type->kind == TYPE_ARRAY)
397226
			type = type->array.element_type;
397226
397226
		for (ptrdepth=0; type->kind==TYPE_POINTER; ptrdepth++)
397226
			type = type->pointer.points_to;
397226
397226
		tquals	= type->base.qualifiers;
397226
		ftabs	= true;
397226
397226
		switch (type->kind) {
397226
			case TYPE_TYPEDEF:
397226
				fmt = "%s ";
397226
				name = type->typedeft.typedefe->base.symbol->string;
397226
				break;
397226
397226
			case TYPE_ATOMIC:
397226
				fmt = "%s ";
397226
				name = get_atomic_kind_name(type->atomic.akind);
397226
				break;
397226
397226
			case TYPE_COMPOUND_STRUCT:
397226
			case TYPE_COMPOUND_UNION:
397226
				compound  = type->compound.compound;
397226
				subentity = compound->members.first_entity;
397226
				decl      = type->typedeft.typedefe;
397226
397226
				if (!subentity || decl->base.symbol) {
397226
					name = decl->base.symbol->string;
397226
					fmt  = (type->kind == TYPE_COMPOUND_STRUCT)
397226
						? "struct %s " : "union %s ";
397226
				} else {
397226
					ftabs = false;
397226
					name  = "";
397226
					fmt   = "";
397226
397226
					if (output_compound(
397226
							entity,depth,
b8225b
							layout,fdout) < 0)
397226
						return -1;
397226
				}
397226
397226
				break;
397226
397226
			case TYPE_VOID:
397226
				fmt = "%s ";
397226
				name = "void";
397226
				break;
397226
397226
			default:
397226
				fmt = "";
397226
				name = "";
397226
b8225b
				if (fdout)
b8225b
					amgc_dprintf(
b8225b
						*fdout,
b8225b
						"UNHANDLED TYPE! %d ",
397226
						type->kind);
397226
397226
				break;
397226
		}
397226
397226
		if (ftabs)
397226
			for (i=0; i
b8225b
				if (output_string(fdout,"\t","","",0) < 0)
397226
					return -1;
397226
397226
		if (tquals & TYPE_QUALIFIER_CONST)
b8225b
			if (output_string(fdout,"const ","","",&len) < 0)
397226
				return -1;
397226
b8225b
		if (output_string(fdout,fmt,name,"",&len) < 0)
397226
			return -1;
397226
397226
		for (fspace=ptrdepth; ptrdepth; ptrdepth--) {
397226
			type = entity->declaration.type;
397226
397226
			while (type->kind == TYPE_ARRAY)
397226
				type = type->array.element_type;
397226
397226
			for (i=0; i
397226
				type = type->pointer.points_to;
397226
397226
			if (type->base.qualifiers & TYPE_QUALIFIER_CONST)
397226
				if (type->kind == TYPE_POINTER)
b8225b
					if (output_string(fdout," const ",
397226
							"","",&len) < 0)
397226
						return -1;
397226
b8225b
			if (output_string(fdout,"*","","",&len) < 0)
397226
				return -1;
397226
		}
397226
397226
		if (fspace)
397226
			len++;
397226
b8225b
		if (fdout) {
397226
			symwidth = layout->symwidth;
397226
397226
			symwidth += layout->tabwidth;
397226
			symwidth &= (~(layout->tabwidth-1));
397226
397226
			len &= (~(layout->tabwidth-1));
397226
397226
			while (len < symwidth) {
b8225b
				if (amgc_dprintf(*fdout,"\t") < 0)
397226
					return -1;
397226
				else
397226
					len += layout->tabwidth;
397226
			}
397226
		} else if (len > width)
397226
			width = len;
397226
b8225b
		if (output_string(fdout,"%s",
397226
				entity->base.symbol->string,
397226
				"",0) < 0)
397226
			return -1;
397226
397226
		type = entity->declaration.type;
397226
b8225b
		while (fdout && type->kind == TYPE_ARRAY) {
b8225b
			if (amgc_dprintf(
b8225b
					*fdout,
397226
					type->array.size ? "[%zu]" : "[]",
397226
					type->array.size) < 0)
397226
				return -1;
397226
397226
			type = type->array.element_type;
397226
		}
397226
b8225b
		if (fdout && amgc_dprintf(*fdout,";\n") < 0)
397226
			return -1;
397226
b8225b
		if (!ftabs && fdout && entity->base.next)
b8225b
			if (amgc_dprintf(*fdout,"\n") < 0)
397226
				return -1;
397226
	}
397226
b8225b
	if (!fdout)
397226
		return width;
397226
397226
	if (--depth) {
397226
		for (i=0; i
b8225b
			if (output_string(fdout,"\t","","",0) < 0)
397226
				return -1;
397226
b8225b
		if (output_string(fdout,"} ","","",0) < 0)
397226
			return -1;
397226
	} else {
b8225b
		if (output_string(fdout,"};\n","","",0) < 0)
397226
			return -1;
397226
	}
397226
397226
	return 0;
397226
}
397226
d1ebf8
static int output_compound_entity(
b8225b
	const struct amgc_driver_ctx *	dctx,
397226
	const struct amgc_unit_ctx *	uctx,
397226
	const struct amgc_entity *	aentity,
b8225b
	const struct amgc_layout *	layout)
397226
{
397226
	struct amgc_layout elayout;
b8225b
	int fdout = amgc_driver_fdout(dctx);
397226
3a51d2
	(void)uctx;
3a51d2
397226
	if (layout && layout->symwidth)
b8225b
		return output_compound(aentity->entity,0,layout,&fdout);
397226
397226
	if (layout)
397226
		memcpy(&elayout,layout,sizeof(elayout));
397226
	else
397226
		memset(&elayout,0,sizeof(elayout));
397226
397226
	if ((elayout.symwidth = output_compound(aentity->entity,0,layout,0)) < 0)
397226
		return -1;
397226
397226
	if (elayout.tabwidth == 0)
397226
		elayout.tabwidth = AMGC_TAB_WIDTH;
397226
b8225b
	if (output_compound(aentity->entity,0,&elayout,&fdout) < 0)
397226
		return -1;
397226
397226
	return 0;
397226
}
d1ebf8
d1ebf8
int amgc_output_compound(
b8225b
	const struct amgc_driver_ctx *	dctx,
d1ebf8
	const struct amgc_unit_ctx *	uctx,
d1ebf8
	const struct amgc_entity *	aentity,
b8225b
	const struct amgc_layout *	layout)
d1ebf8
{
d1ebf8
	union entity_t const * entity;
d1ebf8
d1ebf8
	entity = aentity->entity;
d1ebf8
b8225b
	return ((entity->kind == ENTITY_STRUCT) || (entity->kind == ENTITY_UNION))
b8225b
		? output_compound_entity(dctx,uctx,aentity,layout)
b8225b
		: -1;
d1ebf8
}
ca3de4
ca3de4
int amgc_output_struct(
b8225b
	const struct amgc_driver_ctx *	dctx,
ca3de4
	const struct amgc_unit_ctx *	uctx,
ca3de4
	const struct amgc_entity *	aentity,
b8225b
	const struct amgc_layout *	layout)
ca3de4
{
ca3de4
	union entity_t const * entity;
ca3de4
ca3de4
	entity = aentity->entity;
ca3de4
b8225b
	return (entity->kind == ENTITY_STRUCT)
b8225b
		? output_compound_entity(dctx,uctx,aentity,layout)
b8225b
		: -1;
ca3de4
}
ca3de4
ca3de4
int amgc_output_union(
b8225b
	const struct amgc_driver_ctx *	dctx,
ca3de4
	const struct amgc_unit_ctx *	uctx,
ca3de4
	const struct amgc_entity *	aentity,
b8225b
	const struct amgc_layout *	layout)
ca3de4
{
ca3de4
	union entity_t const * entity;
ca3de4
ca3de4
	entity = aentity->entity;
ca3de4
b8225b
	return (entity->kind == ENTITY_UNION)
b8225b
		? output_compound_entity(dctx,uctx,aentity,layout)
b8225b
		: -1;
b8225b
ca3de4
}
0c91ec
0c91ec
int  amgc_output_unit_structs(
b8225b
	const struct amgc_driver_ctx *	dctx,
0c91ec
	const struct amgc_unit_ctx *	uctx,
b8225b
	const struct amgc_layout *	layout)
0c91ec
{
0c91ec
	const struct amgc_entity * aentity;
0c91ec
0c91ec
	for (aentity=uctx->entities->structs; aentity->entity; aentity++)
b8225b
		if (output_compound_entity(dctx,uctx,aentity,layout) < 0)
0c91ec
			return -1;
0c91ec
0c91ec
	return 0;
0c91ec
}
0c91ec
0c91ec
int  amgc_output_unit_unions(
b8225b
	const struct amgc_driver_ctx *	dctx,
0c91ec
	const struct amgc_unit_ctx *	uctx,
b8225b
	const struct amgc_layout *	layout)
0c91ec
{
0c91ec
	const struct amgc_entity * aentity;
0c91ec
0c91ec
	for (aentity=uctx->entities->unions; aentity->entity; aentity++)
b8225b
		if (output_compound_entity(dctx,uctx,aentity,layout) < 0)
0c91ec
			return -1;
0c91ec
0c91ec
	return 0;
0c91ec
}