/*	depend.c
 *  (c) Copyright 1991 by Ben Eng, All Rights Reserved
 *
 */

#include <clib/exec_protos.h>

#include "make.h"
#include "depend.h"

struct target *
find_target( char *targetname )
{
	struct target *targ = NULL;

	for( struct target *ln = Global.targetlist.lh_Head; ln->node.ln_Succ;
		ln = ln->node.ln_Succ ) {
		if( !strcmp( targetname, ln->name )) {
			targ = ln;
			break;
		}
	}

	return( targ );
}

struct target *
new_target( char *targetname )
{
	long size;
	struct target *new = NULL;

	if( targetname && *targetname && !( new = find_target( targetname ))) {
		size = sizeof(struct target) + strlen( targetname );
		new = (struct target *)malloc( size );
		if( new ) {
			NewList( &new->dependlist );
			NewList( &new->commandlist );
			new->alternate = NULL;
			new->mtime = 0L;
			new->flags = 0L;
			if( targetname ) strcpy( new->name, targetname );
			else *targetname = (char)0;
		}
	}
	return( new );
}

int
delete_target( struct target *targ )
{
	free( targ );
	return( 0 );
}

void
delete_targetlist( struct List *list )
{
	for_list( list, delete_target );
	NewList( list );
}

struct depend *
new_depend( char *dependname )
{
	struct depend *new = NULL;
	long size;

	if( dependname ) {
		size = sizeof(struct depend) + strlen( dependname );
		if( new = (struct depend *)malloc( size )) {
			strcpy( new->name, dependname );
		}
	}
	return( new );
}

int
delete_depend( struct depend *dep )
{
	free( dep );
	return( 0 );
}

void
delete_dependlist( struct List *list )
{
	for_list( list, delete_depend );
	NewList( list );
}

struct command *
new_command( char *cmd )
{
	long size;
	struct command *new = NULL;
	if( cmd && *cmd ) {
		size = sizeof(struct command) + strlen( cmd );
		new = (struct command *)malloc( size );
		if( new ) {
			if( *cmd == '-' ) {
				new->flags = CF_IGNORE;
				cmd++;
			}
			else if( *cmd == '@' ) {
				new->flags = CF_NOECHO;
				cmd++;
			}
			else new->flags = 0;
			strcpy( new->cmd, cmd );
		}
	}
	return( new );
}

int
delete_command( struct command *cmd )
{
	free( cmd );
	return( 0 );
}

void
delete_commandlist( struct List *list )
{
	for_list( list, delete_command );
	NewList( list );
}

struct suffixrule *
find_suffixrule( char *dep_suf, char *tar_suf )
{
	struct suffixrule *sr = NULL;

	for( struct suffixrule *ln = Global.suffixlist.lh_Head; ln->node.ln_Succ;
		ln = ln->node.ln_Succ ) {
		if( !strcmp( dep_suf, ln->dep_suf ) &&
			!strcmp( tar_suf, ln->tar_suf )) {
			sr = ln;
			break;
		}
	}

	return( sr );
}

struct suffixrule *
new_suffixrule( char *dep_suf, char *tar_suf )
{
	int found_flag = 0;
	long size = sizeof(struct suffixrule);
	struct suffixrule *new = find_suffixrule( dep_suf, tar_suf );
	if( new ) found_flag = 1;
	else new = (struct suffixrule *)malloc( size );

	if( new ) {
		strcpy( new->tar_suf, tar_suf );
		strcpy( new->dep_suf, dep_suf );
		if( !found_flag ) AddTail( &Global.suffixlist, &new->node );
	}
	return( new );
}

int
delete_suffixrule( struct suffixrule *rule )
{
	free( rule );
	return( 0 );
}

void
delete_suffixlist( struct List *list )
{
	for_list( list, delete_suffixrule );
}

struct target *
add_suffix_targets( char *suf )
{
	char *next, tar_suf[ 16 ], dep_suf[ 16 ];	
	struct target *ln, *first_targ = NULL;

	for( ln = (struct target *)Global.targetlist.lh_Head;
		ln->node.ln_Succ; ln = ln->node.ln_Succ ) {

		next = ln->name;
		*dep_suf = *tar_suf = (char)0;

		if( *next++ == '.' ) {
			next = parse_strtok( tar_suf, next, sizeof(suf)-1, isnotsuf );
			if( *next++ == '.' ) {
				strcpy( dep_suf, tar_suf ); /* double-suffix */
				next = parse_strtok( tar_suf, next, sizeof(suf)-1, isnotsuf );
			}
		}
		if( !strcmp( suf, dep_suf) || !strcmp( suf, tar_suf )) {
			/* transform a target rule into a suffix rule */
			struct suffixrule *sr = new_suffixrule( dep_suf, tar_suf );
			if( sr ) {
				sr->targ = ln;
				ln->flags |= TF_SUFFIX;
				if( !first_targ ) first_targ = ln;
			}
			else return( NULL ); /* error */
		}
	}

	return( first_targ );
}
