/* parse.c */

#include <stdio.h>
#include "types.h"

int	sp;

parse_file(fp,fname,count,buf,curp,cpp_stack,symtab)
FILE		*fp;
char		*fname;
int		*count;
char		*buf;
int		*curp;
CPPN		**cpp_stack;
SYMENT		**symtab;
{
	int	not_empty;
	int	lb_count = *count;
	char	tok[BUFSIZE];
	int	cp = *curp;

	while ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) >= 0) {
		if (tok[0] == '{') {
			++lb_count;
		} else if (tok[0] == '}') {
			--lb_count;
		} else {
			if (lb_count > 0)
				continue;
			/* possible function definition, 1st ed K&R */
			strcpy(fname,tok);
			if ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) < 0)
				return(0);
			if (tok[0] != '(') {
				cp = sp;
				continue;
			}
			not_empty = 0;
			while ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) >= 0 && tok[0] != ')') {
				not_empty = 1;
				if ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) < 0)
					return(0);
				if (tok[0] == ')')
					break;
			}
			if (cp < 0)
				return(0);
			if (!not_empty) {
				if ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) < 0)
					return(0);
				if (tok[0] != '{')
					continue;
				++lb_count;
			}
			*curp = cp;
			*count = lb_count;
			return(1);
		}
	}
	return(0);
}


depends(filename,funcname)
char		*filename;
char		*funcname;
{
	FILE		*fp;
	char		tok[BUFSIZE];
	char		buf[BUFSIZE];
	char		cur_func[BUFSIZE];
	int		cp = 0;
	CPPN		**cpp_stack;
	SYMENT		**symtab;

	cpp_stack = (CPPN **)malloc(sizeof(CPPN *));
	*cpp_stack = NULL;
	symtab = (SYMENT **)malloc(sizeof(SYMENT *));
	*symtab = NULL;
	if ((fp = fopen(filename,"r")) == NULL) {
		fprintf(stderr,"depends():  can't open file %s\n",filename);
		cpp_rel(cpp_stack,symtab);
		return(0);
	}
	cur_func[BUFSIZE] = '\0';
	buf[0] = '\0';
	while ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) >= 0) {
		if (!strcmp(tok,funcname)) {
			if ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) < 0) {
				fclose(fp);
				cpp_rel(cpp_stack,symtab);
				return(0);
			}
			if (tok[0] == '(') {
				fclose(fp);
				cpp_rel(cpp_stack,symtab);
				return(1);
			}
			cp = sp;
		}
	}
	fclose(fp);
	cpp_rel(cpp_stack,symtab);
	return(0);
}

hdepends(filename,sname)
char		*filename;
char		*sname;
{
	FILE		*fp;
	char		tok[BUFSIZE];
	char		buf[BUFSIZE];
	char		name[BUFSIZE];
	int		cp = 0;
	CPPN		**cpp_stack;
	SYMENT		**symtab;

	cpp_stack = (CPPN **)malloc(sizeof(CPPN *));
	*cpp_stack = NULL;
	symtab = (SYMENT **)malloc(sizeof(SYMENT *));
	*symtab = NULL;
	if ((fp = fopen(filename,"r")) == NULL) {
		fprintf(stderr,"depends():  can't open file %s\n",filename);
		return(0);
	}
	strcpy(name,"\"");
	strcat(name,sname);
	strcat(name,"\"");
	buf[0] = '\0';
	while ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) >= 0) {
		if (tok[0] == '#' && sp == 0) {
			if ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) < 0) {
				fclose(fp);
				return(0);
			}
			if (!strcmp("include",tok)) {
				if ((cp = gettok(fp,buf,tok,cp,cpp_stack,symtab)) < 0) {
					fclose(fp);
					return(0);
				}
				if (!strcmp(name,tok)) {
					fclose(fp);
					return(1);
				}
			}
		}
	}
	fclose(fp);
	return(0);
}

gettok(fp,buf,curtok,cp,cpp_stack,symtab)
FILE		*fp;
char		*buf;
char		*curtok;
int		cp;
CPPN		**cpp_stack;
SYMENT		**symtab;
{
	int		quote = 0;
	int		tokind = 0;
	int		in_comment = 0;
	char		quotechar;

	do {
#ifdef DEBUG
		printf("eating whitespace\n");
#endif
		while (is_white(buf[cp]))
			++cp;
#ifdef DEBUG
		printf("cp = %4d  buf[cp] = '%c'\n",cp,buf[cp]);
#endif
		if (buf[cp] == '\0' && fp != NULL) {
			if (fgets(buf,BUFSIZE-1,fp) == NULL)
				return(-1);
			if (!in_comment) {
				if (cpp_parse(buf,cpp_stack,symtab) < 0)
					return(-1);
				if (cpp_stack != NULL) {
					if (!cpp_useline(cpp_stack,symtab)) {
						buf[0] = ' ';
						buf[1] = '\0';
					}	
				}
			}
			cp = 0;
		}
		else if (buf[cp] == NULL) {
			curtok[0] = '\0';
			return(-1);
		}	
		if (!in_comment) {
			if (buf[cp] == '/' && buf[cp+1] == '*') {
				in_comment = 1;
				cp += 2;
			}
		}
		else {
			if (buf[cp] == '*' && buf[cp+1] == '/') {
				in_comment = 0;
				cp += 2;
			}
			else 
				cp++;
		}
#ifdef DEBUG
		printf("in_comment = %d\n",in_comment);
#endif
	} while (is_white(buf[cp]) || in_comment);
	sp = cp;
	if (is_quote(buf[cp])) {
		quotechar = buf[cp++];
		curtok[tokind++] = quotechar;
		quote = 1;
	}
	if ((is_tok_sep(buf[cp]) || buf[cp] == '\0') && quote == 0) {
		curtok[tokind++] = buf[cp++];
		if (curtok[tokind-1] == '<' && (buf[cp] == '>' ||
			buf[cp] == '=')) {
			curtok[tokind++] = buf[cp++];
		} else if (curtok[tokind-1] == '>' && buf[cp] == '=') {
			curtok[tokind++] = buf[cp++];
		}
	}
	else {
		while ((!is_tok_sep(buf[cp]) && !is_white(buf[cp]) &&
			 buf[cp] != '\0' && quote == 0) ||
			(buf[cp] != '\0' && quote == 1)) {
			if (quote == 1 && buf[cp] == '\\')
				++cp;
			else if (quote == 1 && buf[cp] == quotechar)
				break;
			curtok[tokind++] = buf[cp++];
		}
	}
	if (quote == 1) {
		curtok[tokind++] = buf[cp++];
	}
	curtok[tokind] = '\0';
	return(cp);
}

is_white(c)
char		c;
{
	return((c == '\t' || c == '\n' || c == ' '));
}

is_quote(c)
char		c;
{
	return((c == '\'' || c == '\"'));
}

is_tok_sep(c)
char		c;
{
	return((c == ',' || c == '(' ||
		c == '#' || c == '!' ||
		c == '-' || c == '+' ||
		c == '*' || c == '/' ||
		c == '>' || c == '<' ||
		c == '=' || c == ';' ||
		c == ';' || c == ')' ||
		c == '[' || c == ']' ||
		c == ':' || c == '\\' ||
		c == '[' || c == ']'));
}

