/* RCSID : $Id: utils.c,v 1.5 1996/06/19 06:01:22 ae59 Exp ae59 $ */
/* $Log: utils.c,v $
 * Revision 1.5  1996/06/19  06:01:22  ae59
 * add version description
 *
 * Revision 1.4  1996/06/18  16:24:48  ae59
 * improved usage message
 *
 * Revision 1.3  1996/06/18  15:53:36  ae59
 * corrected ^M, comments, special functions
 *
 * Revision 1.2  1995/11/14  07:52:47  ae59
 * provide recursion
 *
 * Revision 1.1  1995/09/14  08:33:05  ae59
 * Initial revision
 *
 */
#include <stdio.h>
#include "config.h"
#include "version.h"
#include "utils.h"

#define pluralsuffix(num,suffix)	((num)==1?"":(suffix))
#define plural(num)	pluralsuffix(num,"s")

extern int  report_all;
extern int  callgraph;
extern int  echoinp;
extern int  metric;
extern int  subroutines;
extern int  reportid;
extern int  report_vars;
extern int  trace;
extern int  lines;
extern int  ignore_err;
extern char *FileName;
extern char yychar;
extern char *lastline;
extern char *addModPath;

int yyerror(msg) 
char *msg;
{
	fprintf(stderr, "\n%s\n## Error at %s near line %d in File %s\n",
				(1)? "":lastline , token_name(yychar), lines, 
				(FileName==NULL)?"stdin":FileName);
    if(msg==NULL ) fprintf(stderr, " %s\n",msg);
    return 1;
}

void parser_info()
{
    printf("\n%d line%s of %s parsed\n", lines, plural(lines), 
		(FileName==NULL)?"stdin":FileName);
    return;
}

void Message(str)
char *str;
{
	printf(str);
}

#ifdef __STDC__
void internal_error(char *format,e_args)
e_list
#else
void internal_error(format, e_args)
char *format;
e_list
#endif
{
	va_list ptr;
	e_open(ptr, format);
    	fprintf(stderr, "Internal error: ");
    	fprintf(stderr, format, ptr);
	va_end(ptr);
    	exit(2);
}

#ifdef __STDC__
void warning( char * fmt, e_args)
#else
void warning( fmt, e_args)
char* fmt;
e_list
#endif
{
	va_list ptr;
	e_open(ptr, fmt);
    	fprintf(stderr, "Warning line %d: ", lines);
    	fprintf(stderr, fmt, ptr);
    	fprintf(stderr, "\n");
	va_end(ptr);
    	return;
}

/*********************************************************************/
/* Name         : GetOpt                                             */
/* Description  : Reads commandline and quits if a filename is found */
/*                remembers index of found name for processing       */
/*                several names and different options                */
/* Input        : argc  - number of arguments                        */
/*                argv  - pointer to argument strings                */
/* Output       : none                                               */
/* Return       : 0 if commandline has been processed completely     */
/*                1 if commandline has been processed partially      */
/* Side Effect  : changes global flags                               */
/*********************************************************************/
#ifdef __STDC__
int  GetOpt(int argc, char** argv)
#else
int  GetOpt(argc, argv)
int argc;
char **argv;
#endif
{
	static int i=1;

	for (; i< argc; i++)
	{
		if (argv[i][0]=='-')
			switch (argv[i][1])
			{
				case 'a': report_all=1;
						break;
				case 'v': report_vars=1;
						break;
				case 'c': callgraph=1;
						break;
				case 'e': echoinp=1;
						break;
				case 'i': ignore_err=1;
						break;
				case 'm': metric=1;
						break;
				case 's': subroutines=1;
						break;
				case 'r': reportid=1;
						break;
				case 't': trace=1; 
						break;
				case 'x': i++; addModPath=argv[i];
						break;
				case 'h': printf("\n%s %s %s\n",argv[0],VERSION, RELEASE);
			printf("Generates Software Engineering Metrics for Pascal-XSC programs\n");
			printf("\nUsage: %s [options] filenames...\n",argv[0]);
			printf("Options are:\n");
			printf("	-a : report all routines\n");
			printf("	-c : generates flowgraph\n");
			printf("	-e : echos input\n");
			printf("	-i : ignore error\n");
			printf("	-m : generates metrics\n");
			printf("	-s : lists subroutines\n");
			printf("	-t : generates trace\n");
			printf("	-v : reports global variables\n");
			printf("	-x path: sets additional search path for modules\n");
			exit(1);
			break;
				default : fprintf(stderr,"unkown option %s\n",argv[i]);;
			}
			else 
			{
				FileName=argv[i++];
				return 1;
			}
	}
	return 0;
}

#ifdef __STDC__
void ParseMod(FILE* modfile,char* filename) 
#else
void ParseMod(modfile,filename) 
FILE* modfile;
char *filename;
#endif
{
	int i=0, type;
	char buffer[255];
	char modname[255];

	strcpy(modname, filename);
	modname[strlen(modname)-4]=EOS;

	while (!feof(modfile))
	{
		/*
		 * Key word
	 	 */
		type=fgetc(modfile);
		switch (type)
		{
				case 'V':  /* global variable */
			  		data_decls++;
					i=0;
					while ((buffer[i++] = fgetc(modfile)) != '=');
					buffer[--i] =EOS; 
					if (report_all && report_vars) 
					{
						printf("F| %s %c| %s :\n",modname,type, buffer);
					}
					while ((i = fgetc(modfile)) != '\n');
					break;
				case 'F':  /* global function */
				case 'P':  /* global procedure*/
					proc++;
					if (type == 'F' ) func++;
					else proc++;
					i=0;
					while ((buffer[i++] = fgetc(modfile)) != '=');
					buffer[--i] =EOS; 
					if (report_all) 
					{
			printf("F| %s %c| %s : CCM = %d BB = %d LOC = %d ELOC = %d EXOP = %d\n", modname, type, buffer,0,0,0,0,0);
					}
					while ((i = fgetc(modfile)) != '\n');
					break;

				case 'O': /* global operator */
					oper++;
					if ((type=fgetc(modfile)) == 'a' ) 
						 strcpy(buffer,":=");
					else
					{
						type=fgetc(modfile);
						switch (type)
						{
						/* unary */
						case '\033': strcpy(buffer,"+");
						break;
						case '\034': strcpy(buffer,"-");
						break;
						/* binary */
						case '\001': strcpy(buffer,"in");
						break;
						case '\002': strcpy(buffer,"=");
						break;
						case '\003': strcpy(buffer,"<>");
						break;
						case '\004': strcpy(buffer,">=");
						break;
						case '\005': strcpy(buffer,">");
						break;
						case '\006': strcpy(buffer,"<=");
						break;
						case '\007': strcpy(buffer,"<");
						break;
						case '\f': strcpy(buffer,"><");
						break;
						case '\013': strcpy(buffer,"/");
						break;
						case '\n': strcpy(buffer,"*");
						break;
						case '\r': strcpy(buffer,"**");
						break;
						case '\b': strcpy(buffer,"+");
						break;
						case '\016': strcpy(buffer,"+*");
						break;
						case '\017': strcpy(buffer,"+<");
						break;
						case '\t': strcpy(buffer,"-");
						break;
						case '\020': strcpy(buffer,"-<");
						break;
						case '\021': strcpy(buffer,"*<");
						break;
						case '\022': strcpy(buffer,"/<");
						break;
						case '\023': strcpy(buffer,"+>");
						break;
						case '\024': strcpy(buffer,"->");
						break;
						case '\025': strcpy(buffer,"*>");
						break;
						case '\026': strcpy(buffer,"/>");
						break;
						default : strcpy(buffer,"?");
						break;
						}
					}
					type = 'O';
					if (report_all) 
					      printf("F| %s %c| %s : CCM = %d BB = %d LOC = %d ELOC = %d EXOP = %d\n", modname, type, buffer,0,0,0,0,0);
					while ((i = fgetc(modfile)) != '\n');
				break;
				default:
					while ((i = fgetc(modfile)) != '\n')
						if (feof(modfile)) break;
					break;
		} /* switch */
	} /* while */
}

#ifdef __STDC__
char *GetDataPath(void)
#else
char *GetDataPath()
#endif
{
	static char buffer[255];
	char *path=NULL;
	FILE* p88;
	char prev;
	int c=' ', len, i;

	if ((p88=fopen("p88.env", "r")) != NULL) 
	{
		while (!feof(p88))
		{
			prev=c;
			c=fgetc(p88);
			if (c == 'p' && prev ==EOLN )
			{
				path= (char*) buffer;
				c=fgetc(p88); 		/* skip 0x01 */
				len=fgetc(p88)-1; 	/* lenght of string */
				for (i=0 ; i< len; i++) fgetc(p88); /* skip data */
				c=fgetc(p88); 		/* skip 0x01 */
				len=fgetc(p88)-1; 	/* lenght of string */
				for (i=0 ; i< len; i++) path[i]=fgetc(p88); /* skip data */
				path[i]=EOS;
				if (i==0) strcpy(path,"/usr/pxsc/sys/");
				break;
			}
		}
		fclose( p88);
	}
	return path;
}
