/*-------------------------------------------------------------------------*/
/* GNU Prolog                                                              */
/*                                                                         */
/* Part  : installation                                                    */
/* File  : cpp_headers.c                                                   */
/* Descr.: General GNU Prolog header file maker                            */
/* Author: Daniel Diaz                                                     */
/*                                                                         */
/* Copyright (C) 1999,2000 Daniel Diaz                                     */
/*                                                                         */
/* GNU Prolog is free software; you can redistribute it and/or modify it   */
/* under the terms of the GNU General Public License as published by the   */
/* Free Software Foundation; either version 2, or any later version.       */
/*                                                                         */
/* GNU Prolog is distributed in the hope that it will be useful, but       */
/* WITHOUT ANY WARRANTY; without even the implied warranty of              */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU        */
/* General Public License for more details.                                */
/*                                                                         */
/* You should have received a copy of the GNU General Public License along */
/* with this program; if not, write to the Free Software Foundation, Inc.  */
/* 59 Temple Place - Suite 330, Boston, MA 02111, USA.                     */
/*-------------------------------------------------------------------------*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>

#define DO_NOT_ADD_COMMENTS
#define REMOVE_COMMENTS
#define REMOVE_BLANK_LINES




/*---------------------------------*/
/* Constants                       */
/*---------------------------------*/

/*---------------------------------*/
/* Type Definitions                */
/*---------------------------------*/

typedef struct
    {
     char *name;
     char *parent;
     int   line;
    }UsedFile;




/*---------------------------------*/
/* Global Variables                */
/*---------------------------------*/

char     **dir;
FILE      *fout;
char       buff[4096];
UsedFile   used[1024];
int        nb_used=0;


/*---------------------------------*/
/* Function Prototypes             */
/*---------------------------------*/

void      Cpp_File              (char *name,int skip_comment);




/*-------------------------------------------------------------------------*/
/* MAIN                                                                    */
/*                                                                         */
/*-------------------------------------------------------------------------*/
int main(int argc,char *argv[])

{
 if (argc<4)
    {
     fprintf(stderr,"Usage cpp_headers in_file.h out_file.h search_dir...\n");
     return 1;
    }
 dir=argv+3;
 if ((fout=fopen(argv[2],"w"))==NULL)
    {
     perror(argv[2]);
     return 1;
    }
 fprintf(fout,"/* %s generated from %s using cpp_headers */\n",
         argv[2],argv[1]);

 Cpp_File(argv[1],0);
 fclose(fout);
 return 0;
}




#define SKIP_SPACE(p)   while(isspace(*p)) p++;

/*-------------------------------------------------------------------------*/
/* CPP_FILE                                                                */
/*                                                                         */
/*-------------------------------------------------------------------------*/
void Cpp_File(char *name,int skip_comment)

{
 char **d;
 int    i;
 FILE *fin;
 char *p,*q;
 int   line=0;
 char  name1[1024];
#ifdef REMOVE_BLANK_LINES
 int   can_be_removed=1;
#endif


 for(d=dir;*d;d++)
    {
     sprintf(buff,"%s/%s",*d,name);
     if ((fin=fopen(buff,"r"))!=NULL)
         break;
    }

 if (*d==NULL)
    {
     fprintf(stderr,"Cannot find the location of %s\n",name);
     exit(1);
    }

 while(fgets(buff,sizeof(buff),fin))
    {
     line++;
     if (skip_comment)
        {
         if (*buff!='/' || buff[1]!='*')
             goto stop_skip_comment;
         p=buff+strlen(buff)-1;
         while(isspace(*p))
             p--;
         if (p[-1]!='*' || *p!='/')
             goto stop_skip_comment;
         continue;

stop_skip_comment:
#ifndef REMOVE_COMMENTS
         skip_comment=0;
#endif
	}


     if (*buff!='#')
         goto reflect_line;

     p=buff+1;
     SKIP_SPACE(p);
     if (strncmp(p,"include",7))
         goto reflect_line;
     p+=7;
     SKIP_SPACE(p);
     if (*p!='"')
         goto reflect_line;
     p++;
     q=p+strlen(p);
     while(*q!='"')
         q--;
     *q='\0';
     strcpy(name1,p);
#ifndef DO_NOT_ADD_COMMENTS
     fprintf(fout,"/* %s:%d includes %s */\n",name,line,name1);
#endif
     for(i=0;i<nb_used;i++)
         if (strcmp(used[i].name,name1)==0)
             break;

     if (i>=nb_used)
        {
         used[nb_used].name=strdup(name1);
         used[nb_used].parent=strdup(name);
         used[nb_used].line=line;
         nb_used++;
         Cpp_File(name1,1);
        }
#ifndef DO_NOT_ADD_COMMENTS
      else
         fprintf(fout,"/* already included by %s:%d */\n",
                 used[i].parent,used[i].line);
#endif

     continue;

reflect_line:
#ifdef REMOVE_BLANK_LINES
     if (can_be_removed)
        {
         p=buff;
         SKIP_SPACE(p);
         if (*p=='\0')
             continue;
        }

     p=buff+strlen(buff)-1;
     while(isspace(*p))
         p--;
     can_be_removed=(*p!='\\');
#endif
     fputs(buff,fout);
    }

 fclose(fin);
}
