/*" $Id: pmake.c,v 1.16 1995/10/19 09:31:35 ae59 Exp ae59 $ */
/**************************************************************** 
 * Description : Creates makefile from pascal sources           * 
 *               and prints it to stdout                        * 
 * Note        : Compile: cc -o pmake pmake.c                   * 
 *               or       make pmake                            * 
 *               Call :   pmake *.p                             * 
 * Return      : 0 returned in case of an error                 * 
 * Author      : H. Berlejung, IAMK UNIKA                       * 
 * Initial date: 1994-01-26                                     * 
 * Copyright   : (C) All rights reserved UNIKA IAM              *
 **************************************************************** 
 */
/*
$Log: pmake.c,v $
 * Revision 1.16  1995/10/19  09:31:35  ae59
 * corrected uninitialized savelist buffer. Initialized with EOS
 *
 * Revision 1.15  1995/09/21  16:14:27  ae59
 * continues even if sca of an module fails,restructured makefile
 *
 * Revision 1.14  1995/09/21  11:44:47  ae59
 * considered p88.env (search of modules)
 * check host system (path)
 * checked PXSC_SYS (future extension)
 * introduced savelist in order to avoid double targets
 * changed default description text in makefile
 *
 * Revision 1.13  1995/08/15  12:58:50  ae59
 * targets not separated by newline
 * restructured usage msg
 * new option opt_name that directs sinmple lists
 *
 * Revision 1.12  1995/01/26  07:39:55  ae59
 * replace ANSI_C by __STDC__, removed unused vars.
 *
 * Revision 1.11  1994/09/02  07:47:16  ae59
 * $on, $off supported, check target in stdmod, no iostd spec.
 *
 * Revision 1.10  1994/05/30  12:43:57  ae59
 * rm point from OEX definition
 *
 * Revision 1.9  1994/05/20  09:54:38  ae59
 * add targets in case of -a option
 * add Fgetc function to handle toupper misbehavior
 *
 * Revision 1.8  1994/05/20  09:22:41  ae59
 * changed toupper call at Word due to MSC misbehaviour
 *
 * Revision 1.7  1994/05/04  13:07:08  ae59
 * replaced sprint with strcat in target list creation.
 * macro used for target extension OEXT.
 *
 * Revision 1.6  1994/03/15  09:25:00  ae59
 * changed Makefile RCS ID to avoid RCS substitution in  source
 *
 * Revision 1.5  1994/03/14  08:23:43  ae59
 * add RCS entry
 *
 * Revision 1.4  1994/03/14  08:18:10  ae59
 * add __STDC__ Prototypes for C++ Compiler
 * add target dosclean
 * revised version string manipulation
 *
 * Revision 1.3  1994/02/23  15:26:49  ae59
 * allow different lines for use clause and module names
 *
 * Revision 1.2  1994/01/26  12:28:56  ae59
 * corrected version string
 *
 * Revision 1.1  1994/01/26  11:22:43  ae59
 * Initial revision
 *
 */

/*--------------------------------------------------------------*
 *                   includings                                 *
 *--------------------------------------------------------------*
 */
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <ctype.h>

/*#define __STDC__*/
#ifdef __STDC__
#define _PROTOTYPE(proc, arg) proc arg
#else
#define _PROTOTYPE(proc, arg) proc()
#endif
/*--------------------------------------------------------------*
 *                   macros and constants                       *
 *--------------------------------------------------------------*
 */
/*
 * abbreviations
 */
#define EOLN             '\n'
#define EOS              '\0'
#define FEND             ((char) -1)
#define SPACE            ' '
#define ASSIGN           '='
#define TAB              '\t'
#define FALSE            0
#define TRUE             (!FALSE)

#define TARGETEXT        "o"  /* default target extension     */
#define TARGETEXTLEN     10    /* default length of  extension */
#define VERSIONLEN       50    /* max length of version string */

/*
 * limits 
 */
#define BUFFLEN       255
/*
 * errors
 */
#define NO_ERROR         0
#define NO_SRCFILE       1
#define NO_DESTFILE      2 
#define CMD_ERROR        3 
#define FEND_ERROR       4
#define NO_MEMORY        5
#define MISC_ERROR       6

#define FEXT_SEP '.'
#define DOS_PATH_SEP '\\'
#define UNIX_PATH_SEP '/'
#define P88ENV 		"p88.env"	
#define CURRENTDIR		"./"
#define SYSTEM_path		"path"	
#define SYSTEM_PATH		"PATH"	
#define PXSC_SYS		"PXSC_SYS"	
#define HOME			"HOME"	
/*--------------------------------------------------------------*
 *                   global vars                                *
 *--------------------------------------------------------------*
 */
int opt_all;
int opt_names;
int trace=0;
int debug=0;
int isstdmod=0;
int cmdargc;
char **cmdargv;
char path_sep = DOS_PATH_SEP;

static char *rcsid="$Id: pmake.c,v 1.16 1995/10/19 09:31:35 ae59 Exp ae59 $";
char  version[VERSIONLEN];
static char targetext[]=".$(OEXT)";
static char target [TARGETEXTLEN];
static int savesize=BUFFLEN;
static char* savelist=NULL;

/*
 * Where to find pxsc modules
 */
static char* pxsc_sys ;
static char* home ;
static char p88_env [BUFFLEN];
static char p88_env_home [BUFFLEN];

/*--------------------------------------------------------------*
 *                   local prototypes                           *
 *--------------------------------------------------------------*
 */
_PROTOTYPE(static int  StrEq   ,(char *s1,char *s2));
_PROTOTYPE(static int  mod_in_list ,(char *s1));
_PROTOTYPE(static int  Fgetc, (FILE* f));
_PROTOTYPE(static char *BuildFilename,(char *env,char* filename,char* ext));
_PROTOTYPE(static void Out ,(char* name, char *list));
_PROTOTYPE(static char Word,(FILE* f));
_PROTOTYPE(static void SearchModules,(FILE* f,char **plist, int* size));
_PROTOTYPE(static int  Sca,(char* filename));
_PROTOTYPE(static void MakeFile,(int argc, char**argv));
_PROTOTYPE(static void PostMakeFile,(void));
_PROTOTYPE(static void GetP88env,(char *path, char *modpath));
_PROTOTYPE(static char* GetEnvName,(char *filename));
_PROTOTYPE(static void SaveTarget ,(char *name));
/*--------------------------------------------------------------*
 *                   procedures                                 *
 *--------------------------------------------------------------*
 */
 
/**************************************************************** 
 * Name     : StrEq                                             * 
 * Descript.: compares 2 strings without case distinction       * 
 * Input    : s1, s2 strngs                                     * 
 * Output   : none                                              * 
 * Return   : 1 if both identical, else 0                       * 
 * Global   : none                                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static int StrEq( char *s1,char *s2)
#else
static int StrEq( s1,s2)
char*s1, *s2;
#endif
{
	while (*s1 && *s2 ) if (toupper(*s1)==toupper(*s2)) { s1++;s2++;}
					else break;
	return (*s1 == EOS && *s2==EOS) ? 1:0;
}

/**************************************************************** 
 * Name     : mod_in_list                                       * 
 * Descript.: checks s1 tob e already listed                    * 
 * Input    : s1     strngs                                     * 
 * Output   : none                                              * 
 * Return   : 1 if module listed , else 0                       * 
 * Global   : none                                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static int mod_in_list( char* s1)
#else
static int mod_in_list( s1)
char*s1 ;
#endif
{
	register int i;
	char buffer[255];
	char*arg;

	i=cmdargc-1;
	for (; i>0;i--)
	{
		if (cmdargv[i][0]=='-') continue;
		strcpy(buffer, cmdargv[i]);
	     if ((arg=strrchr(buffer,'.')) != NULL) *arg=EOS;
		if (debug) printf("%d Compare: %s %s\n",i,s1,buffer);
		if (StrEq(s1, buffer)) return 1;
	}
	return 0;
	
}

/**************************************************************** 
 * Name     : Fgetc                                             * 
 * Descript.: reads a character and convert to upper case       * 
 * Input    : f - file desc                                     * 
 * Output   : none                                              * 
 * Return   : upper case of character                           * 
 * Global   : none                                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static int Fgetc( FILE *f)
#else
static int Fgetc( f)
FILE* f;
#endif
{
	int c = fgetc(f);
	return (toupper(c));
}

/**************************************************************** 
 * Name     : BuildFilename                                     * 
 * Descript.: Builds filename from environment variable,        * 
 *            filename and extension.                           * 
 * Input    : env      : name of environment variable "" none   * 
 *            filename : name of file                           * 
 *            ext      : extension "" none                      * 
 * Output   : none                                              * 
 * Return   : pointer to filename built                         * 
 * Global   : none                                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static char *BuildFilename(char* env,char* filename, char* ext)
#else
static char *BuildFilename(env,filename, ext)
char *env;
char *filename;
char *ext;
#endif
{
     static char buffer[BUFFLEN];
     static char *sep_pos =buffer, 
                 *path_pos=buffer;

     *buffer = EOS;

     /* get environment variable */
     if (*env != EOS ) 
     {
          char *envname;

          if ((envname =getenv(env))!=NULL)
               sprintf(buffer, "%s%c",envname,path_sep);
     }

     /* add filename to buffer */
     strcat(buffer,filename);

     /* add extension  */
     sep_pos  = strrchr(buffer,FEXT_SEP);
     path_pos = strrchr(buffer,path_sep);
     /* 
      * don't substitute separator in path and leading sep's 
      */
     if ((sep_pos > path_pos+1) &&
         (sep_pos != buffer)    &&
         (sep_pos !=NULL    ))   *sep_pos = EOS; /* cut old extension */
        if (*ext !='.')  strcat(buffer,".") ;
     strcat(buffer,ext) ;
     return buffer;
}
/**************************************************************** 
 * Name     : Out                                               * 
 * Descript.: Builds filename from environment variable,        * 
 *            filename and extension.                           * 
 * Input    : env      : name of environment variable "" none   * 
 *            filename : name of file                           * 
 *            ext      : extension "" none                      * 
 * Output   : none                                              * 
 * Return   : pointer to filename built                         * 
 * Global   : none                                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static void Out (char* name, char* list)
#else
static void Out (name, list)
char* name;
char *list;
#endif
{
     char tname[BUFFLEN];
	char stdmod[20];

     sprintf(stdmod,"stdmod%s",targetext);
     strcpy(tname,name);
     name=BuildFilename("",tname,targetext);
     printf("%s : ",name);
	if (isstdmod && (StrEq(name,stdmod)==0)) printf("%s ",stdmod);
     while (*list ==' ') list++;
     if (*list) 
     {
	   if ((StrEq(name,stdmod)!=0)) 
	   {
		/* modules in stdmod are not allowed */
	   	fprintf(stderr,"# Warning :%s in dependancy list of %s ignored !\n",
					  list,name);
     	printf(" %s\n", tname);
		return;
	   }
        while (*list) 
                if (*list == ' ') 
                {
                      printf("%s ", targetext);     
				  list++;
                }
                else putc(*list++,stdout);     
        printf("%s ",targetext);    
     }                       
     printf(" %s", tname);
     puts("");
     return;
}
/**************************************************************** 
 * Name     : Word                                              * 
 * Descript.: Gives a character of no string and no comment     * 
 *            gives stopping char in former cases               *
 * Input    : none                                              *
 * Output   : none                                              * 
 * Return   : none                                              * 
 * Global   : _Options, _Error_msg                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static char Word( FILE* f)
#else
static char Word( f)
FILE* f;
#endif
{
     int c;
     if (feof(f)) return (char) -1;
     c=fgetc(f); /* end of line */
     switch (c) 
     {
               case '\'': while ((c=fgetc(f))!=-1) if (c=='\'')  break;
                    break;
               case '{': while ((c=fgetc(f))!=-1) if (c=='}')  break;
                    break;                    
               case '(': if ((c=fgetc(f))=='*')
                    {
                      while ((c=fgetc(f))!=-1) 
                         if (c=='*') 
                              if ((c=fgetc(f))==')') break;
                    }
				else 
				{ /* restore c */
					ungetc(c,f);
					c ='(';
				}
                    break;                    
               case '$':  /* read $off-$on */
				{
				int cf,cff, co =fgetc(f);
				if ((co=='o') || (co == 'O'))
                    {
					cf = fgetc(f);
					if ((cf=='f') || (cf == 'F'))
					{
					 cff = fgetc(f);
					 if ((cff=='f') || (cff == 'F'))
					 {
                      		while ((c=fgetc(f))!=-1) 
                         		if (c=='$') 
							{
                              		c=fgetc(f);
                              		if ((c=='o')||(c=='O'))
								{
									c = fgetc(f);
                              			if ((c=='n')||(c=='N')) break;
								}
							}
					 }
					 else
					 {
						ungetc(cff,f);ungetc(cf,f); ungetc(co,f);
					 }
					}
					else
					{
						ungetc(cf,f); ungetc(co,f);
					}

                    }
				else ungetc(co,f);
				}
                    break;                    
     }
     return c;
} 
/**************************************************************** 
 * Name     : SearchModules                                     * 
 * Descript.: Searches USE clauses and the module names         * 
 * Input    : none                                              *
 * Output   : none                                              * 
 * Return   : none                                              * 
 * Global   : _Options, _Error_msg                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static void   SearchModules(FILE* f, char** plist, int *size)
#else
static void   SearchModules(f,plist, size)
FILE* f;
char **plist;
int* size;
#endif
{
     char c[2],prev;
     char buffer[BUFFLEN];
	char *glblstr="GLOBAL";
	int i;
     FILE*test;

     *c=' '; c[1]=EOS;
     *buffer=EOS;
     while (! feof(f))
     {
          prev=*c;
          *c=Word(f);     /* don't combine with to upper because msc6 */
          *c=toupper(*c); /* uses trashy macro calls                  */
		if (trace) putchar(*c);
          switch (*c) 
          {
            case '\n' : *c=' ';
                 break;
            case 'U': if (isalnum(prev)) break;
                 *c=Fgetc(f);
                 if (*c!='S') break;
                 *c=Fgetc(f);
                 if (*c!='E') break;
                 *c=Word(f);
                 if (!(*c==')' ||*c==' ' || *c=='}' || *c=='\n' )) break;
                 do
                 {
                    *c=Word(f);
				if (trace) putchar(*c);
                    switch (*c)
                    {
					case ' ':
						/* strlen ("GLOBAL")==6 */
						if ((i=strlen(buffer))==strlen(glblstr))
						 for (;i>0&&(toupper(buffer[i-1])==glblstr[i-1]);
							i--);
						if (i==0) 
						{ 	/* found global , ignore it*/
							*buffer=EOS;
						}
						break;
                         case '}': case')': break;
                         case ',': case ';':
                         if (strlen(buffer)+strlen(*plist)> *size)
                         {
                              char*tmp;
                              *size+=BUFFLEN;
                              if ((tmp=(char*) 
                                 malloc((size_t)((*size)*sizeof(char))))==NULL)
                              {
                                   fprintf(stderr,"No more Memory");
                                   return ;
                              }    
                              else
                              {
                                   strcpy(tmp,*plist);
                                   free(*plist);
                                   *plist=tmp;
                              } 
                         }
                         {
                         	char *tmpname;

                         	int ok=TRUE;
						strcpy(buffer,(tmpname=GetEnvName(buffer)));
						*tmpname=EOS;
                         	if (opt_all==FALSE)
                         	{
						 /* 
						  * check if source of dependency 
						  * module exists
						  */
						 if (debug)
						   printf("## Check dependency  : %s\n",buffer);
                               if ((test=fopen(buffer,"r"))!=NULL) fclose(test);
                               else ok=FALSE; 
                         	}      
                              buffer[strlen(buffer)-2]=EOS;
                         	if (ok==TRUE)
                         	{
						 	if (debug)
							 printf("## Add dependency   : %s to %s\n",
							 buffer,*plist);
                         		strcat(*plist," ");
                         		strcat(*plist,buffer);
                         	}
                         }
                         *buffer=EOS; /* cut buffer */
                         break;
                         
                      default:
                         if (isalnum(*c)||*c=='_')
                         {
                              strcat(buffer,c);
                         }
                         break;   
                     }
                  }   
                  while (*c!=';');     
                  break;
                    
          }
     }
     return ;
}
/**************************************************************** 
 * Name     : GetEnvName                                        * 
 * Descript.: Searches name in the pxsc search structure        * 
 * Input    : filename :name of analysed module                 *
 * Output   : none                                              * 
 * Return   : location and name of input file                   * 
 * Global   : _Options, _Error_msg                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static char* GetEnvName(char* filename)
#else
static char* GetEnvName(filename)
char* filename;
#endif
{
	FILE* file;
	static char name[BUFFLEN];
	static char* pfname;

     strcpy(name,(pfname = BuildFilename("",filename,".p")));     
	/* 
	 * first try: search file in current directory
	 */
/*	printf("1. Search %s\n",name);*/
     file=fopen(name,"r");
	/* 
 	 * second try: search file in p88.env directory
 	 */
    	if (*p88_env != EOS && file == NULL)
	{
		sprintf(name,"%s%s",p88_env,pfname);
		/* printf("2. Search %s\n",name);*/
		file=fopen(name,"r");
    	}		
    	if (*p88_env_home != EOS && file == NULL )
	{
		/* 
 	 	 * third try: search file in $home/p88.env directory
 		 */
		sprintf(name,"%s%s",p88_env_home,pfname);
		/* printf("3. Search %s\n",name);*/
    		file=fopen(name,"r");
	}
	if (file != NULL) fclose(file);
	else strcpy(name,pfname);
	*pfname=EOS;
	return name;
}
/**************************************************************** 
 * Name     : SaveTarget                                        * 
 * Descript.: Saves current target name to avoid double targets * 
 * Input    : name - current target name                        *
 * Output   : none                                              * 
 * Return   : none                                              * 
 * Global   : savelist, savesize                                * 
 **************************************************************** 
 */
#ifdef __STDC__
static void SaveTarget(char* name)
#else
static void SaveTarget(name)
char* name;
#endif
{
	char *tmp;

	if (savelist==NULL) return;
	if (strlen(savelist) + strlen(name) >= savesize)
	{
		savesize += BUFFLEN;
     	if ((tmp = (char*) malloc((size_t)(savesize*sizeof(char))) ) == NULL) 
     	{
			/* no more memory */
			savesize -= BUFFLEN;
		   	return;
     	}
		else
		{
			strcpy(tmp,savelist);
			free(savelist);
			savelist=tmp;
		}
	}
	strcat(savelist, " ");
	strcat(savelist, name);
}

/**************************************************************** 
 * Name     : Sca                                               * 
 * Descript.: Performs source code analysing                    * 
 * Input    : filename :name of analysed module                 *
 * Output   : none                                              * 
 * Return   : none                                              * 
 * Global   : _Options, _Error_msg                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static int Sca(char* filename)
#else
static int Sca(filename)
char* filename;
#endif
{
	static int level=0;
     char *plist, *name;
	char localname[BUFFLEN];
	char tmpname[BUFFLEN];
     FILE* file;
     int res=NO_ERROR;
     int size=2*BUFFLEN;

     level++; 
	strcpy(localname,(name=GetEnvName(filename)));
	*name=EOS;
	name=(char*) localname;

     if (debug) printf("\n## Check target file : %s \n",name);
	if (savelist!= NULL)
	{
		/* 
		 * save target name to list
		 */
		char *tmpname;
		char* found=savelist;
		tmpname=BuildFilename("",name,targetext);
		while ( (found=strstr(found,tmpname))!=NULL)
		{
			if (found==savelist) break;
			if (*(found-1) == ' ') break;
			found += strlen(tmpname);
		}
		if (found != NULL) {*tmpname=EOS;return;}
		else SaveTarget(tmpname);
		*tmpname=EOS;
	}
     if ((file=fopen(name,"r")) == NULL)
	{
          /* file not readable */
		if (debug)
         	 printf("\n#Target file : %s cannot open.\n",name);
     	Out(name, "");
          return(NO_ERROR);
	}
     /* init module's name list */
     if ((plist = (char*) malloc((size_t)(size*sizeof(char))) ) == NULL) 
     {
          return(NO_MEMORY);
     };
     
     /* module names seperated by ' ' */
     strcpy(plist," "); 

     /* search use and concatenate names to plist string */     
     SearchModules(file,&plist, &size);
     
     /* end of file scanning */
     fclose (file);
     
     /* scan module dependency */
     Out(name, plist);
     if (debug)
		printf("\n#Level %d :target list for %s: %s.\n",level,name,plist);
     while (strlen(plist)>2 )
     {
          if ((name=strrchr(plist,' '))==NULL) break;
         	if (debug)
			printf("\n# Level %d :process dependency %s\n",level,name);
          if (name[1]==EOS) break;
          else
          {
		/* check if found module is already in
		 * command line list
		 */
		 if (mod_in_list(&name[1])==0)
		 {
     /*       	puts("");*/
           	res=Sca(&name[1]);
		 }
          } 
          *name=EOS; /* cut string */
     }     

     free ( plist);

     level--; 
     return res;
}
/**************************************************************** 
 * Name     : Makefile                                          * 
 * Descript.: write information needed for a makefile           * 
 * Input    : argc argv like main commandline                   *
 * Output   : none                                              * 
 * Return   : none                                              * 
 * Global   : _Options, _Error_msg                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static void MakeFile(int argc, char **argv)
#else
static void MakeFile(argc, argv)
int argc;
char **argv;
#endif
{
        char buf[29];
        time_t t;
        int i;
	   FILE* test;
        
        t=time(&t);
        strcpy(buf,ctime(&t));
        buf[strlen(buf)-1]=EOS;
        argc--;

        printf("# RCS : $%s$\n","Id");
        puts("####################################################");
        printf("# Description  : Makefile generated from %-10s#\n",argv[0]);
        puts(  "#                Targets:                          #");
        puts(  "#                 ALL    : generates all targets   #");
        puts(  "#                 clean  : removes local targets   #");
        puts(  "#                 clobber: removes all targets     #");
        puts(  "#                All rights reserved !             #");
        printf("# Version      : V%-31s  #\n",version);
        printf("# Date         : %-30s    #\n",&buf[4]);
        if (*p88_env != EOS) 
			printf("# Local p88.env: %-33s #\n",p88_env);
        if (*p88_env_home != EOS) 
			printf("# HOME p88.env : %-33s #\n",p88_env_home);
        if (pxsc_sys != NULL) 
			printf("# PXSC_SYS     : %-33s #\n",pxsc_sys);
        puts("#                                                  #");
        for (i=argc; i>0;i--)
           if (argv[i][0] != '-') 
		 {
        		printf("# Files        : %-33s #\n",argv[i--]);
			break;
		 }
        for (; i>0;i--)
           if (argv[i][0] != '-') printf("#                %-33s #\n",argv[i]);
        puts("####################################################");
	   puts("#");
        puts("# pxsc flags / pxsc manager / clean command / suffixes  ");
	   puts("#");
        puts("PFLAGS=+x +n");
        puts("RM=rm -f");
        puts("RMDOS=ERASE");
        puts("MXSC=mxsc");
	   for (i=3; targetext[i]; i++)
		if (targetext[i]==')') break;
		else putchar(targetext[i]);
        printf("=%s\n", target);
	   puts(".SUFFIXES:");
        puts(".SUFFIXES:");
        printf(".SUFFIXES: .p %s\n",targetext);
        puts("####################################################");
    	   puts("# default targets from command line ");
        puts("####################################################");
        printf("ALL : ");

	   /* check basic modules of pxsc */
        test=fopen("stdmod.p","r");
        isstdmod=(test!=NULL);
        if (isstdmod)
	   {
               printf("stdmod%s ",targetext);
               fclose(test);
	   }
        for (i=argc; i>0;i--)
           if (argv[i][0] != '-')     
           {
               char *sep;
               if ((sep=strrchr(argv[i],'.'))!=NULL) *sep=EOS;

               printf("%s%s ",argv[i],targetext);
           }
        puts("\n####################################################");
	   puts("# default source to target transition");
        puts("####################################################");
        printf(".p%s :\n",targetext);
        puts("\t@$(MXSC) $(PFLAGS) $* ");
	   puts("");
        puts("\n####################################################");
	   puts("# internal module targets ");
        puts("####################################################");
        return;
}
/**************************************************************** 
 * Name     : PostMakeFile                                      * 
 * Descript.: write information needed for the rest of makefile * 
 * Output   : none                                              * 
 * Return   : none                                              * 
 * Global   : _Options, _Error_msg                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static void PostMakeFile()
#else
static void PostMakeFile()
#endif
{
        puts("\n####################################################");
	   puts("# clean all targets ");
        puts("####################################################");
        puts("clean :");
        if (path_sep == UNIX_PATH_SEP) printf("\t$(RM) *%s\n",targetext);
	   else printf("\t$(RMDOS) *%s\n",targetext);
        puts("\nunixclean :");
        printf("\t$(RM) *%s\n",targetext);
        puts("\ndosclean :");
        printf("\t$(RMDOS) *%s\n",targetext);
	   if (savelist!=NULL)
	   {
        	 puts("\n####################################################");
	   	 puts("# removes all targets ");
        	 puts("####################################################");
	      printf("\nclobber :\n\t%s",(path_sep == UNIX_PATH_SEP)? 
					"$(RM)":"$(RMDOS)");
	      printf("%s\n",savelist);
	   }
	   puts("#\n################### eof ############################");
}

/**************************************************************** 
 * Name     : GetP88env                                         * 
 * Descript.: opens p88.env file and sets corresponding string  * 
 * Input    : path - path where p88 should be located           *
 * Output   : modpath - path where modules are located          * 
 * Return   : none                                              * 
 * Global   : _Options, _Error_msg                              * 
 **************************************************************** 
 */
#ifdef __STDC__
static void GetP88env(char *path, char *modpath)
#else
static void GetP88env(path, modpath)
char *path;
char *modpath;
#endif
{
	FILE* p88file;
	char filename[BUFFLEN];
	int lastpos;
	char c;
	int i;

	*modpath=EOS;

	if (path == NULL) return;

	strcpy(filename,path);

	/* possible add of path separator*/
	lastpos =strlen(filename)-1 ;
	if (filename[lastpos] != path_sep) 
	{
		filename[++lastpos]=path_sep;
		filename[++lastpos]=EOS;
	}
	strcat(filename,P88ENV);
	if (debug) printf("# open %s\n",filename);
	if ((p88file=fopen(filename,"r"))==NULL) return;

	while (!feof(p88file))
	{
		if ((c=fgetc(p88file)) == '\n')
		{
			if (feof(p88file)) {*modpath=EOS; break;}
			if ((c=fgetc(p88file)) == 'p')
			{
				if (feof(p88file)) {*modpath=EOS; break;}
				lastpos=(int)fgetc(p88file)-1;
				for (i=0;i<lastpos;i++) modpath[i]=fgetc(p88file);
				modpath[i]=EOS;
				break;
			}
		}
	}
	fclose(p88file);

	return;
}
/*--------------------------------------------------------------*
 *                   main                                       *
 *--------------------------------------------------------------*
 */
#ifdef __STDC__
int main(int argc, char** argv )
#else
int main(argc, argv )
int argc;
char **argv;
#endif
{       int i ,res=NO_ERROR;
	   char* os_path;

        opt_all=FALSE;
        opt_names=FALSE;
	   strcpy(target, TARGETEXT); /* default target */
	
	   /*
	    * determine path separator of host
	    */
	   if ((os_path=getenv(SYSTEM_PATH))==NULL) os_path=getenv(SYSTEM_path);
	   if (os_path!=NULL)
	   {
		char* tmp=os_path;
		while (*tmp) 
			if (*tmp == UNIX_PATH_SEP || *tmp == DOS_PATH_SEP)
			{
				path_sep = *tmp;
				break;
			}	
			else tmp++;
	   }

	   pxsc_sys=getenv(PXSC_SYS);
	   home=getenv(HOME);

	   GetP88env(CURRENTDIR,p88_env);
	   GetP88env(home,p88_env_home);

	   if (debug)
		printf("ENV: home=%s \nsys=%s \npath=%s \n p88=%s \np88home=%s\n",
			(home==NULL)? "failed":home, (pxsc_sys==NULL)? 
			"failed":pxsc_sys,(os_path==NULL)?"failed":os_path,p88_env,
			p88_env_home);
	   /* serach version/date string */
	   for (i=0;rcsid[i] && rcsid[i]!=',';i++);
	   strncpy(version,(char*)&(rcsid[i+2]),VERSIONLEN);
	   version[VERSIONLEN-1]=EOS;
	   for (i=0;i<VERSIONLEN-1-6 && version[i]&& version[i]!='/';i++) ;
	   version[i+6]=EOS;
	   cmdargc=argc; cmdargv=argv;

        if (argc==1)
        {
          printf("%s V%s - print pxsc module dependencies\n",argv[0], version);
          printf("usage:%s [-a] [-n] [-e<ext>] [-obj] [-d|-t] filename\n",argv[0]);
          puts(  "     -a      : consider all (local + non-local) dependencies");
          puts(  "     -n      : print names of modules only ");
          puts(  "     -e<ext> : targets have extension .<ext> (default <ext>=o)");
          puts(  "     -obj    : like -eobj");
          puts(  "     -t,-d   : trace and debug (for internal usage)");
        }
        else
        {
			/* security check */
		   if (*target==' '  || *target ==EOS)
		   {
			puts("\nERROR : Empty target extension is too dangerous !");
			puts("ABORTED!");
		     if (savelist!=NULL) free(savelist);
			exit(MISC_ERROR);
		   }	
             for (i=1 ;i<argc;i++)
             {
                if (*argv[i]=='-')
                        switch(argv[i][1])
                        {
                                case 'a': opt_all=TRUE;
						  break;
                                case 'd': debug=TRUE;
						  break;
                                case 'o': if (strcmp(argv[i],"-obj")==0)
										strcpy(target,"obj");
						  break;
                                case 't': trace=TRUE;
                                break;
                                case 'n': opt_names=TRUE;
						  break;
                                case 'e': 
							strcpy(target,(char*)&(argv[i][2]));
						  break;
                        }
             }
     	   /* init target save list */
     	   if ((savelist = 
		   (char*) malloc((size_t)(savesize*sizeof(char))) ) == NULL) 
     	   {
			fprintf(stderr,"Sorry, I ran out of memory");
         	 	exit(NO_MEMORY);
     	   };
		   *savelist=EOS;

             if (opt_names==FALSE) MakeFile(argc,argv);
             for (i=1 ;i<argc;i++)
                if (*argv[i]!='-') res=Sca(argv[i]);
             if (opt_names==FALSE) 
		   {
			PostMakeFile();
		   }
     }     
	if (savelist!=NULL) free(savelist);
	exit(res);
     return res;
}
/* --- eof --- */
