/* -*- 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, yavuzv@rumms.uni-mannheim.de */ /* $Id: database.c,v 1.45 1997/12/13 16:06:54 volkan Exp $ */ #include "glosstex.h" #include "database.h" #include "error.h" #include "list.h" #include "labels.h" #include <assert.h> #include <string.h> #include <stdio.h> #include <stdlib.h> #include <ctype.h> enum e_pass { PASS_1 = 0, PASS_2 = 1 }; static unsigned int lineno = 0; static void process_file (enum e_pass pass, FILE * infile, char *inname); static void process_line (enum e_pass pass, char *inname, char *line); static void write_line (FILE * outfile, char* inname, char *list, char *label, char *item, char *longform, char *line, char *list_mode, char *pageref_mode, char *page); static int glo_parse_item (char *line, char *label, char *item, char *longform, int *ptr); void read_databases (void) { FILE *dbfile; enum e_pass pass = PASS_1; s_node *filename = databases.root; for (pass = PASS_1; pass <= PASS_2; pass++) { while (filename != 0) { if ((dbfile = fopen (filename->ptr, "r")) == NULL) { error ("database %s", (char *) filename->ptr); } else { printlog (PROGRESS, STDOUT, "(%s ", (char *) filename->ptr); process_file (pass, dbfile, (char *) filename->ptr); printlog (PROGRESS, STDOUT, ")"); } filename = filename->next; } filename = databases.root; } } static void process_file (enum e_pass pass, FILE * dbfile, char *inname) { enum e_state { HEADER, BODY }; int status; char buf[LINESIZE]; enum e_state state = HEADER; char *line = 0; while (fgets (buf, LINESIZE, dbfile) != 0) { if (buf[strlen (buf) - 1] == '\n') lineno++; status = strncmp (buf, "@entry{", 7); if ((state == HEADER) && (status != 0)) { ; /* ignore heading garbage */ } else { state = BODY; if (status == 0) { /* begin new entry */ /* process current entry before starting new entry */ if (line != 0) { process_line (pass, inname, line); free (line); } line = (char *) malloc (strlen (buf) + 1); assert (line != 0); strcpy (line, buf); if (line[strlen (line) - 1] == '\n') line[strlen (line) - 1] = ' '; } else if (strncmp (buf, "%", 1) == 0) { ; /* skip comments */ } else { /* add lines to current entry */ size_t len = strlen (line); /* LINT: null is ok here */ line = (char *) realloc (line, len + strlen (buf) + 1); assert (line != 0); strcpy (&line[len], buf); if (line[strlen (line) - 1] == '\n') line[strlen (line) - 1] = ' '; } } } /* process last pending line in file */ if (line != 0) { process_line (pass, inname, line); free (line); } } static void process_line (enum e_pass pass, char *inname, char *line) { char label[LINESIZE]; char item[LINESIZE]; char longform[LINESIZE]; size_t index; int ptr = 0; s_list_iterator iter; s_list_iterator iter2; s_label *node; s_label *node2; iter.root = labels.root; iter.current = labels.root; iter2.root = labels.root; iter2.current = labels.root; if (glo_parse_item (line, label, item, longform, &ptr) != 0) { printlog (PROGRESS, STDOUT, "x"); printlog (WARNING, LOGFILE, "\n%s:%u parse error: %s", inname, lineno, line); count_gdf_parsing++; return; } /* remove all trailing spaces */ index = strlen (&line[ptr]); index--; while (line[ptr + index] == ' ') { line[ptr + index] = '\0'; index--; } switch (pass) { case PASS_1: /* is there a reference to <label> in any list? */ node = find_label (&iter, FIND_FIRST, label, 0); if (node != 0) { /* explicit reference to <label> found process references to <label> in each <list> */ while (node != 0) { switch ((enum e_label_flag) node->flag) { case UNRESOLVED: write_line (outfile, inname, node->list, label, item, longform, &line[ptr], node->list_mode, node->pageref_mode, node->page); node->flag = RESOLVED; break; case RESOLVED: printlog (PROGRESS, STDOUT, "i"); printlog (INFORMATION, LOGFILE, "\n%s:%u %s already resolved", inname, lineno, label); count_gdf_defined++; break; } node = find_label (&iter, FIND_NEXT, label, 0); } } break; case PASS_2: /* now look for wildcard in any list */ node = find_label (&iter, FIND_FIRST, "*", 0); if (node == 0) { printlog (PROGRESS, STDOUT, "."); printlog (DEBUG, LOGFILE, "\n%s:%u %s@%s(%s) not needed", inname, lineno, label, item, longform); } else { /* check for wildcard in every list */ while (node != 0) { /* wurde <label> in <node->list> schon explicit angefordert? */ if ((node2 = find_label (&iter2, FIND_FIRST, label, node->list)) == 0) { write_line (outfile, inname, node->list, label, item, longform, &line[ptr], node->list_mode, node->pageref_mode, node->page); node->flag = RESOLVED; } node = find_label (&iter, FIND_NEXT, "*", 0); } } break; } } static void write_line (FILE * outfile, char* inname, char *list, char *label, char *item, char *longform, char *line, char *list_mode, char *pageref_mode, char *page) { fprintf (outfile, "\\GlossTeXEntry{%s%s@{%s}{%s}{%s}{%s}{%s}{%s}" "{\\GlossTeXPage{%s}{%s}}|GlossTeXNull}{0}\n", list, label, label, item, longform, line, list, list_mode, pageref_mode, page); printlog (PROGRESS, STDOUT, "o"); printlog (VERBOSE, LOGFILE, "\n%s:%u %s@%s(%s) used *", inname, lineno, label, item, longform); count_gdf_success++; } /* #module GloScan "2-001" *********************************************************************** * * * The software was developed at the Monsanto Company and is provided * * "as-is". Monsanto Company and the auther disclaim all warranties * * on the software, including without limitation, all implied warran- * * ties of merchantabilitiy and fitness. * * * * This software does not contain any technical data or information * * that is proprietary in nature. It may be copied, modified, and * * distributed on a non-profit basis and with the inclusion of this * * notice. * * * *********************************************************************** */ /* this has been slightly modified by volkan yavuz 1996/12/18 */ static int glo_parse_item (char *line, char *label, char *item, char *longform, int *ptr) { int i, brace; char x; /* Copy the label to the output string. */ i = 0; brace = 1; *ptr = 7; while (1) { x = line[(*ptr)++]; if (x == '\0') return 1; if (x == '{') if (line[*ptr - 2] != '\\') brace++; if (x == '}') { if (line[*ptr - 2] != '\\') brace--; if (brace <= 0) break; } if (x == ',') break; label[i++] = x; } label[i] = '\0'; /* Find the beginning of the item string. */ while (isspace (line[*ptr]) != 0) (*ptr)++; /* Copy the item to the output string. */ i = 0; while (brace > 0) { x = line[(*ptr)++]; if (x == '\0') return 1; if (x == '{') if (line[*ptr - 2] != '\\') brace++; if (x == '}') { if (line[*ptr - 2] != '\\') brace--; if (brace <= 0) break; } if (x == ',') break; item[i++] = x; } item[i] = '\0'; /* Check to see if the item is missing. If it is, default to the label. */ if (i == 0) (void) strcpy (item, label); /* FIXME: lint code error */ while (isspace (line[*ptr]) != 0) (*ptr)++; /* Copy the long-form to the output string. */ i = 0; while (brace > 0) { x = line[(*ptr)++]; if (x == '\0') return 1; if (x == '{') if (line[*ptr - 2] != '\\') brace++; if (x == '}') { if (line[*ptr - 2] != '\\') brace--; if (brace <= 0) break; } longform[i++] = x; } longform[i] = '\0'; return 0; /* it's all ok */ }