/* build.c */

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

DNODE 	*add_dep_node();
FNODE	*add_file_node();

/* goes through the current directory build the dep list for each file */

build_depends(make_list,opts,mname)
DNODE		**make_list;
OPTS		*opts;
char		*mname;
{
	DIR		*dirp;
	struct direct	*dp;
	DNODE		*new;
	int		is_dep;
	char		ask[BUFSIZE];

	if ((dirp = opendir( CURRENT_DIR )) == NULL) {
		fprintf(stderr,"build_depends(): can't open directory\n");
		return(0);
	}
	/* for each file in the directory */
	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
		/* is it a recognisable source file */
		if (!valid_source_file(dp->d_name))
			continue;
		if ((new = add_dep_node(make_list,dp->d_name)) == NULL) {
			closedir(dirp);
			return(0);
		}
		/* a file depends on itself */
		add_file_node(new,dp->d_name);
		/* create the dependency list for the current file */
		if ((is_dep = build_dep_list(new,opts)) == 0) {
			closedir(dirp);
			return(0);
		}
		if (opts->exhaustive == 1 && is_dep == 1 && strcmp(new->name,mname)) {
			fprintf(stderr,"Warning:  no one else uses file %s\n",new->name);
			if (opts->interactive) {
				printf("Include file in Makefile(Y/N)? ");
				gets(ask);
				if (ask[0] != 'Y' && ask[0] != 'y')
					new->use_it = 0;
			}
			else
				new->use_it = 0;
		}
	}
	closedir(dirp);
	return(1);
}

build_dep_list(dnode,opts)
DNODE		*dnode;
OPTS		*opts;
{
	FILE		*fp;
	int		count = 0;
	int		cp = 0;
	int		stype;
	int		cont;
	char		buf[BUFSIZE];
	char		func_name[BUFSIZE];
	int		aok;
	int		is_dep = 0;
	CPPN		**cpp_stack;
	SYMENT		**symtab;

	stype = valid_source_file(dnode->name);	
	if (opts->exhaustive == 0 && stype == CSOURCE)
		return(1);
	if ((fp = fopen(dnode->name,"r")) == NULL) {
		fprintf(stderr,"build_dep_list: can't open %s\n",dnode->name);
		return(0);
	}
	cpp_stack = (CPPN **)malloc(sizeof(CPPN *));
	*cpp_stack = NULL;
	symtab = (SYMENT **)malloc(sizeof(SYMENT *));
	*symtab = NULL;
	buf[0] = '\0';
	func_name[0] = '\0';
	/* forever */
	for (;;) {
		cont = 1;
		switch (stype) {
			/* get the next function definition */	
			case CSOURCE:	cont = parse_file(fp,func_name,&count,buf,&cp,cpp_stack,symtab);
					break;
			default:	;
		}
		/* if we are done with the file, stop */
		if (!cont)
			break;
		/* add the dependencies */
		if ((aok = depend_on_it(dnode,func_name)) == 0) {
			cpp_rel(cpp_stack,symtab);
			fclose(fp);
			return(0);
		}
		if (aok == 2)
			is_dep = 1;
		if (stype == CHEADER)
			break;
	}
	cpp_rel(cpp_stack,symtab);
	fclose(fp);
	return(is_dep+1);
}

depend_on_it(dnode,func_name)
DNODE		*dnode;
char		*func_name;
{
	DIR		*dirp;
	struct direct	*dp;
	int		stype;
	int		aok;
	int		is_dep = 0;

#ifdef DEBUG
	printf("depend_on_it():  dnode->name= '%s'\nfunc_name= '%s'\n",dnode->name,func_name);
#endif
	stype = valid_source_file(dnode->name);	
	if ((dirp = opendir( CURRENT_DIR )) == NULL) {
		fprintf(stderr,"depend_on_it():  Can't open directory\n");
		return(0);
	}
	/* for each file in the directory */
	for (dp = readdir(dirp); dp != NULL; dp = readdir(dirp)) {
		if (!valid_source_file(dp->d_name) || in_file_list(dnode,dp->d_name))
			continue;
		switch (stype) {
			case CSOURCE:	aok = depends(dp->d_name,func_name);
					break;
			case CHEADER:	aok = hdepends(dp->d_name,dnode->name);
					break;
		}
		/* if we found a dependency, add the current file to list */
		if (aok) {
			is_dep = 1;
			if (add_file_node(dnode,dp->d_name) == NULL) {
				closedir(dirp);
				return(0);
			}
		}
	}
	closedir(dirp);
	return(is_dep+1);
}
