/*********************************************/
/*                                           */
/*  File: chtmlprocs.c                       */
/*  Purpose: c2html lex and yacc procedures  */
/*                                           */
/*  Author: Sfiligoi Igor                    */
/*                                           */
/*  Created      : 12.02.1997                */
/*  Last modified: 15.04.1997                */
/*                                           */
/*********************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>

#include "chtmlprocs.h"


/* allocate space and convert string to HTML read form */
/* count the new_lines using Curr_Line */
/* set the color of the comments */
char *str2htmlmem(char *str)
{
 char *dest;
 int i,j,newlen,len,newmaxlen;

 /* write out the token (for test only) */
 if (doprint)
   fprintf(stderr,"%s|",str);


 /* convert to HTML read form */
 len = strlen(str);
 newmaxlen = 5*len; 			/* worst case */
 dest = (char *) malloc(newmaxlen+1);

 j=0;
 for (i=0; i<len;i++)
	{
	 switch (str[i])
		{
		case '&':
			dest[j++]='&';
			dest[j++]='a';
			dest[j++]='m';
			dest[j++]='p';
			dest[j++]=';';
			break;
		case '<':
			dest[j++]='&';
			dest[j++]='l';
			dest[j++]='t';
			dest[j++]=';';
			break;
		case '>':
			dest[j++]='&';
			dest[j++]='g';
			dest[j++]='t';
			dest[j++]=';';
			break;
		case '\n': /* new line */
			dest[j++]='\n';
			 ++Curr_Line;
			break;
		default:
			dest[j++]=str[i];
			break;
		}
	}
 dest[j]=0;
 newlen=j;

 if ((strstr(dest,"/*")!=NULL)||(strstr(dest,"\\\n")!=NULL))
	{ /* a comment or a blankend is present => set the color from that point on */
	 char *cmt;

	 /* 38 char long TAG */
	 newlen+=38;

	 if (newlen>=newmaxlen)
		{ /* alloc space for TAG */
		 char *temp;

		 temp = dest;
		 dest = (char *) malloc(newlen+1);
		 strcpy(dest,temp);
		 free(temp);
		}

	 /* make space for TAG */
	 {/* find if it is first a comment of a blankend */
	  char *tmp1,*tmp2;

	  tmp1=strstr(dest,"/*");
	  tmp2=strstr(dest,"\\\n");

	  if (((tmp1!=NULL)&&(tmp1<tmp2))||(tmp2==NULL))
		cmt=tmp1;
	  else
		cmt=tmp2;
	 }

	 memmove(&(cmt[26]),cmt,strlen(cmt)+1);

	 /* insert start TAG */
	 memcpy((void *) cmt,(void *) "<FONT COLOR=\"#6080C0\"><EM>",26);
	 /* insert end TAG */
	 strcpy(&(dest[newlen-12]),"</EM></FONT>");
	}

 return dest;
}

/* allocate space and convert string to HTML read form */
/* count the new_lines using Curr_Line */
/* set the color of the comments */
/* used when starting with a string */
void str2htmlmem_string(char *str,
			STRREC *strrec) /* OUT */
{
 char *dest;
 int i,j,newlen,len,newmaxlen;
 int eostr;	/* end of string */

 /* write out the token (for test only) */
 if (doprint)
   fprintf(stderr,"%s|",str);


 len = strlen(str);
       
 if (str[0]=='<')
   {
     /* find end of string */
     {
       int i;

       eostr=0;
       for (i=1;i<len; i++)
	 {
	   if (str[i]=='>')
	     { /* found EOSTR */
	       eostr=i;
	       break;  /* exit from the for */
		}
	 }
       
     }
     
     /* first char */
     strrec->pred = (char *) malloc(5);
     strcpy(strrec->pred,"&lt;");
   }
 else if (str[0]=='\"')
        {
	  /* find end of string */
	  {
	    int i;
	    
	    eostr=0;
	    for (i=1;i<len; i++)
	      {
		if (str[i]=='\\')
		  i++; /* do not consider the following char */
		else if (str[i]=='\"')
		  { /* found EOSTR */
		    eostr=i;
		    break;  /* exit from the for */
		  }
	      }
	    
	  }
	  
	  /* first char */
	  strrec->pred = (char *) malloc(2);
	  strrec->pred[0] = '\"';
	  strrec->pred[1] = 0;
       }
      else
	{
	  /* find end of string */
	  {
	    int i;
	    
	    eostr=0;
	    for (i=1;i<len; i++)
	      {
		if (str[i]=='\\')
		  i++; /* do not consider the following char */
		else if (str[i]=='\'')
		  { /* found EOSTR */
		    eostr=i;
		    break;  /* exit from the for */
		  }
	      }
       
	  }
     
     /* first char */
     strrec->pred = (char *) malloc(2);
     strrec->pred[0] = '\'';
     strrec->pred[1] = 0;
   }

 /* name of the string to be preserved */
 strrec->name = (char *) calloc(1,eostr);
 strncpy(strrec->name,&(str[1]),eostr-1);

 /* string */
 strrec->mid = (char *) malloc((eostr-1)*5+1); /* worst case */
 
 { /* convert to HTML read form */
  char *src = &(str[1]);
  char *dest = strrec->mid;

  len = eostr-1;

  j=0;
  for (i=0; i<len;i++)
    {
      switch (src[i])
	{
	case '&':
	  dest[j++]='&';
	  dest[j++]='a';
	  dest[j++]='m';
	  dest[j++]='p';
	  dest[j++]=';';
	  break;
	case '<':
	  dest[j++]='&';
	  dest[j++]='l';
	  dest[j++]='t';
	  dest[j++]=';';
	  break;
	case '>':
	  dest[j++]='&';
	  dest[j++]='g';
	  dest[j++]='t';
	  dest[j++]=';';
	  break;
	case '\n': /* new line */
	  dest[j++]='\n';
	  ++Curr_Line;
	  break;
	default:
	  dest[j++]=src[i];
	  break;
	}
    }
  dest[j]=0;
 }

 /* tail */
 strrec->succ = (char *) malloc((strlen(str)-eostr)*5+39); /* worst case */
 strcpy(strrec->succ,&(str[eostr]));
 { /* convert to HTML read form */
  char *src = &(str[eostr]);
  char *dest = strrec->succ;

  len = strlen(str)-eostr;

  j=0;
  for (i=0; i<len;i++)
    {
      switch (src[i])
	{
	case '&':
	  dest[j++]='&';
	  dest[j++]='a';
	  dest[j++]='m';
	  dest[j++]='p';
	  dest[j++]=';';
	  break;
	case '<':
	  dest[j++]='&';
	  dest[j++]='l';
	  dest[j++]='t';
	  dest[j++]=';';
	  break;
	case '>':
	  dest[j++]='&';
	  dest[j++]='g';
	  dest[j++]='t';
	  dest[j++]=';';
	  break;
	case '\n': /* new line */
	  dest[j++]='\n';
	  ++Curr_Line;
	  break;
	default:
	  dest[j++]=src[i];
	  break;
	}
    }
  dest[j]=0;
  newlen = j;

  if ((strstr(&(dest[1]),"/*")!=NULL)||(strstr(&(dest[1]),"\\\n")!=NULL))
	{ /* a comment or a blankend is present => set the color from that point on */
	 char *cmt;

	 /* 38 char long TAG */
	 newlen+=38;

	 /* make space for TAG */
	 {/* find if it is first a comment of a blankend */
	  char *tmp1,*tmp2;

	  tmp1=strstr(&(dest[1]),"/*");
	  tmp2=strstr(&(dest[1]),"\\\n");

	  if (((tmp1!=NULL)&&(tmp1<tmp2))||(tmp2==NULL))
		cmt=tmp1;
	  else
		cmt=tmp2;
	 }

	 memmove(&(cmt[26]),cmt,strlen(cmt)+1);

	 /* insert start TAG */
	 memcpy((void *) cmt,(void *) "<FONT COLOR=\"#6080C0\"><EM>",26);
	 /* insert end TAG */
	 strcpy(&(dest[newlen-12]),"</EM></FONT>");
	}
 }
}

/* extract idf from source and place other in else */
/* allocate space for idf and else */
void extractidf(char *source,	/* IN */
		char **idf,	/* IN */
		char **succ)	/* OUT */
{
 int i,len;

 /* find the end of the identifier */
 for (	i=0;
 	((source[i]>='0')&&(source[i]<='9'))||
	((source[i]>='a')&&(source[i]<='z'))||
	((source[i]>='A')&&(source[i]<='Z'))||
	(source[i]=='_');
	i++);

 (*idf) = (char *) malloc(i+1);
 strncpy((*idf),source,i);
 (*idf)[i]=0;

 len = strlen(source);
 (*succ) = (char *) malloc(len-i+1);
 strcpy((*succ),&(source[i]));
}


/* search for specified file in the path */
/* returns the *.chi file */
char *find_include(char *strname)
{
 char *localpath;
 char *pathel;
 char actdir[4096];
 char tmpdir[4096];


 localpath = (char *) malloc(strlen(path)+1);
 strcpy(localpath,path);

 for (pathel = strtok(localpath,":");
      pathel!=NULL;
      pathel = strtok(NULL,":"))
   {
     char *filename;
     FILE *afile;

     getcwd(actdir,4096);

     if (chdir(pathel)!=0)
       {
	 fprintf(stderr,"WARNING: %s not a valid dir!\n",pathel);
	 continue;
       }
     getcwd(tmpdir,4096);

     chdir(actdir);

     filename = (char *) malloc(strlen(tmpdir)+strlen(strname)+16);
     strcpy(filename,tmpdir);
     if (filename[strlen(tmpdir)-1]!='/')
       strcat(filename,"/");
     strcat(filename,strname);
     filename[strlen(filename)-2]='_'; /* strname should be *.h -> *_h */
     strcat(filename,".chi");

     afile = fopen(filename,"r");
     if (afile!=NULL)
       { /* found */
	 fclose(afile);

	 free(localpath);
	 return filename;
       }

     free(filename);
   }

 free(localpath);
 return NULL;
}

/* convert non-normalized absolute or relative dir in a normalized relative dir */
char *normalize_dir(char *absdir,		/* Path to be normalized */
		    char *targetdir)		/* Directory where the result path will be used */
{
 char *orgdir;
 char *actdir;
 char *tmpdir;
 char *adir;
 int diri;

 if ((((absdir[0]=='h')||(absdir[0]=='H'))&&
      ((absdir[1]=='t')||(absdir[1]=='T'))&&
      ((absdir[2]=='t')||(absdir[2]=='T'))&&
      ((absdir[3]=='p')||(absdir[3]=='P'))&&
      (absdir[4]==':'))
     ||
     ((absdir[0]=='/')&&(absdir[1]=='/')))
   { /* absolute http path, do nothing */
     adir = (char *) malloc(strlen(absdir)+1);
     strcpy(adir,absdir);

     return adir;
   }


 orgdir = (char *) malloc(4096);
 actdir = (char *) malloc(4096);
 tmpdir = (char *) malloc(4096);

 /* find the absolute address */
 getcwd(orgdir,4096);
 
 {
   int filelen;

   /* find the logical end of the file */
   for (filelen=0; 
	(absdir[filelen]!=0)&&(absdir[filelen]!='#')&&(absdir[filelen]!='?'); 
	filelen++);

   for (diri=filelen; (diri>=0)&&(absdir[diri]!='/'); diri--);
 }

 if (diri<0)
   { /* cur. dir */
     strcpy(tmpdir,".");
   }
 else
   { /* ch. dir */
     strncpy(tmpdir,absdir,diri+1);
     tmpdir[diri+1]=0;
   }

 if (chdir(tmpdir)!=0)
   {
     fprintf(stderr,"WARNING: absdir %s not a valid dir!\n",tmpdir);
   }
 else
   {
     getcwd(tmpdir,4096);
   }

 chdir(orgdir);

 /* transform in relative address */
 if (chdir(targetdir)!=0)
   {
     fprintf(stderr,"WARNING: targetdir %s not a valid dir!\n",targetdir);
   }
 
 getcwd(actdir,4096);

 chdir(orgdir);

 {
   int eqi,i;
   char intdir[4096];

   strcpy(intdir,tmpdir);

   for (eqi=0; (actdir[eqi]!=0)&&(actdir[eqi]==intdir[eqi]); eqi++);

   if (actdir[eqi]==0)
     { /* actdir[eqi]==0 */
       if (intdir[eqi]==0)
	 { /* current dir */
	   strcpy(tmpdir,"");
	 }
       else
	 { /* intdir is a child of act dir */
	   strcpy(tmpdir,&(intdir[eqi+1]));
	 }
     }
   else
     { /* actdir[eqi]!=0 */
       if (intdir[eqi]==0)
	 { /* intdir is a parent */
	   strcpy(tmpdir,"..");
	   for (i=eqi+1; actdir[i]!=0;i++)
	     if (actdir[i]=='/')
	       strcat(tmpdir,"/..");
	 }
       else
	 {
	   for (;actdir[eqi]!='/'; eqi--); /* position to the last / */

	   strcpy(tmpdir,"");
	   for (i=eqi; actdir[i]!=0;i++)
	     if (actdir[i]=='/')
	       strcat(tmpdir,"../");

	   strcat(tmpdir,&(intdir[eqi+1]));
	 }
     }
 }

 /* create the complete file name */
 adir = (char *) malloc(strlen(tmpdir)+strlen(absdir)-diri+3);
 strcpy(adir,tmpdir);
 if ((strlen(adir)>0)&&(adir[strlen(adir)-1]!='/'))
   strcat(adir,"/");
 strcat(adir,&(absdir[diri+1]));

 free(tmpdir);
 free(actdir);
 free(orgdir);

 return adir;
}