Blame src/output/amgc_output_compound.c

397226
/**********************************************************/
397226
/*  apimagic: cparser-based API normalization utility     */
397226
/*  Copyright (C) 2015--2016  Z. Gilboa                   */
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(
397226
	FILE *		fout,
397226
	const char *	fmt,
397226
	const char *	string,
397226
	const char *	brace,
397226
	int *		len)
397226
{
397226
	int ret = fout
397226
		? fprintf(fout,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,
397226
	FILE *				fout)
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
397226
	if (depth && fout && (fputc('\n',fout) < 0))
397226
		return -1;
397226
397226
	for (i=0; i
397226
		if (output_string(fout,"\t","","",0) < 0)
397226
			return -1;
397226
397226
	if (output_string(fout,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,
397226
							layout,fout) < 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
397226
				if (fout)
397226
					fprintf(fout,"UNHANDLED TYPE! %d ",
397226
						type->kind);
397226
397226
				break;
397226
		}
397226
397226
		if (ftabs)
397226
			for (i=0; i
397226
				if (output_string(fout,"\t","","",0) < 0)
397226
					return -1;
397226
397226
		if (tquals & TYPE_QUALIFIER_CONST)
397226
			if (output_string(fout,"const ","","",&len) < 0)
397226
				return -1;
397226
397226
		if (output_string(fout,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)
397226
					if (output_string(fout," const ",
397226
							"","",&len) < 0)
397226
						return -1;
397226
397226
			if (output_string(fout,"*","","",&len) < 0)
397226
				return -1;
397226
		}
397226
397226
		if (fspace)
397226
			len++;
397226
397226
		if (fout) {
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) {
397226
				if (fputc('\t',fout) < 0)
397226
					return -1;
397226
				else
397226
					len += layout->tabwidth;
397226
			}
397226
		} else if (len > width)
397226
			width = len;
397226
397226
		if (output_string(fout,"%s",
397226
				entity->base.symbol->string,
397226
				"",0) < 0)
397226
			return -1;
397226
397226
		type = entity->declaration.type;
397226
397226
		while (fout && type->kind == TYPE_ARRAY) {
397226
			if (fprintf(fout,
397226
					type->array.size ? "[%zu]" : "[]",
397226
					type->array.size) < 0)
397226
				return -1;
397226
397226
			type = type->array.element_type;
397226
		}
397226
397226
		if (fout && fputs(";\n",fout) < 0)
397226
			return -1;
397226
397226
		if (!ftabs && fout && entity->base.next)
397226
			if (fputc('\n',fout) < 0)
397226
				return -1;
397226
	}
397226
397226
	if (!fout)
397226
		return width;
397226
397226
	if (--depth) {
397226
		for (i=0; i
397226
			if (output_string(fout,"\t","","",0) < 0)
397226
				return -1;
397226
397226
		if (output_string(fout,"} ","","",0) < 0)
397226
			return -1;
397226
	} else {
397226
		if (output_string(fout,"};\n","","",0) < 0)
397226
			return -1;
397226
	}
397226
397226
	return 0;
397226
}
397226
d1ebf8
static int output_compound_entity(
397226
	const struct amgc_unit_ctx *	uctx,
397226
	const struct amgc_entity *	aentity,
397226
	const struct amgc_layout *	layout,
397226
	FILE *				fout)
397226
{
397226
	struct amgc_layout elayout;
397226
397226
	if (layout && layout->symwidth)
397226
		return output_compound(aentity->entity,0,layout,fout);
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
397226
	if (output_compound(aentity->entity,0,&elayout,fout) < 0)
397226
		return -1;
397226
397226
	return 0;
397226
}
d1ebf8
d1ebf8
int amgc_output_compound(
d1ebf8
	const struct amgc_unit_ctx *	uctx,
d1ebf8
	const struct amgc_entity *	aentity,
d1ebf8
	const struct amgc_layout *	layout,
d1ebf8
	FILE *				fout)
d1ebf8
{
d1ebf8
	union entity_t const * entity;
d1ebf8
d1ebf8
	entity = aentity->entity;
d1ebf8
d1ebf8
	if ((entity->kind == ENTITY_STRUCT) || (entity->kind == ENTITY_UNION))
d1ebf8
		return output_compound_entity(uctx,aentity,layout,fout);
d1ebf8
	else
d1ebf8
		return -1;
d1ebf8
}
ca3de4
ca3de4
int amgc_output_struct(
ca3de4
	const struct amgc_unit_ctx *	uctx,
ca3de4
	const struct amgc_entity *	aentity,
ca3de4
	const struct amgc_layout *	layout,
ca3de4
	FILE *				fout)
ca3de4
{
ca3de4
	union entity_t const * entity;
ca3de4
ca3de4
	entity = aentity->entity;
ca3de4
ca3de4
	if (entity->kind == ENTITY_STRUCT)
ca3de4
		return output_compound_entity(uctx,aentity,layout,fout);
ca3de4
	else
ca3de4
		return -1;
ca3de4
}
ca3de4
ca3de4
int amgc_output_union(
ca3de4
	const struct amgc_unit_ctx *	uctx,
ca3de4
	const struct amgc_entity *	aentity,
ca3de4
	const struct amgc_layout *	layout,
ca3de4
	FILE *				fout)
ca3de4
{
ca3de4
	union entity_t const * entity;
ca3de4
ca3de4
	entity = aentity->entity;
ca3de4
ca3de4
	if (entity->kind == ENTITY_UNION)
ca3de4
		return output_compound_entity(uctx,aentity,layout,fout);
ca3de4
	else
ca3de4
		return -1;
ca3de4
}
0c91ec
0c91ec
int  amgc_output_unit_structs(
0c91ec
	const struct amgc_unit_ctx *	uctx,
0c91ec
	const struct amgc_layout *	layout,
0c91ec
	FILE *				fout)
0c91ec
{
0c91ec
	const struct amgc_entity * aentity;
0c91ec
0c91ec
	for (aentity=uctx->entities->structs; aentity->entity; aentity++)
0c91ec
		if (output_compound_entity(uctx,aentity,layout,fout))
0c91ec
			return -1;
0c91ec
0c91ec
	return 0;
0c91ec
}
0c91ec
0c91ec
int  amgc_output_unit_unions(
0c91ec
	const struct amgc_unit_ctx *	uctx,
0c91ec
	const struct amgc_layout *	layout,
0c91ec
	FILE *				fout)
0c91ec
{
0c91ec
	const struct amgc_entity * aentity;
0c91ec
0c91ec
	for (aentity=uctx->entities->unions; aentity->entity; aentity++)
0c91ec
		if (output_compound_entity(uctx,aentity,layout,fout))
0c91ec
			return -1;
0c91ec
0c91ec
	return 0;
0c91ec
}