/* makef.c */

#include <stdio.h>
#include <sys/types.h>
#include <sys/dir.h>
#include "types.h"

DNODE		*last_node();
DNODE		*find_dep();



make_file(make_list,opts,mname)
DNODE		**make_list;
OPTS		*opts;
char		*mname;
{
	FILE		*fp;
	DNODE		*out;
	DNODE		*in;
	DNODE		*last;
	int		count;
	int		type;
	char		name[BUFSIZE];

	if ((fp = fopen("Makefile","w")) == NULL) {
		fprintf(stderr,"make_file(): can't open Makefile for writing\n");
		return(0);
	}
	if (!macros(make_list,fp,opts,mname)) {
		fclose(fp);
		return(0);
	}
	for (out = *make_list; out != NULL; out = out->next) {
		if (target(out->name,name) && out->use_it) {
			type = valid_source_file(out->name);
			fprintf(fp,"%s:\t",name);
			last = last_node(make_list,out->name);
			count = 0;
			for (in = *make_list; in != NULL; in = in->next) {
				if (valid_source_file(in->name) == CSOURCE &&
				    strcmp(in->name,out->name))
					continue;
				if (in_file_list(in,out->name)) {
					++count;
					if (strcmp(in->name,name))
						write_dep(fp,count,in,last,in->name);
					else
						write_dep(fp,count,in,last,"");
				}
			}
			write_command(fp,out->name,type,opts);
		}
	}
	fclose(fp);
	return(1);
}

write_command(fp,name,type,opts)
FILE		*fp;
char		*name;
int		type;
OPTS		*opts;
{
	switch (type) {
		case CSOURCE:	fprintf(fp,"\t\t$(CC) $(COPTS) -c %s\n\n",name);
				break;
		case CHEADER:	fprintf(fp,"\t\ttouch %s\n\n",name);
				break;
	}
}

write_dep(fp,count,in,last,name)
FILE		*fp;
int		count;
DNODE		*in;
DNODE		*last;
char		*name;
{
	if (count == 1 && in != last)
		fprintf(fp,"%s\\\n",name);
	else if (count == 1)
		fprintf(fp,"%s\n",name);
	else if (in == last)
		fprintf(fp,"\t\t%s\n",name);
	else
		fprintf(fp,"\t\t%s\\\n",name);
}

DNODE *
last_node(make_list,name)
DNODE		**make_list;
char		*name;
{
	DNODE		*last = NULL;
	DNODE		*in;

	for (in = *make_list; in != NULL; in = in->next) {
		if (valid_source_file(in->name) == CSOURCE &&
		    strcmp(in->name,name))
			continue;
		if (in_file_list(in,name))
			last = in;
	}
	return(last);
}	

macros(make_list,fp,opts,mname)
DNODE		**make_list;
FILE		*fp;
OPTS		*opts;
char		*mname;
{
	fprintf(fp,"#%s\n",BANNER);
	fprintf(fp,"CC= cc\n");
	fprintf(fp,"COPTS= -g\n");
	fprintf(fp,"OFILES= \\\n");
	if (!ofiles(make_list,fp,opts))
		return(0);
	fprintf(fp,"#\n");
	if (!main_target(fp,opts,mname))
		return(0);
	return(1);
}

ofiles(make_list,fp,opts)
DNODE		**make_list;
FILE		*fp;
OPTS		*opts;
{
	DNODE		*cur;
	DIR		*dirp;
	struct direct	*dp;
	int		type;
	char		name[BUFSIZE];
	char		last[BUFSIZE];

	if ((dirp = opendir( CURRENT_DIR )) == NULL) {
		fprintf(stderr,"ofiles(): can't open directory\n");
		return(0);
	}
	if (!last_ofile(make_list,opts,last)) {
		closedir(dirp);
		return(0);	
	}
	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
		type = valid_source_file(dp->d_name);
		if ((cur = find_dep(make_list,dp->d_name)) == NULL)
			continue;
		if (type == CSOURCE && target(dp->d_name,name) && cur->use_it)
			if (strcmp(last,dp->d_name))
				fprintf(fp,"\t%s\\\n",name);
			else
				fprintf(fp,"\t%s\n",name);
	}
	closedir(dirp);
	return(1);
}

last_ofile(make_list,opts,last)
DNODE		**make_list;
OPTS		*opts;
char		*last;
{
	DNODE		*cur;
	DIR		*dirp;
	struct direct	*dp;
	int		type;
	char		name[BUFSIZE];

	if ((dirp = opendir( CURRENT_DIR )) == NULL) {
		fprintf(stderr,"last_ofile(): can't open directory\n");
		return(0);
	}
	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
		type = valid_source_file(dp->d_name);
		if ((cur = find_dep(make_list,dp->d_name)) == NULL)
			continue;
		if (type == CSOURCE && target(dp->d_name,name) && cur->use_it)
			strcpy(last,dp->d_name);
	}
	closedir(dirp);
	return(1);
}

find_main_target(opts,mname)
OPTS		*opts;
char		*mname;
{
	DIR		*dirp;
	struct direct	*dp;
	int		type;
	int		count = 0;

	if ((dirp = opendir( CURRENT_DIR )) == NULL) {
		fprintf(stderr,"main_target(): can't open directory\n");
		return(0);
	}
	mname[0] = '\0';	
	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
		type = valid_source_file(dp->d_name);
		if (type == CSOURCE)
			if (depends(dp->d_name,"main")) {
				if (++count > 1) 
					fprintf(stderr,"Warning: main() multiply defined: %s\n",dp->d_name);
				strcpy(mname,dp->d_name);
			}

	}
	closedir(dirp);
	return(1);
}

main_target(fp,opts,mname)
FILE		*fp;
OPTS		*opts;
char		*mname;
{
	int		i;
	char		name[BUFSIZE];

	strcpy(name,mname);
	for (i = 0; name[i] != '.' && name[i] != '\0'; i++)
		;
	name[i] = '\0';	
	fprintf(fp,"%s:\t$(OFILES)\n",name);
	fprintf(fp,"\t\t$(CC) $(COPTS) -o %s $(OFILES)\n\n",name);
	return(1);
}

target(old,new)
char		*old;
char		*new;
{
	int		i;

	strcpy(new,old);
	for (i = 0; old[i] != '.' && old[i] != '\0'; i++)
		;
	if (old[i] == NULL)
		return(0);
	if (!strcmp(&old[i+1],"c"))
		new[i+1] = 'o';
	else if (!strcmp(&old[i+1],"h"))
		;
	else
		return(0);
	return(1);
}
