Back to index

tetex-bin  3.0
scanid.c
Go to the documentation of this file.
00001 /*
00002  *
00003  *  This file is part of
00004  *     MakeIndex - A formatter and format independent index processor
00005  *
00006  *  Copyright (C) 1989 by Chen & Harrison International Systems, Inc.
00007  *  Copyright (C) 1988 by Olivetti Research Center
00008  *  Copyright (C) 1987 by Regents of the University of California
00009  *
00010  *  Author:
00011  *     Pehong Chen
00012  *     Chen & Harrison International Systems, Inc.
00013  *     Palo Alto, California
00014  *     USA
00015  *     (phc@renoir.berkeley.edu or chen@orc.olivetti.com)
00016  *
00017  *  Contributors:
00018  *     Please refer to the CONTRIB file that comes with this release
00019  *     for a list of people who have contributed to this and/or previous
00020  *     release(s) of MakeIndex.
00021  *
00022  *  All rights reserved by the copyright holders.  See the copyright
00023  *  notice distributed with this software for a complete description of
00024  *  the conditions under which it is made available.
00025  *
00026  */
00027 
00028 #include    "mkind.h"
00029 #include    "scanid.h"
00030 
00031 #define CHECK_LENGTH()      if (i > len_field) goto FIELD_OVERFLOW
00032 
00033 int     idx_lc;                           /* line count */
00034 int     idx_tc;                           /* total entry count */
00035 int     idx_ec;                           /* erroneous entry count */
00036 int     idx_dc;                           /* number of dots printed so far */
00037 
00038 static int first_entry = TRUE;
00039 static int comp_len;
00040 static char key[ARGUMENT_MAX];
00041 static char no[NUMBER_MAX];
00042 #ifndef WIN32
00043 extern char *strchr ARGS((const char* s,int c));
00044 #endif
00045 
00046 NODE_PTR head;
00047 NODE_PTR tail;
00048 
00049 static void   flush_to_eol ARGS((void));
00050 static int    make_key ARGS((void));
00051 static void   make_string ARGS((char **ppstr,int n));
00052 static int    scan_alpha_lower ARGS((char *no,int *npg,short *count));
00053 static int    scan_alpha_upper ARGS((char *no,int *npg,short *count));
00054 static int    scan_arabic ARGS((char *no,int *npg,short *count));
00055 static int    scan_arg1 ARGS((void));
00056 static int    scan_arg2 ARGS((void));
00057 static int    scan_field ARGS((int *n,char field[],int len_field,
00058                              int ck_level, int ck_encap,int ck_actual));
00059 static int    scan_key ARGS((struct KFIELD *data));
00060 static int    scan_no ARGS((char *no,int *npg,short *count,short *type));
00061 static int    scan_roman_lower ARGS((char *no,int *npg,short *count));
00062 static int    scan_roman_upper ARGS((char *no,int *npg,short *count));
00063 static void   search_quote ARGS((char **sort_key,char **actual_key));
00064 
00065 void
00066 scan_idx(VOID_ARG)
00067 {
00068     char    keyword[ARRAY_MAX];
00069     int     c;
00070     int     i = 0;
00071     int     not_eof = TRUE;
00072     int     arg_count = -1;
00073 
00074     MESSAGE("Scanning input file %s...", idx_fn);
00075     idx_lc = idx_tc = idx_ec = idx_dc = 0;
00076     comp_len = strlen(page_comp);
00077     while (not_eof) {
00078        switch (c = GET_CHAR(idx_fp)) {
00079        case EOF:
00080            if (arg_count == 2) {
00081               idx_lc++;
00082               if (make_key())
00083                   IDX_DOT(DOT_MAX);
00084               arg_count = -1;
00085            } else
00086               not_eof = FALSE;
00087            break;
00088 
00089        case LFD:
00090            idx_lc++;
00091            if (arg_count == 2) {
00092               if (make_key())
00093                   IDX_DOT(DOT_MAX);
00094               arg_count = -1;
00095            } else if (arg_count > -1) {
00096               IDX_ERROR("Missing arguments -- need two (premature LFD).\n",
00097                        NULL);
00098               arg_count = -1;
00099            }
00100        case TAB:
00101        case SPC:
00102            break;
00103 
00104        default:
00105            switch (arg_count) {
00106            case -1:
00107               i = 0;
00108               keyword[i++] = (char) c;
00109               arg_count++;
00110               idx_tc++;
00111               break;
00112            case 0:
00113               if (c == idx_aopen) {
00114                   arg_count++;
00115                   keyword[i] = NUL;
00116                   if (STREQ(keyword, idx_keyword)) {
00117                      if (!scan_arg1()) {
00118                          arg_count = -1;
00119                      }
00120                   } else {
00121                      IDX_SKIPLINE;
00122                      IDX_ERROR("Unknown index keyword %s.\n", keyword);
00123                   }
00124               } else {
00125                   if (i < ARRAY_MAX)
00126                      keyword[i++] = (char) c;
00127                   else {
00128                      IDX_SKIPLINE;
00129                      IDX_ERROR2("Index keyword %s too long (max %d).\n",
00130                                keyword, ARRAY_MAX);
00131                   }
00132               }
00133               break;
00134            case 1:
00135               if (c == idx_aopen) {
00136                   arg_count++;
00137                   if (!scan_arg2()) {
00138                      arg_count = -1;
00139                   }
00140               } else {
00141                   IDX_SKIPLINE;
00142 IDX_ERROR(
00143 "No opening delimiter for second argument (illegal character `%c').\n", c);
00144               }
00145               break;
00146            case 2:
00147               IDX_SKIPLINE;
00148 IDX_ERROR(
00149 "No closing delimiter for second argument (illegal character `%c').\n", c);
00150               break;
00151            }
00152            break;
00153        }
00154     }
00155 
00156     /* fixup the total counts */
00157     idx_tt += idx_tc;
00158     idx_et += idx_ec;
00159 
00160     DONE(idx_tc - idx_ec, "entries accepted", idx_ec, "rejected");
00161     CLOSE(idx_fp);
00162 }
00163 
00164 static void
00165 flush_to_eol(VOID_ARG)
00166 {      /* flush to end-of-line, or end-of-file, whichever is first */
00167     int a;
00168 
00169     while ( ((a = GET_CHAR(idx_fp)) != LFD) && (a != EOF) )
00170        /* NO-OP */;
00171 }
00172 
00173 static int
00174 make_key(VOID_ARG)
00175 {
00176     NODE_PTR ptr;
00177     int     i;
00178     static size_t len = sizeof(NODE);
00179 
00180     /* allocate and initialize a node */
00181 
00182 #ifdef DEBUG
00183        totmem += len;
00184        (void)fprintf(stderr,"make_key(): malloc(%d)\ttotmem = %ld\n",
00185            len,totmem);
00186 #endif /* DEBUG */
00187 
00188     if ((ptr = (NODE_PTR) malloc(len)) == NULL)
00189        fprintf (stderr, "Not enough core...abort.\n");
00190 
00191     bzero(ptr, len);
00192     /* Initialize dangling pointers
00193      * Note: it would be a nice work to redesign the code to use NULL for
00194      * comparision ... nevertheless, using local "" in a global environment
00195      * isn't the hit because the allocation of the keys with german_sort may
00196      * crash with a nitpicking memory allocation (Linux, libc-5.4.46).
00197      * <werner@suse.de>
00198      */
00199     for (i = 0; i < FIELD_MAX; i++)
00200     {
00201        make_string(&(ptr->data.sf[i]), 1);
00202        make_string(&(ptr->data.af[i]), 1);
00203     }
00204     make_string(&(ptr->data.encap), 1);
00205     ptr->data.lpg[0] = NUL;
00206     ptr->data.count = 0;
00207     ptr->data.type = EMPTY;
00208 
00209     /* process index key */
00210     if (!scan_key(&(ptr->data)))
00211        return (FALSE);
00212 
00213     /* determine group type */
00214     ptr->data.group = group_type(ptr->data.sf[0]);
00215 
00216     /* process page number */
00217     strcpy(ptr->data.lpg, no);
00218     if (!scan_no(no, ptr->data.npg, &(ptr->data.count), &(ptr->data.type)))
00219        return (FALSE);
00220 
00221     if (first_entry) {
00222        head = tail = ptr;
00223        first_entry = FALSE;
00224     } else {
00225        tail->next = ptr;
00226        tail = ptr;
00227     }
00228     ptr->data.lc = idx_lc;
00229     ptr->data.fn = idx_fn;
00230     tail->next = NULL;
00231 
00232     return (TRUE);
00233 }
00234 
00235 static void
00236 #if STDC
00237 make_string(char **ppstr, int n)
00238 #else
00239 make_string(ppstr,n)               /* allocate n-byte string if *ppstr */
00240 char   **ppstr;                    /* points to an empty string */
00241 int    n;
00242 #endif
00243 {
00244     if (*ppstr)                    /* Do NOT leaking here, <werner@suse.de> */
00245        free(*ppstr);
00246 
00247     /* Note: we have always allocate the correct amount of memory to
00248      * avoid chrashes because the string length of the actual and
00249      * sort key may differ at german_sort and strange indexentries
00250      * <werner@suse.de>
00251      */
00252     (*ppstr) = (char*)malloc(n);
00253     if (!(*ppstr))
00254        fprintf (stderr, "Not enough core...abort.\n");
00255     bzero(*ppstr, n);              /* Always zero anything, <werner@suse.de> */
00256 }
00257 
00258 static int
00259 #if STDC
00260 scan_key(FIELD_PTR data)
00261 #else
00262 scan_key(data)
00263 FIELD_PTR data;
00264 #endif
00265 {
00266     int     i = 0;                 /* current level */
00267     int     n = 0;                 /* index to the key[] array */
00268     int     second_round = FALSE;
00269     int     last = FIELD_MAX - 1;
00270     size_t  len;
00271 
00272     while (TRUE) {
00273        if (key[n] == NUL)
00274            break;
00275        len = strlen(key);
00276        if (key[n] == idx_encap)
00277        {
00278            n++;
00279            make_string(&(data->encap), len + 1);
00280            if (scan_field(&n, data->encap, len, FALSE, FALSE, FALSE))
00281               break;
00282            else
00283               return (FALSE);
00284        }
00285        if (key[n] == idx_actual) {
00286            n++;
00287 
00288            make_string(&(data->af[i]), len + 1);
00289            if (i == last)
00290            {
00291               if (!scan_field(&n, data->af[i], len, FALSE, TRUE, FALSE))
00292                   return (FALSE);
00293            }
00294            else
00295            {
00296               if (!scan_field(&n, data->af[i], len, TRUE, TRUE, FALSE))
00297                   return (FALSE);
00298            }
00299        } else {
00300            /* Next nesting level */
00301            if (second_round) {
00302               i++;
00303               n++;
00304            }
00305 
00306            make_string(&(data->sf[i]), len + 1);
00307            if (i == last)
00308            {
00309               if (!scan_field(&n, data->sf[i], len, FALSE, TRUE, TRUE))
00310                   return (FALSE);
00311            }
00312            else
00313            {
00314               if (!scan_field(&n, data->sf[i], len, TRUE, TRUE, TRUE))
00315                   return (FALSE);
00316            }
00317            second_round = TRUE;
00318            if (german_sort && strchr(data->sf[i], '"'))
00319            {
00320               make_string(&(data->af[i]),strlen(data->sf[i]) + 1);
00321               search_quote(&(data->sf[i]), &(data->af[i]));
00322            }
00323        }
00324     }
00325 
00326     /* check for empty fields which shouldn't be empty */
00327     if (*data->sf[0] == NUL) {
00328        NULL_RTN;
00329     }
00330     for (i = 1; i < FIELD_MAX - 1; i++)
00331        if ((*data->sf[i] == NUL) &&
00332            ((*data->af[i] != NUL) || (*data->sf[i + 1] != NUL))) {
00333            NULL_RTN;
00334        }
00335     /* i == FIELD_MAX-1 */
00336     if ((*data->sf[i] == NUL) && (*data->af[i] != NUL)) {
00337        NULL_RTN;
00338     }
00339     return (TRUE);
00340 }
00341 
00342 static int
00343 #if STDC
00344 scan_field(int *n, char field[], int len_field, int ck_level, int ck_encap, 
00345        int ck_actual)
00346 #else
00347 scan_field(n, field, len_field, ck_level, ck_encap, ck_actual)
00348 int    *n;
00349 char    field[];
00350 int    len_field;    /* length of field[], EXCLUDING space for final NUL */
00351 int     ck_level;
00352 int     ck_encap;
00353 int     ck_actual;
00354 #endif
00355 {
00356     int     i = 0;
00357     int     nbsh;                  /* backslash count */
00358 
00359     if (compress_blanks && ((key[*n] == SPC) || (key[*n] == TAB)))
00360        ++* n;
00361 
00362     while (TRUE) {
00363        nbsh = 0;
00364        while (key[*n] == idx_escape)
00365        {
00366            nbsh++;
00367            field[i++] = key[*n];
00368            CHECK_LENGTH();
00369            ++*n;
00370        }
00371 
00372        if (key[*n] == idx_quote)
00373        {
00374            if (nbsh % 2 == 0)
00375               field[i++] = key[++*n];
00376            else
00377               field[i++] = key[*n];
00378            CHECK_LENGTH();
00379        }
00380        else if ((ck_level && (key[*n] == idx_level)) ||
00381                (ck_encap && (key[*n] == idx_encap)) ||
00382                (ck_actual && (key[*n] == idx_actual)) ||
00383                (key[*n] == NUL))
00384        {
00385            if ((i > 0) && compress_blanks && (field[i - 1] == SPC))
00386               field[i - 1] = NUL;
00387            else
00388               field[i] = NUL;
00389            return (TRUE);
00390        } else {
00391            field[i++] = key[*n];
00392            CHECK_LENGTH();
00393            if ((!ck_level) && (key[*n] == idx_level)) {
00394               IDX_ERROR2("Extra `%c' at position %d of first argument.\n",
00395                         idx_level, *n + 1);
00396               return (FALSE);
00397            } else if ((!ck_encap) && (key[*n] == idx_encap)) {
00398               IDX_ERROR2("Extra `%c' at position %d of first argument.\n",
00399                         idx_encap, *n + 1);
00400               return (FALSE);
00401            } else if ((!ck_actual) && (key[*n] == idx_actual)) {
00402               IDX_ERROR2("Extra `%c' at position %d of first argument.\n",
00403                         idx_actual, *n + 1);
00404               return (FALSE);
00405            }
00406        }
00407        /* check if max field length is reached */
00408        if (i > len_field)
00409        {
00410        FIELD_OVERFLOW:
00411            if (!ck_encap) {
00412               IDX_ERROR("Encapsulator of page number too long (max. %d).\n",
00413                        len_field);
00414            } else if (ck_actual) {
00415               IDX_ERROR("Index sort key too long (max. %d).\n", len_field);
00416            } else {
00417               IDX_ERROR("Text of key entry too long (max. %d).\n", len_field);
00418            }
00419            return (FALSE);
00420        }
00421        ++*n;
00422     }
00423 }
00424 
00425 int
00426 #if STDC
00427 group_type(char *str)
00428 #else
00429 group_type(str)
00430 char   *str;
00431 #endif
00432 {
00433     int     i = 0;
00434 
00435     while ((str[i] != NUL) && ISDIGIT(str[i]))
00436        i++;
00437 
00438     if (str[i] == NUL) {
00439        sscanf(str, "%d", &i);
00440        return (i);
00441     } else if (ISSYMBOL(str[0]))
00442        return (SYMBOL);
00443     else
00444        return (ALPHA);
00445 }
00446 
00447 static int
00448 #if STDC
00449 scan_no(char no[], int npg[], short *count, short *type)
00450 #else
00451 scan_no(no, npg, count, type)
00452 char    no[];
00453 int   npg[];
00454 short  *count;
00455 short  *type;
00456 #endif
00457 {
00458     int     i = 1;
00459 
00460     if (isdigit(no[0])) {
00461        *type = ARAB;
00462        if (!scan_arabic(no, npg, count))
00463            return (FALSE);
00464        /* simple heuristic to determine if a letter is Roman or Alpha */
00465     } else if (IS_ROMAN_LOWER(no[0]) && (!IS_COMPOSITOR)) {
00466        *type = ROML;
00467        if (!scan_roman_lower(no, npg, count))
00468            return (FALSE);
00469        /* simple heuristic to determine if a letter is Roman or Alpha */
00470     } else if (IS_ROMAN_UPPER(no[0]) &&
00471               ((no[0] == ROMAN_I) || (!IS_COMPOSITOR))) {
00472        *type = ROMU;
00473        if (!scan_roman_upper(no, npg, count))
00474            return (FALSE);
00475     } else if (IS_ALPHA_LOWER(no[0])) {
00476        *type = ALPL;
00477        if (!scan_alpha_lower(no, npg, count))
00478            return (FALSE);
00479     } else if (IS_ALPHA_UPPER(no[0])) {
00480        *type = ALPU;
00481        if (!scan_alpha_upper(no, npg, count))
00482            return (FALSE);
00483     } else {
00484        IDX_ERROR("Illegal page number %s.\n", no);
00485        return (FALSE);
00486     }
00487     return (TRUE);
00488 }
00489 
00490 
00491 static int
00492 #if STDC
00493 scan_arabic(char no[], int npg[], short *count)
00494 #else
00495 scan_arabic(no, npg, count)
00496 char    no[];
00497 int   npg[];
00498 short  *count;
00499 #endif
00500 {
00501     short   i = 0;
00502     char    str[ARABIC_MAX+1];            /* space for trailing NUL */
00503 
00504     while ((no[i] != NUL) && (i <= ARABIC_MAX) && (!IS_COMPOSITOR)) {
00505        if (isdigit(no[i])) {
00506            str[i] = no[i];
00507            i++;
00508        } else {
00509 IDX_ERROR2("Illegal Arabic digit: position %d in %s.\n", i + 1, no);
00510            return (FALSE);
00511        }
00512     }
00513     if (i > ARABIC_MAX) {
00514        IDX_ERROR2("Arabic page number %s too big (max %d digits).\n",
00515                  no, ARABIC_MAX);
00516        return (FALSE);
00517     }
00518     str[i] = NUL;
00519 
00520     ENTER(strtoint(str) + page_offset[ARAB]);
00521 
00522     if (IS_COMPOSITOR)
00523        return (scan_no(&no[i + comp_len], npg, count, &i));
00524     else
00525        return (TRUE);
00526 }
00527 
00528 
00529 static int
00530 #if STDC
00531 scan_roman_lower(char no[], int npg[], short *count)
00532 #else
00533 scan_roman_lower(no, npg, count)
00534 char    no[];
00535 int   npg[];
00536 short  *count;
00537 #endif
00538 {
00539     short   i = 0;
00540     int     inp = 0;
00541     int     prev = 0;
00542     int     the_new;
00543 
00544     while ((no[i] != NUL) && (i < ROMAN_MAX) && (!IS_COMPOSITOR)) {
00545        if ((IS_ROMAN_LOWER(no[i])) &&
00546            ((the_new = ROMAN_LOWER_VAL(no[i])) != 0)) {
00547            if (prev == 0)
00548               prev = the_new;
00549            else {
00550               if (prev < the_new) {
00551                   prev = the_new - prev;
00552                   the_new = 0;
00553               }
00554               inp += prev;
00555               prev = the_new;
00556            }
00557        } else {
00558 IDX_ERROR2("Illegal Roman number: position %d in %s.\n", i + 1, no);
00559            return (FALSE);
00560        }
00561        i++;
00562     }
00563     if (i == ROMAN_MAX) {
00564        IDX_ERROR2("Roman page number %s too big (max %d digits).\n",
00565                  no, ROMAN_MAX);
00566        return (FALSE);
00567     }
00568     inp += prev;
00569 
00570     ENTER(inp + page_offset[ROML]);
00571 
00572     if (IS_COMPOSITOR)
00573        return (scan_no(&no[i + comp_len], npg, count, &i));
00574     else
00575        return (TRUE);
00576 }
00577 
00578 
00579 static int
00580 #if STDC
00581 scan_roman_upper(char no[], int npg[], short *count)
00582 #else
00583 scan_roman_upper(no, npg, count)
00584 char    no[];
00585 int   npg[];
00586 short  *count;
00587 #endif
00588 {
00589     short   i = 0;
00590     int     inp = 0;
00591     int     prev = 0;
00592     int     the_new;
00593 
00594     while ((no[i] != NUL) && (i < ROMAN_MAX) && (!IS_COMPOSITOR)) {
00595        if ((IS_ROMAN_UPPER(no[i])) &&
00596            ((the_new = ROMAN_UPPER_VAL(no[i])) != 0)) {
00597            if (prev == 0)
00598               prev = the_new;
00599            else {
00600               if (prev < the_new) {
00601                   prev = the_new - prev;
00602                   the_new = 0;
00603               }
00604               inp += prev;
00605               prev = the_new;
00606            }
00607        } else {
00608 IDX_ERROR2("Illegal Roman number: position %d in %s.\n", i + 1, no);
00609            return (FALSE);
00610        }
00611        i++;
00612     }
00613     if (i == ROMAN_MAX) {
00614        IDX_ERROR2("Roman page number %s too big (max %d digits).\n",
00615                  no, ROMAN_MAX);
00616        return (FALSE);
00617     }
00618     inp += prev;
00619 
00620     ENTER(inp + page_offset[ROMU]);
00621 
00622     if (IS_COMPOSITOR)
00623        return (scan_no(&no[i + comp_len], npg, count, &i));
00624     else
00625        return (TRUE);
00626 }
00627 
00628 
00629 static int
00630 #if STDC
00631 scan_alpha_lower(char no[], int npg[], short *count)
00632 #else
00633 scan_alpha_lower(no, npg, count)
00634 char    no[];
00635 int   npg[];
00636 short  *count;
00637 #endif
00638 {
00639     short   i;
00640 
00641     ENTER(ALPHA_VAL(no[0]) + page_offset[ALPL]);
00642 
00643     i = 1;
00644     if (IS_COMPOSITOR)
00645        return (scan_no(&no[comp_len + 1], npg, count, &i));
00646     else
00647        return (TRUE);
00648 }
00649 
00650 
00651 static int
00652 #if STDC
00653 scan_alpha_upper(char no[], int npg[], short *count)
00654 #else
00655 scan_alpha_upper(no, npg, count)
00656 char    no[];
00657 int   npg[];
00658 short  *count;
00659 #endif
00660 {
00661     short   i;
00662 
00663     ENTER(ALPHA_VAL(no[0]) + page_offset[ALPU]);
00664 
00665     i = 1;
00666     if (IS_COMPOSITOR)
00667        return (scan_no(&no[comp_len + 1], npg, count, &i));
00668     else
00669        return (TRUE);
00670 }
00671 
00672 
00673 static int
00674 scan_arg1(VOID_ARG)
00675 {
00676     int     i = 0;
00677     int     n = 0;                 /* delimiter count */
00678     int     a;
00679 
00680     if (compress_blanks)
00681        while (((a = GET_CHAR(idx_fp)) == SPC) || (a == TAB));
00682     else
00683        a = GET_CHAR(idx_fp);
00684 
00685     while ((i < ARGUMENT_MAX) && (a != EOF))
00686     {
00687        if ((a == idx_quote) || (a == idx_escape))
00688        {                           /* take next character literally */
00689            key[i++] = (char) a;    /* but preserve quote or escape */
00690            a = GET_CHAR(idx_fp);
00691            key[i++] = (char) a;    /* save literal character */
00692        }
00693        else if (a == idx_aopen)
00694        {             /* opening delimiters within the argument list */
00695            key[i++] = (char) a;
00696            n++;
00697        }
00698        else if (a == idx_aclose)
00699        {
00700            if (n == 0)                    /* end of argument */
00701            {
00702               if (compress_blanks && key[i - 1] == SPC)
00703                   key[i - 1] = NUL;
00704               else
00705                   key[i] = NUL;
00706               return (TRUE);
00707            }
00708            else                    /* nested delimiters */
00709            {
00710               key[i++] = (char) a;
00711               n--;
00712            }
00713        }
00714        else
00715        {
00716            switch (a)
00717            {
00718            case LFD:
00719               idx_lc++;
00720               IDX_ERROR("Incomplete first argument (premature LFD).\n", "");
00721               return (FALSE);
00722            case TAB:
00723            case SPC:
00724               /* compress successive SPC's to one SPC */
00725               if (compress_blanks)
00726               {
00727                   if ((i > 0) && (key[i - 1] != SPC) && (key[i - 1] != TAB))
00728                      key[i++] = SPC;
00729                   break;
00730               }
00731            default:
00732               key[i++] = (char) a;
00733               break;
00734            }
00735        }
00736        a = GET_CHAR(idx_fp);
00737     }
00738 
00739     flush_to_eol();                /* Skip to end of line */
00740     idx_lc++;
00741     IDX_ERROR("First argument too long (max %d).\n", ARGUMENT_MAX);
00742     return (FALSE);
00743 }
00744 
00745 
00746 static int
00747 scan_arg2(VOID_ARG)
00748 {
00749     int     i = 0;
00750     int     a;
00751     int     hit_blank = FALSE;
00752 
00753     while (((a = GET_CHAR(idx_fp)) == SPC) || (a == TAB));
00754 
00755     while (i < NUMBER_MAX) {
00756        if (a == idx_aclose) {
00757            no[i] = NUL;
00758            return (TRUE);
00759        } else
00760            switch (a) {
00761            case LFD:
00762               idx_lc++;
00763 IDX_ERROR("Incomplete second argument (premature LFD).\n", "");
00764               return (FALSE);
00765            case TAB:
00766            case SPC:
00767               hit_blank = TRUE;
00768               break;
00769            default:
00770               if (hit_blank) {
00771                   flush_to_eol();  /* Skip to end of line */
00772                   idx_lc++;
00773 IDX_ERROR("Illegal space within numerals in second argument.\n", "");
00774                   return (FALSE);
00775               }
00776               no[i++] = (char) a;
00777               break;
00778            }
00779        a = GET_CHAR(idx_fp);
00780     }
00781     flush_to_eol();  /* Skip to end of line */
00782     idx_lc++;
00783     IDX_ERROR("Second argument too long (max %d).\n", NUMBER_MAX);
00784     return (FALSE);
00785 }
00786 
00787 
00788 static void
00789 #if STDC
00790 search_quote(char **sort_key, char **actual_key)
00791 #else
00792 search_quote(sort_key, actual_key)
00793 char  **sort_key;
00794 char  **actual_key;
00795 #endif
00796 {
00797     char   *ptr;                   /* pointer to sort_key */
00798     char   *sort;                  /* contains sorting text */
00799     int     char_found = FALSE;
00800 
00801     strcpy(*actual_key, *sort_key);
00802     ptr = strchr(*sort_key, '"');       /* look for first double quote */
00803     while (ptr != (char*)NULL)
00804     {
00805        sort = NULL;
00806        switch (*(ptr + 1))
00807        {                           /* skip to umlaut or sharp S */
00808        case 'a':
00809        case 'A':
00810            sort = isupper(*(ptr + 1)) ? "Ae" : "ae";
00811            break;
00812        case 'o':
00813        case 'O':
00814            sort = isupper(*(ptr + 1)) ? "Oe" : "oe";
00815            break;
00816        case 'u':
00817        case 'U':
00818            sort = isupper(*(ptr + 1)) ? "Ue" : "ue";
00819            break;
00820        case 's':
00821            sort = "ss";
00822            break;
00823        default:
00824            break;
00825        }
00826        if (sort != NULL)
00827        {
00828            char_found = TRUE;
00829            *ptr = sort[0];         /* write to sort_key */
00830            *(ptr + 1) = sort[1];
00831        }
00832        ptr = strchr(ptr + 1, '"');    /* next double quote */
00833     }
00834     if (!char_found)               /* reset actual_key ? */
00835        make_string(actual_key, 1);
00836     return;
00837 }