Back to index

tetex-bin  3.0
Defines | Functions | Variables
scanid.c File Reference
#include "mkind.h"
#include "scanid.h"

Go to the source code of this file.

Defines

#define CHECK_LENGTH()   if (i > len_field) goto FIELD_OVERFLOW

Functions

char *strchr ARGS ((const char *s, int c))
static void flush_to_eol ARGS ((void))
static void make_string ARGS ((char **ppstr, int n))
static int scan_alpha_lower ARGS ((char *no, int *npg, short *count))
static int scan_field ARGS ((int *n, char field[], int len_field, int ck_level, int ck_encap, int ck_actual))
static int scan_key ARGS ((struct KFIELD *data))
static int scan_no ARGS ((char *no, int *npg, short *count, short *type))
static void search_quote ARGS ((char **sort_key, char **actual_key))
void scan_idx (VOID_ARG)
static void flush_to_eol (VOID_ARG)
static int make_key (VOID_ARG)
static void make_string (char **ppstr, int n)
static int scan_key (FIELD_PTR data)
static int scan_field (int *n, field, int len_field, int ck_level, int ck_encap, int ck_actual)
int group_type (char *str)
static int scan_no (no, npg, short *count, short *type)
static int scan_arabic (no, npg, short *count)
static int scan_roman_lower (no, npg, short *count)
static int scan_roman_upper (no, npg, short *count)
static int scan_alpha_lower (no, npg, short *count)
static int scan_alpha_upper (no, npg, short *count)
static int scan_arg1 (VOID_ARG)
static int scan_arg2 (VOID_ARG)
static void search_quote (char **sort_key, char **actual_key)

Variables

int idx_lc
int idx_tc
int idx_ec
int idx_dc
static int first_entry = TRUE
static int comp_len
static char key [ARGUMENT_MAX]
static char no [NUMBER_MAX]
NODE_PTR head
NODE_PTR tail

Define Documentation

#define CHECK_LENGTH ( )    if (i > len_field) goto FIELD_OVERFLOW

Definition at line 31 of file scanid.c.


Function Documentation

char* strchr ARGS ( (const char *s, int c )
static void flush_to_eol ARGS ( (void ) [static]
static void make_string ARGS ( (char **ppstr, int n ) [static]
static int scan_roman_upper ARGS ( (char *no, int *npg, short *count ) [static]
static int scan_field ARGS ( (int *n, char field[], int len_field, int ck_level, int ck_encap, int ck_actual)  ) [static]
static int scan_key ARGS ( (struct KFIELD *data ) [static]
static int scan_no ARGS ( (char *no, int *npg, short *count, short *type ) [static]
static void search_quote ARGS ( (char **sort_key, char **actual_key)  ) [static]
static void flush_to_eol ( VOID_ARG  ) [static]

Definition at line 165 of file scanid.c.

{      /* flush to end-of-line, or end-of-file, whichever is first */
    int a;

    while ( ((a = GET_CHAR(idx_fp)) != LFD) && (a != EOF) )
       /* NO-OP */;
}

Here is the caller graph for this function:

int group_type ( char *  str)

Definition at line 429 of file scanid.c.

{
    int     i = 0;

    while ((str[i] != NUL) && ISDIGIT(str[i]))
       i++;

    if (str[i] == NUL) {
       sscanf(str, "%d", &i);
       return (i);
    } else if (ISSYMBOL(str[0]))
       return (SYMBOL);
    else
       return (ALPHA);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int make_key ( VOID_ARG  ) [static]

Definition at line 174 of file scanid.c.

{
    NODE_PTR ptr;
    int     i;
    static size_t len = sizeof(NODE);

    /* allocate and initialize a node */

#ifdef DEBUG
       totmem += len;
       (void)fprintf(stderr,"make_key(): malloc(%d)\ttotmem = %ld\n",
           len,totmem);
#endif /* DEBUG */

    if ((ptr = (NODE_PTR) malloc(len)) == NULL)
       fprintf (stderr, "Not enough core...abort.\n");

    bzero(ptr, len);
    /* Initialize dangling pointers
     * Note: it would be a nice work to redesign the code to use NULL for
     * comparision ... nevertheless, using local "" in a global environment
     * isn't the hit because the allocation of the keys with german_sort may
     * crash with a nitpicking memory allocation (Linux, libc-5.4.46).
     * <werner@suse.de>
     */
    for (i = 0; i < FIELD_MAX; i++)
    {
       make_string(&(ptr->data.sf[i]), 1);
       make_string(&(ptr->data.af[i]), 1);
    }
    make_string(&(ptr->data.encap), 1);
    ptr->data.lpg[0] = NUL;
    ptr->data.count = 0;
    ptr->data.type = EMPTY;

    /* process index key */
    if (!scan_key(&(ptr->data)))
       return (FALSE);

    /* determine group type */
    ptr->data.group = group_type(ptr->data.sf[0]);

    /* process page number */
    strcpy(ptr->data.lpg, no);
    if (!scan_no(no, ptr->data.npg, &(ptr->data.count), &(ptr->data.type)))
       return (FALSE);

    if (first_entry) {
       head = tail = ptr;
       first_entry = FALSE;
    } else {
       tail->next = ptr;
       tail = ptr;
    }
    ptr->data.lc = idx_lc;
    ptr->data.fn = idx_fn;
    tail->next = NULL;

    return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void make_string ( char **  ppstr,
int  n 
) [static]

Definition at line 239 of file scanid.c.

{
    if (*ppstr)                    /* Do NOT leaking here, <werner@suse.de> */
       free(*ppstr);

    /* Note: we have always allocate the correct amount of memory to
     * avoid chrashes because the string length of the actual and
     * sort key may differ at german_sort and strange indexentries
     * <werner@suse.de>
     */
    (*ppstr) = (char*)malloc(n);
    if (!(*ppstr))
       fprintf (stderr, "Not enough core...abort.\n");
    bzero(*ppstr, n);              /* Always zero anything, <werner@suse.de> */
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_alpha_lower ( no  ,
npg  ,
short count 
) [static]

Definition at line 633 of file scanid.c.

{
    short   i;

    ENTER(ALPHA_VAL(no[0]) + page_offset[ALPL]);

    i = 1;
    if (IS_COMPOSITOR)
       return (scan_no(&no[comp_len + 1], npg, count, &i));
    else
       return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_alpha_upper ( no  ,
npg  ,
short count 
) [static]

Definition at line 655 of file scanid.c.

{
    short   i;

    ENTER(ALPHA_VAL(no[0]) + page_offset[ALPU]);

    i = 1;
    if (IS_COMPOSITOR)
       return (scan_no(&no[comp_len + 1], npg, count, &i));
    else
       return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_arabic ( no  ,
npg  ,
short count 
) [static]

Definition at line 495 of file scanid.c.

{
    short   i = 0;
    char    str[ARABIC_MAX+1];            /* space for trailing NUL */

    while ((no[i] != NUL) && (i <= ARABIC_MAX) && (!IS_COMPOSITOR)) {
       if (isdigit(no[i])) {
           str[i] = no[i];
           i++;
       } else {
IDX_ERROR2("Illegal Arabic digit: position %d in %s.\n", i + 1, no);
           return (FALSE);
       }
    }
    if (i > ARABIC_MAX) {
       IDX_ERROR2("Arabic page number %s too big (max %d digits).\n",
                 no, ARABIC_MAX);
       return (FALSE);
    }
    str[i] = NUL;

    ENTER(strtoint(str) + page_offset[ARAB]);

    if (IS_COMPOSITOR)
       return (scan_no(&no[i + comp_len], npg, count, &i));
    else
       return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_arg1 ( VOID_ARG  ) [static]

Definition at line 674 of file scanid.c.

{
    int     i = 0;
    int     n = 0;                 /* delimiter count */
    int     a;

    if (compress_blanks)
       while (((a = GET_CHAR(idx_fp)) == SPC) || (a == TAB));
    else
       a = GET_CHAR(idx_fp);

    while ((i < ARGUMENT_MAX) && (a != EOF))
    {
       if ((a == idx_quote) || (a == idx_escape))
       {                           /* take next character literally */
           key[i++] = (char) a;    /* but preserve quote or escape */
           a = GET_CHAR(idx_fp);
           key[i++] = (char) a;    /* save literal character */
       }
       else if (a == idx_aopen)
       {             /* opening delimiters within the argument list */
           key[i++] = (char) a;
           n++;
       }
       else if (a == idx_aclose)
       {
           if (n == 0)                    /* end of argument */
           {
              if (compress_blanks && key[i - 1] == SPC)
                  key[i - 1] = NUL;
              else
                  key[i] = NUL;
              return (TRUE);
           }
           else                    /* nested delimiters */
           {
              key[i++] = (char) a;
              n--;
           }
       }
       else
       {
           switch (a)
           {
           case LFD:
              idx_lc++;
              IDX_ERROR("Incomplete first argument (premature LFD).\n", "");
              return (FALSE);
           case TAB:
           case SPC:
              /* compress successive SPC's to one SPC */
              if (compress_blanks)
              {
                  if ((i > 0) && (key[i - 1] != SPC) && (key[i - 1] != TAB))
                     key[i++] = SPC;
                  break;
              }
           default:
              key[i++] = (char) a;
              break;
           }
       }
       a = GET_CHAR(idx_fp);
    }

    flush_to_eol();                /* Skip to end of line */
    idx_lc++;
    IDX_ERROR("First argument too long (max %d).\n", ARGUMENT_MAX);
    return (FALSE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_arg2 ( VOID_ARG  ) [static]

Definition at line 747 of file scanid.c.

{
    int     i = 0;
    int     a;
    int     hit_blank = FALSE;

    while (((a = GET_CHAR(idx_fp)) == SPC) || (a == TAB));

    while (i < NUMBER_MAX) {
       if (a == idx_aclose) {
           no[i] = NUL;
           return (TRUE);
       } else
           switch (a) {
           case LFD:
              idx_lc++;
IDX_ERROR("Incomplete second argument (premature LFD).\n", "");
              return (FALSE);
           case TAB:
           case SPC:
              hit_blank = TRUE;
              break;
           default:
              if (hit_blank) {
                  flush_to_eol();  /* Skip to end of line */
                  idx_lc++;
IDX_ERROR("Illegal space within numerals in second argument.\n", "");
                  return (FALSE);
              }
              no[i++] = (char) a;
              break;
           }
       a = GET_CHAR(idx_fp);
    }
    flush_to_eol();  /* Skip to end of line */
    idx_lc++;
    IDX_ERROR("Second argument too long (max %d).\n", NUMBER_MAX);
    return (FALSE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_field ( int n,
field  ,
int  len_field,
int  ck_level,
int  ck_encap,
int  ck_actual 
) [static]

Definition at line 347 of file scanid.c.

{
    int     i = 0;
    int     nbsh;                  /* backslash count */

    if (compress_blanks && ((key[*n] == SPC) || (key[*n] == TAB)))
       ++* n;

    while (TRUE) {
       nbsh = 0;
       while (key[*n] == idx_escape)
       {
           nbsh++;
           field[i++] = key[*n];
           CHECK_LENGTH();
           ++*n;
       }

       if (key[*n] == idx_quote)
       {
           if (nbsh % 2 == 0)
              field[i++] = key[++*n];
           else
              field[i++] = key[*n];
           CHECK_LENGTH();
       }
       else if ((ck_level && (key[*n] == idx_level)) ||
               (ck_encap && (key[*n] == idx_encap)) ||
               (ck_actual && (key[*n] == idx_actual)) ||
               (key[*n] == NUL))
       {
           if ((i > 0) && compress_blanks && (field[i - 1] == SPC))
              field[i - 1] = NUL;
           else
              field[i] = NUL;
           return (TRUE);
       } else {
           field[i++] = key[*n];
           CHECK_LENGTH();
           if ((!ck_level) && (key[*n] == idx_level)) {
              IDX_ERROR2("Extra `%c' at position %d of first argument.\n",
                        idx_level, *n + 1);
              return (FALSE);
           } else if ((!ck_encap) && (key[*n] == idx_encap)) {
              IDX_ERROR2("Extra `%c' at position %d of first argument.\n",
                        idx_encap, *n + 1);
              return (FALSE);
           } else if ((!ck_actual) && (key[*n] == idx_actual)) {
              IDX_ERROR2("Extra `%c' at position %d of first argument.\n",
                        idx_actual, *n + 1);
              return (FALSE);
           }
       }
       /* check if max field length is reached */
       if (i > len_field)
       {
       FIELD_OVERFLOW:
           if (!ck_encap) {
              IDX_ERROR("Encapsulator of page number too long (max. %d).\n",
                       len_field);
           } else if (ck_actual) {
              IDX_ERROR("Index sort key too long (max. %d).\n", len_field);
           } else {
              IDX_ERROR("Text of key entry too long (max. %d).\n", len_field);
           }
           return (FALSE);
       }
       ++*n;
    }
}

Here is the caller graph for this function:

Definition at line 66 of file scanid.c.

{
    char    keyword[ARRAY_MAX];
    int     c;
    int     i = 0;
    int     not_eof = TRUE;
    int     arg_count = -1;

    MESSAGE("Scanning input file %s...", idx_fn);
    idx_lc = idx_tc = idx_ec = idx_dc = 0;
    comp_len = strlen(page_comp);
    while (not_eof) {
       switch (c = GET_CHAR(idx_fp)) {
       case EOF:
           if (arg_count == 2) {
              idx_lc++;
              if (make_key())
                  IDX_DOT(DOT_MAX);
              arg_count = -1;
           } else
              not_eof = FALSE;
           break;

       case LFD:
           idx_lc++;
           if (arg_count == 2) {
              if (make_key())
                  IDX_DOT(DOT_MAX);
              arg_count = -1;
           } else if (arg_count > -1) {
              IDX_ERROR("Missing arguments -- need two (premature LFD).\n",
                       NULL);
              arg_count = -1;
           }
       case TAB:
       case SPC:
           break;

       default:
           switch (arg_count) {
           case -1:
              i = 0;
              keyword[i++] = (char) c;
              arg_count++;
              idx_tc++;
              break;
           case 0:
              if (c == idx_aopen) {
                  arg_count++;
                  keyword[i] = NUL;
                  if (STREQ(keyword, idx_keyword)) {
                     if (!scan_arg1()) {
                         arg_count = -1;
                     }
                  } else {
                     IDX_SKIPLINE;
                     IDX_ERROR("Unknown index keyword %s.\n", keyword);
                  }
              } else {
                  if (i < ARRAY_MAX)
                     keyword[i++] = (char) c;
                  else {
                     IDX_SKIPLINE;
                     IDX_ERROR2("Index keyword %s too long (max %d).\n",
                               keyword, ARRAY_MAX);
                  }
              }
              break;
           case 1:
              if (c == idx_aopen) {
                  arg_count++;
                  if (!scan_arg2()) {
                     arg_count = -1;
                  }
              } else {
                  IDX_SKIPLINE;
IDX_ERROR(
"No opening delimiter for second argument (illegal character `%c').\n", c);
              }
              break;
           case 2:
              IDX_SKIPLINE;
IDX_ERROR(
"No closing delimiter for second argument (illegal character `%c').\n", c);
              break;
           }
           break;
       }
    }

    /* fixup the total counts */
    idx_tt += idx_tc;
    idx_et += idx_ec;

    DONE(idx_tc - idx_ec, "entries accepted", idx_ec, "rejected");
    CLOSE(idx_fp);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_key ( FIELD_PTR  data) [static]

Definition at line 262 of file scanid.c.

{
    int     i = 0;                 /* current level */
    int     n = 0;                 /* index to the key[] array */
    int     second_round = FALSE;
    int     last = FIELD_MAX - 1;
    size_t  len;

    while (TRUE) {
       if (key[n] == NUL)
           break;
       len = strlen(key);
       if (key[n] == idx_encap)
       {
           n++;
           make_string(&(data->encap), len + 1);
           if (scan_field(&n, data->encap, len, FALSE, FALSE, FALSE))
              break;
           else
              return (FALSE);
       }
       if (key[n] == idx_actual) {
           n++;

           make_string(&(data->af[i]), len + 1);
           if (i == last)
           {
              if (!scan_field(&n, data->af[i], len, FALSE, TRUE, FALSE))
                  return (FALSE);
           }
           else
           {
              if (!scan_field(&n, data->af[i], len, TRUE, TRUE, FALSE))
                  return (FALSE);
           }
       } else {
           /* Next nesting level */
           if (second_round) {
              i++;
              n++;
           }

           make_string(&(data->sf[i]), len + 1);
           if (i == last)
           {
              if (!scan_field(&n, data->sf[i], len, FALSE, TRUE, TRUE))
                  return (FALSE);
           }
           else
           {
              if (!scan_field(&n, data->sf[i], len, TRUE, TRUE, TRUE))
                  return (FALSE);
           }
           second_round = TRUE;
           if (german_sort && strchr(data->sf[i], '"'))
           {
              make_string(&(data->af[i]),strlen(data->sf[i]) + 1);
              search_quote(&(data->sf[i]), &(data->af[i]));
           }
       }
    }

    /* check for empty fields which shouldn't be empty */
    if (*data->sf[0] == NUL) {
       NULL_RTN;
    }
    for (i = 1; i < FIELD_MAX - 1; i++)
       if ((*data->sf[i] == NUL) &&
           ((*data->af[i] != NUL) || (*data->sf[i + 1] != NUL))) {
           NULL_RTN;
       }
    /* i == FIELD_MAX-1 */
    if ((*data->sf[i] == NUL) && (*data->af[i] != NUL)) {
       NULL_RTN;
    }
    return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_no ( no  ,
npg  ,
short count,
short type 
) [static]

Definition at line 451 of file scanid.c.

{
    int     i = 1;

    if (isdigit(no[0])) {
       *type = ARAB;
       if (!scan_arabic(no, npg, count))
           return (FALSE);
       /* simple heuristic to determine if a letter is Roman or Alpha */
    } else if (IS_ROMAN_LOWER(no[0]) && (!IS_COMPOSITOR)) {
       *type = ROML;
       if (!scan_roman_lower(no, npg, count))
           return (FALSE);
       /* simple heuristic to determine if a letter is Roman or Alpha */
    } else if (IS_ROMAN_UPPER(no[0]) &&
              ((no[0] == ROMAN_I) || (!IS_COMPOSITOR))) {
       *type = ROMU;
       if (!scan_roman_upper(no, npg, count))
           return (FALSE);
    } else if (IS_ALPHA_LOWER(no[0])) {
       *type = ALPL;
       if (!scan_alpha_lower(no, npg, count))
           return (FALSE);
    } else if (IS_ALPHA_UPPER(no[0])) {
       *type = ALPU;
       if (!scan_alpha_upper(no, npg, count))
           return (FALSE);
    } else {
       IDX_ERROR("Illegal page number %s.\n", no);
       return (FALSE);
    }
    return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_roman_lower ( no  ,
npg  ,
short count 
) [static]

Definition at line 533 of file scanid.c.

{
    short   i = 0;
    int     inp = 0;
    int     prev = 0;
    int     the_new;

    while ((no[i] != NUL) && (i < ROMAN_MAX) && (!IS_COMPOSITOR)) {
       if ((IS_ROMAN_LOWER(no[i])) &&
           ((the_new = ROMAN_LOWER_VAL(no[i])) != 0)) {
           if (prev == 0)
              prev = the_new;
           else {
              if (prev < the_new) {
                  prev = the_new - prev;
                  the_new = 0;
              }
              inp += prev;
              prev = the_new;
           }
       } else {
IDX_ERROR2("Illegal Roman number: position %d in %s.\n", i + 1, no);
           return (FALSE);
       }
       i++;
    }
    if (i == ROMAN_MAX) {
       IDX_ERROR2("Roman page number %s too big (max %d digits).\n",
                 no, ROMAN_MAX);
       return (FALSE);
    }
    inp += prev;

    ENTER(inp + page_offset[ROML]);

    if (IS_COMPOSITOR)
       return (scan_no(&no[i + comp_len], npg, count, &i));
    else
       return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static int scan_roman_upper ( no  ,
npg  ,
short count 
) [static]

Definition at line 583 of file scanid.c.

{
    short   i = 0;
    int     inp = 0;
    int     prev = 0;
    int     the_new;

    while ((no[i] != NUL) && (i < ROMAN_MAX) && (!IS_COMPOSITOR)) {
       if ((IS_ROMAN_UPPER(no[i])) &&
           ((the_new = ROMAN_UPPER_VAL(no[i])) != 0)) {
           if (prev == 0)
              prev = the_new;
           else {
              if (prev < the_new) {
                  prev = the_new - prev;
                  the_new = 0;
              }
              inp += prev;
              prev = the_new;
           }
       } else {
IDX_ERROR2("Illegal Roman number: position %d in %s.\n", i + 1, no);
           return (FALSE);
       }
       i++;
    }
    if (i == ROMAN_MAX) {
       IDX_ERROR2("Roman page number %s too big (max %d digits).\n",
                 no, ROMAN_MAX);
       return (FALSE);
    }
    inp += prev;

    ENTER(inp + page_offset[ROMU]);

    if (IS_COMPOSITOR)
       return (scan_no(&no[i + comp_len], npg, count, &i));
    else
       return (TRUE);
}

Here is the call graph for this function:

Here is the caller graph for this function:

static void search_quote ( char **  sort_key,
char **  actual_key 
) [static]

Definition at line 792 of file scanid.c.

{
    char   *ptr;                   /* pointer to sort_key */
    char   *sort;                  /* contains sorting text */
    int     char_found = FALSE;

    strcpy(*actual_key, *sort_key);
    ptr = strchr(*sort_key, '"');       /* look for first double quote */
    while (ptr != (char*)NULL)
    {
       sort = NULL;
       switch (*(ptr + 1))
       {                           /* skip to umlaut or sharp S */
       case 'a':
       case 'A':
           sort = isupper(*(ptr + 1)) ? "Ae" : "ae";
           break;
       case 'o':
       case 'O':
           sort = isupper(*(ptr + 1)) ? "Oe" : "oe";
           break;
       case 'u':
       case 'U':
           sort = isupper(*(ptr + 1)) ? "Ue" : "ue";
           break;
       case 's':
           sort = "ss";
           break;
       default:
           break;
       }
       if (sort != NULL)
       {
           char_found = TRUE;
           *ptr = sort[0];         /* write to sort_key */
           *(ptr + 1) = sort[1];
       }
       ptr = strchr(ptr + 1, '"');    /* next double quote */
    }
    if (!char_found)               /* reset actual_key ? */
       make_string(actual_key, 1);
    return;
}

Here is the call graph for this function:

Here is the caller graph for this function:


Variable Documentation

int comp_len [static]

Definition at line 39 of file scanid.c.

int first_entry = TRUE [static]

Definition at line 38 of file scanid.c.

Definition at line 46 of file scanid.c.

Definition at line 36 of file scanid.c.

Definition at line 35 of file scanid.c.

Definition at line 33 of file scanid.c.

Definition at line 34 of file scanid.c.

char key[ARGUMENT_MAX] [static]

Definition at line 40 of file scanid.c.

char no[NUMBER_MAX] [static]

Definition at line 41 of file scanid.c.

Definition at line 47 of file scanid.c.