/* $Id: constraint.c,v 1.8 2009/01/27 15:40:21 potyra Exp $ 
 *
 * Copyright (C) 2007-2009 FAUcc Team <info@faumachine.org>.
 * This program is free software. You can redistribute it and/or modify it
 * under the terms of the GNU General Public License, either version 2 of
 * the License, or (at your option) any later version. See COPYING.
 */

#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include "identifier.h"
#include "constraint.h"
#include "stmt.h"

struct constraint *
constraint_new(void)
{
	struct constraint *c;

	c = malloc(sizeof *c);
	assert(c);

	memset(c, 0, sizeof *c);

	return c;
}

struct constraint *
constraint_dup(struct constraint *oc)
{
	struct constraint *nc;

	nc = constraint_new();

	nc->string = identifier_dup(oc->string);
	nc->expr = expr_dup(oc->expr);

	return nc;
}

void
constraint_free(struct constraint *c)
{
}

struct constraint_list *
constraint_list_new(void)
{
	struct constraint_list *cl;

	cl = malloc(sizeof *cl);
	assert(cl);

	memset(cl, 0, sizeof *cl);

	return cl;
}

struct constraint_list *
constraint_list_dup(struct constraint_list *ocl)
{
	struct constraint_list *ncl;
	struct constraint *oc;
	struct constraint *nc;

	if (ocl == NULL) {
		return ocl;
	}

	ncl = constraint_list_new();

	for (oc = ocl->first; oc; oc = oc->next) {
		nc = constraint_dup(oc);

		nc->prev = ncl->last;
		nc->next = NULL;
		if (nc->prev) {
			nc->prev->next = nc;
		} else {
			ncl->first = nc;
		}
		ncl->last = nc;
	}

	return ncl;
}

void
constraint_list_free(struct constraint_list *cl)
{
}

void
constraint_list_append_last(struct constraint_list *cl, struct constraint *c)
{
	c->prev = cl->last;
	c->next = NULL;
	if (c->prev) {
		c->prev->next = c;
	} else {
		cl->first = c;
	}
	cl->last = c;
}

void
constraint_output(struct stmt *s, const char *string, struct expr *expr)
{
	struct constraint *c;

	assert(*string == '='
	    || *string == '+');

	if (! s->output) {
		s->output = constraint_list_new();
	}

	c = constraint_new();
	c->string = string;
	c->expr = expr;

	constraint_list_append_last(s->output, c);
}

void
constraint_input(struct stmt *s, const char *string, struct expr *expr)
{
	struct constraint *c;

	assert(*string != '='
	    && *string != '+');

	if (! s->input) {
		s->input = constraint_list_new();
	}

	c = constraint_new();
	c->string = string;
	c->expr = expr;

	constraint_list_append_last(s->input, c);
}

void
constraint_change(struct stmt *s, const char *string)
{
	struct constraint *c;

	if (! s->change) {
		s->change = constraint_list_new();
	}

	c = constraint_new();
	c->string = string;
	c->expr = NULL;

	constraint_list_append_last(s->change, c);
}
