/* -*- c -*- */

/*
  GlossTeX, a tool for the automatic preparation of glossaries.
  Copyright (C) 1997 Volkan Yavuz

  This program 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
  of the License, or (at your option) any later version.

  This program 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., 675 Mass Ave, Cambridge, MA 02139, USA.

  Volkan Yavuz, [email protected]
*/

/* $Id: labels.c,v 1.29 1997/12/13 16:06:55 volkan Exp $ */

#include "glosstex.h"
#include "labels.h"
#include "list.h"
#include "error.h"
#include <assert.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>

#define KEYWORDSIZE 10          /* \GLX@entry */
#define INPUTWORDSIZE 7         /* \@input */

static int get_label (char buf[],
                     char *label, char *pageref_mode,
                     char *list, char *list_mode, char *page);

int
read_labels (char *inname)
{
 FILE *infile;
 char buf[LINESIZE];
 unsigned int lineno = 0;
 s_list_iterator iter;

 /* don't forget to update "iter" whenever "labels" changes! */
 iter.root = labels.root;
 iter.current = labels.root;

 if ((infile = fopen (inname, "r")) == NULL) {
   error ("input-file %s", inname);
   return 1;
 }
 printlog (PROGRESS, STDOUT, "(%s ", inname);

 while (fgets (buf, LINESIZE, infile) != 0) {
   if (buf[strlen (buf) - 1] == '\n')
     lineno++;

   if ((strncmp (buf, "\\GLX@entry", KEYWORDSIZE)) == 0) {

     s_label *label = (s_label *) malloc (sizeof (s_label));
     s_label *found_label = 0;
     assert (label != 0);

     label->label = (char *) malloc (WORDSIZE + 1);
     assert (label->label != 0);

     label->pageref_mode = (char *) malloc (WORDSIZE + 1);
     assert (label->pageref_mode != 0);

     label->list = (char *) malloc (WORDSIZE + 1);
     assert (label->list != 0);

     label->list_mode = (char *) malloc (WORDSIZE + 1);
     assert (label->list_mode != 0);

     label->page = (char *) malloc (WORDSIZE + 1);
     assert (label->page != 0);

     label->flag = UNRESOLVED;

     if (get_label (&buf[KEYWORDSIZE],
                    label->label, label->pageref_mode,
                    label->list, label->list_mode,
                    label->page) != 0) {
       printlog (PROGRESS, STDOUT, "x");
       printlog (WARNING, LOGFILE, "\n%s:%u parse error: %s",
                 inname, lineno, buf);
       count_label_parsing++;
       continue;
     }
     if ((found_label =
          find_label (&iter, FIND_FIRST, label->label, label->list)) == 0) {
       list_add (&labels, label);
       iter.root = labels.root; /* update iter because labels changed */
       printlog (INFORMATION, LOGFILE, "\n%s:%u %s[%s](%s)%s@%s",
                 inname, lineno,
                 label->label, label->pageref_mode,
                 label->list, label->list_mode, label->page);
       count_label_success++;
       printlog (PROGRESS, STDOUT, "i");
     } else {
       if (((strcmp (found_label->pageref_mode, "n") == 0) &&
            (strcmp (label->pageref_mode, "n") != 0)) ||
           ((strcmp (found_label->list_mode, "n") == 0) &&
            (strcmp (label->list_mode, "n") != 0))) {
         printlog (INFORMATION, LOGFILE,
                   "\n%s:%u %s[%s](%s)%s@%s overrides %s[%s](%s)%s@%s",
                   inname, lineno,
                   label->label, label->pageref_mode,
                   label->list, label->list_mode, label->page,
                   found_label->label, found_label->pageref_mode,
             found_label->list, found_label->list_mode, found_label->page);
         printlog (PROGRESS, STDOUT, "o");
         free (found_label->label);
         free (found_label->pageref_mode);
         free (found_label->list);
         free (found_label->list_mode);
         free (found_label->page);
         found_label->label = label->label;
         found_label->pageref_mode = label->pageref_mode;
         found_label->list = label->list;
         found_label->list_mode = label->list_mode;
         found_label->page = label->page;
         count_label_override++;
         free (label);
       } else {
         printlog (VERBOSE, LOGFILE, "\n%s:%u %s[%s](%s)%s@%s ignored",
                   inname, lineno,
                   label->label, label->pageref_mode,
                   label->list, label->list_mode, label->page);
         printlog (PROGRESS, STDOUT, ".");
         count_label_defined++;

         free (label->label);
         free (label->pageref_mode);
         free (label->list);
         free (label->list_mode);
         free (label->page);
         free (label);
       }
     }

   } else if ((strncmp (buf, "\\@input", INPUTWORDSIZE)) == 0) {
     char *new_file_name = (char *) malloc (WORDSIZE + 1);
     assert (new_file_name != 0);

     if (sscanf ((char *) (&buf[INPUTWORDSIZE]),
                 "{%128[^}]}\n", new_file_name) == 1)
       read_labels (new_file_name);
   }
 }
 printlog (PROGRESS, STDOUT, ")");

 return 0;
}

s_label *
find_label (s_list_iterator * iterator, enum e_find_mode find_mode,
           char *label, char *list)
{
 if (find_mode == FIND_FIRST)
   iterator->current = iterator->root;
 else
   iterator->current != 0 ? iterator->current = iterator->current->next : 0;

 while (iterator->current != 0) {
   if ((strcmp (((s_label *) (iterator->current->ptr))->label, label) == 0) &&
       ((list == 0) ? 1 == 1 :
        (strcmp (((s_label *) (iterator->current->ptr))->list, list) == 0)))
     return ((s_label *) (iterator->current->ptr));
   iterator->current = iterator->current->next;
 }
 return 0;
}

unsigned int
show_unresolved_labels (s_list list, FILE * file)
{
 unsigned int i = 0;
 s_node *p = list.root;
 while (p != 0) {
   if ((((s_label *) (p->ptr))->flag) == UNRESOLVED) {
     printlog (WARNING, STDOUT | LOGFILE, "\n%s[%s](%s)%s@%s unresolved",
               ((s_label *) (p->ptr))->label,
               ((s_label *) (p->ptr))->pageref_mode,
               ((s_label *) (p->ptr))->list,
               ((s_label *) (p->ptr))->list_mode,
               ((s_label *) (p->ptr))->page);
     ++i;
   }
   p = p->next;
 }
 return i;
}

static int
get_label (char buf[],
          char *label, char *pageref_mode,
          char *list, char *list_mode, char *page)
{
 int i = sscanf ((char *) (buf),
                 "{%128[^}]}{%128[^}]}{%128[^}]}{%128[^}]}{%128[^}]}\n",
                 label, pageref_mode, list, list_mode, page);

 return i != 5 ? 1 : 0;
}