/*
 *   This routine handles the PostScript prologs that might
 *   be included through:
 *
 *      - Default
 *      - Use of PostScript fonts
 *      - Specific inclusion through specials, etc.
 *      - Use of graphic specials that require them.
 *
 *   Things are real simple.  We build a linked list of headers to
 *   include.  Then, when the time comes, we simply copy those
 *   headers down.
 */
#include "dvips.h" /* The copyright notice in that file is included too! */
struct header_list *header_head ;
/*
 *   The external routines we use.
 */
extern char *newstring() ;
extern void error() ;
extern void copyfile() ;
extern FILE *search() ;
extern long lastheadermem ;
extern char errbuf[] ;
extern integer fontmem, swmem ;
extern char *infont ;
extern int headersready ;
#ifdef DEBUG
extern integer debug_flag ;
#endif
/*
 *   This more general routine adds a name to a list of unique
 *   names.
 */
int
add_name(s, what)
   char *s ;
   struct header_list **what ;
{
   struct header_list *p, *q ;

   for (p = *what ; p != NULL; p = p->next)
      if (strcmp(p->name, s)==0)
         return 0 ;
   q = (struct header_list *)mymalloc((integer)(sizeof(struct header_list)
                                          + strlen(s))) ;
   q->Hname = infont ;
   q->next = NULL ;
   strcpy(q->name, s) ;
   if (*what == NULL)
      *what = q ;
   else {
      for (p = *what; p->next != NULL; p = p->next) ;
      p->next = q ;
   }
   return 1 ;
}
/*
 *   This function checks the virtual memory usage of a header file.
 *   If we can find a VMusage comment, we use that; otherwise, we use
 *   length of the file.
 */
void checkhmem(s)
char *s ;
{
   FILE *f = search(headerpath, s, READ) ;

   if (f==0) {
      (void)sprintf(errbuf, "! Couldn't find header file %s", s) ;
      error(errbuf) ;
   } else {
      int len, i, j ;
      long mem = -1 ;
      char buf[1024] ;

      len = fread(buf, sizeof(char), 1024, f) ;
      for (i=0; i<len-20; i++)
         if (buf[i]=='%' && strncmp(buf+i, "%%VMusage:", 10)==0) {
            if (sscanf(buf+i+10, "%d %ld", &j, &mem) != 2)
               mem = -1 ;
            break ;
         }
      if (mem == -1) {
         mem = 0 ;
         while (len > 0) {
            mem += len ;
            len = fread(buf, sizeof(char), 1024, f) ;
         }
      }
      if (mem < 0)
         mem = DNFONTCOST ;
      fclose(f) ;
      lastheadermem = mem ;
#ifdef DEBUG
      if (dd(D_HEADER))
         (void)fprintf(stderr, "Adding header file \"%s\" %ld\n",
                                s, mem) ;
#endif
      fontmem -= mem ;
      if (fontmem > 0) /* so we don't count it twice. */
         swmem -= mem ;
   }
}
/*
 *   This routine is responsible for adding a header file.  We also
 *   calculate the VM usage.  If we can find a VMusage comment, we
 *   use that; otherwise, we use the length of the file.
 */
int
add_header(s)
char *s ;
{
   int r ;

   r = add_name(s, &header_head) ;
   if (r) {
      if (headersready == 1) {
         struct header_list *p = header_head ;

         while (p) {
            checkhmem(p->name) ;
            p = p->next ;
         }
         headersready = 2 ;
      } else if (headersready == 2) {
         checkhmem(s) ;
      }
   }
   return r ;
}
/*
 *   This routine runs down a list, returning each in order.
 */
char *
get_name(what)
   struct header_list **what ;
{
   if (what && *what) {
      char *p = (*what)->name ;
      infont = (*what)->Hname ;
      *what =  (*what)->next ;
      return p ;
   } else
      return 0 ;
}
/*
 *   This routine actually sends the headers.
 */
void
send_headers() {
   struct header_list *p = header_head ;
   char *q ;

   while (0 != (q=get_name(&p))) {
#ifdef DEBUG
      if (dd(D_HEADER))
         (void)fprintf(stderr, "Sending header file \"%s\"\n", q) ;
#endif
      copyfile(q) ;
   }
   infont = 0 ;
}
