1 /*
2  *
3  *  This file is part of
4  *	MakeIndex - A formatter and format independent index processor
5  *
6  *  Copyright (C) 1998-2011 by the TeX Live project.
7  *  Copyright (C) 1989 by Chen & Harrison International Systems, Inc.
8  *  Copyright (C) 1988 by Olivetti Research Center
9  *  Copyright (C) 1987 by Regents of the University of California
10  *
11  *  Author:
12  *	Pehong Chen
13  *	Chen & Harrison International Systems, Inc.
14  *	Palo Alto, California
15  *	USA
16  *
17  *  Contributors:
18  *	Please refer to the CONTRIB file that comes with this release
19  *	for a list of people who have contributed to this and/or previous
20  *	release(s) of MakeIndex.
21  *
22  *  All rights reserved by the copyright holders.  See the copyright
23  *  notice distributed with this software for a complete description of
24  *  the conditions under which it is made available.
25  *
26  */
27 
28 #include    "mkind.h"
29 #include    "scanst.h"
30 
31 static int sty_lc = 0;                 /* line count */
32 static int sty_tc = 0;                 /* total count */
33 static int sty_ec = 0;                 /* error count */
34 
35 char    idx_keyword[ARRAY_MAX] = IDX_KEYWORD;
36 char    idx_aopen = IDX_AOPEN;
37 char    idx_aclose = IDX_ACLOSE;
38 char    idx_level = IDX_LEVEL;
39 char    idx_ropen = IDX_ROPEN;
40 char    idx_rclose = IDX_RCLOSE;
41 char    idx_quote = IDX_QUOTE;
42 char    idx_actual = IDX_ACTUAL;
43 char    idx_encap = IDX_ENCAP;
44 char    idx_escape = IDX_ESCAPE;
45 
46 char    preamble[ARRAY_MAX] = PREAMBLE_DEF;
47 char    postamble[ARRAY_MAX] = POSTAMBLE_DEF;
48 int     prelen = PREAMBLE_LEN;
49 int     postlen = POSTAMBLE_LEN;
50 
51 char    setpage_open[ARRAY_MAX] = SETPAGEOPEN_DEF;
52 char    setpage_close[ARRAY_MAX] = SETPAGECLOSE_DEF;
53 int     setpagelen = SETPAGE_LEN;
54 
55 char    group_skip[ARRAY_MAX] = GROUPSKIP_DEF;
56 int     skiplen = GROUPSKIP_LEN;
57 
58 int     headings_flag = HEADINGSFLAG_DEF;
59 char    heading_pre[ARRAY_MAX] = HEADINGPRE_DEF;
60 char    heading_suf[ARRAY_MAX] = HEADINGSUF_DEF;
61 int     headprelen = HEADINGPRE_LEN;
62 int     headsuflen = HEADINGSUF_LEN;
63 
64 char    symhead_pos[ARRAY_MAX] = SYMHEADPOS_DEF;
65 char    symhead_neg[ARRAY_MAX] = SYMHEADNEG_DEF;
66 
67 char    numhead_pos[ARRAY_MAX] = NUMHEADPOS_DEF;
68 char    numhead_neg[ARRAY_MAX] = NUMHEADNEG_DEF;
69 
70 char    item_r[FIELD_MAX][ARRAY_MAX] = {ITEM0_DEF, ITEM1_DEF, ITEM2_DEF};
71 char    item_u[FIELD_MAX][ARRAY_MAX] = {"", ITEM1_DEF, ITEM2_DEF};
72 char    item_x[FIELD_MAX][ARRAY_MAX] = {"", ITEM1_DEF, ITEM2_DEF};
73 
74 int     ilen_r[FIELD_MAX] = {ITEM_LEN, ITEM_LEN, ITEM_LEN};
75 int     ilen_u[FIELD_MAX] = {0, ITEM_LEN, ITEM_LEN};
76 int     ilen_x[FIELD_MAX] = {0, ITEM_LEN, ITEM_LEN};
77 
78 char    delim_p[FIELD_MAX][ARRAY_MAX] = {DELIM_DEF, DELIM_DEF, DELIM_DEF};
79 char    delim_n[ARRAY_MAX] = DELIM_DEF; /* page number separator */
80 char    delim_r[ARRAY_MAX] = DELIMR_DEF;/* page range designator */
81 char    delim_t[ARRAY_MAX] = DELIMT_DEF;/* page list terminating delimiter */
82 
83 char    suffix_2p[ARRAY_MAX] = "";      /* suffix for two page ranges */
84 char    suffix_3p[ARRAY_MAX] = "";      /* suffix for three page ranges */
85 char    suffix_mp[ARRAY_MAX] = "";      /* suffix for multiple page ranges */
86 
87 char    encap_p[ARRAY_MAX] = ENCAP0_DEF;/* encapsulator prefix */
88 char    encap_i[ARRAY_MAX] = ENCAP1_DEF;/* encapsulator infix */
89 char    encap_s[ARRAY_MAX] = ENCAP2_DEF;/* encapsulator postfix */
90 
91 int     linemax = LINE_MAX;
92 
93 int     indent_length = INDENTLEN_DEF;
94 char    indent_space[ARRAY_MAX] = INDENTSPC_DEF;
95 
96 char    page_comp[ARRAY_MAX] = COMPOSITOR_DEF;
97 int     page_offset[PAGETYPE_MAX] = {
98 0,
99 ROMAN_LOWER_OFFSET,
100 ROMAN_LOWER_OFFSET + ARABIC_OFFSET,
101 ROMAN_LOWER_OFFSET + ARABIC_OFFSET + ALPHA_LOWER_OFFSET,
102 ROMAN_LOWER_OFFSET + ARABIC_OFFSET + ALPHA_LOWER_OFFSET + ROMAN_UPPER_OFFSET
103 };
104 static char page_prec[ARRAY_MAX] = PRECEDENCE_DEF;
105 
106 static int put_dot;
107 
108 static	int	count_lfd (char *str);
109 static	int	next_nonblank (void);
110 static	int	process_precedence (void);
111 static	int	scan_char (char *c);
112 static	int	scan_spec (char *spec);
113 static	int	scan_string (char *str);
114 
115 void
scan_sty(void)116 scan_sty(void)
117 {
118     char    spec[STRING_MAX];
119     int     tmp;
120 
121     MESSAGE1("Scanning style file %s", sty_fn);
122     while (scan_spec(spec)) {
123 	sty_tc++;
124 	put_dot = TRUE;
125 
126 	/* output pre- and post-ambles */
127 	if (STREQ(spec, PREAMBLE)) {
128 	    (void) scan_string(preamble);
129 	    prelen = count_lfd(preamble);
130 	} else if (STREQ(spec, POSTAMBLE)) {
131 	    (void) scan_string(postamble);
132 	    postlen = count_lfd(postamble);
133 	} else if (STREQ(spec, GROUP_SKIP)) {
134 	    (void) scan_string(group_skip);
135 	    skiplen = count_lfd(group_skip);
136 	} else if (STREQ(spec, HEADINGS_FLAG)) {
137 	    SCAN_NO(&headings_flag);
138 	} else if (STREQ(spec, HEADING_PRE)) {
139 	    (void) scan_string(heading_pre);
140 	    headprelen = count_lfd(heading_pre);
141 	} else if (STREQ(spec, HEADING_SUF)) {
142 	    (void) scan_string(heading_suf);
143 	    headsuflen = count_lfd(heading_suf);
144 	} else if (STREQ(spec, SYMHEAD_POS)) {
145 	    (void) scan_string(symhead_pos);
146 	} else if (STREQ(spec, SYMHEAD_NEG)) {
147 	    (void) scan_string(symhead_neg);
148 	} else if (STREQ(spec, NUMHEAD_POS)) {
149 	    (void) scan_string(numhead_pos);
150 	} else if (STREQ(spec, NUMHEAD_NEG)) {
151 	    (void) scan_string(numhead_neg);
152 	} else if (STREQ(spec, SETPAGEOPEN)) {
153 	    (void) scan_string(setpage_open);
154 	    setpagelen = count_lfd(setpage_open);
155 	} else if (STREQ(spec, SETPAGECLOSE)) {
156 	    (void) scan_string(setpage_close);
157 	    setpagelen = count_lfd(setpage_close);
158 	    /* output index item commands */
159 	} else if (STREQ(spec, ITEM_0)) {
160 	    (void) scan_string(item_r[0]);
161 	    ilen_r[0] = count_lfd(item_r[0]);
162 	} else if (STREQ(spec, ITEM_1)) {
163 	    (void) scan_string(item_r[1]);
164 	    ilen_r[1] = count_lfd(item_r[1]);
165 	} else if (STREQ(spec, ITEM_2)) {
166 	    (void) scan_string(item_r[2]);
167 	    ilen_r[2] = count_lfd(item_r[2]);
168 	} else if (STREQ(spec, ITEM_01)) {
169 	    (void) scan_string(item_u[1]);
170 	    ilen_u[1] = count_lfd(item_u[1]);
171 	} else if (STREQ(spec, ITEM_12)) {
172 	    (void) scan_string(item_u[2]);
173 	    ilen_u[2] = count_lfd(item_u[2]);
174 	} else if (STREQ(spec, ITEM_x1)) {
175 	    (void) scan_string(item_x[1]);
176 	    ilen_x[1] = count_lfd(item_x[1]);
177 	} else if (STREQ(spec, ITEM_x2)) {
178 	    (void) scan_string(item_x[2]);
179 	    ilen_x[2] = count_lfd(item_x[2]);
180 	    /* output encapsulators */
181 	} else if (STREQ(spec, ENCAP_0))
182 	    (void) scan_string(encap_p);
183 	else if (STREQ(spec, ENCAP_1))
184 	    (void) scan_string(encap_i);
185 	else if (STREQ(spec, ENCAP_2))
186 	    (void) scan_string(encap_s);
187 	/* output delimiters */
188 	else if (STREQ(spec, DELIM_0))
189 	    (void) scan_string(delim_p[0]);
190 	else if (STREQ(spec, DELIM_1))
191 	    (void) scan_string(delim_p[1]);
192 	else if (STREQ(spec, DELIM_2))
193 	    (void) scan_string(delim_p[2]);
194 	else if (STREQ(spec, DELIM_N))
195 	    (void) scan_string(delim_n);
196 	else if (STREQ(spec, DELIM_R))
197 	    (void) scan_string(delim_r);
198 	else if (STREQ(spec, DELIM_T))
199 	    (void) scan_string(delim_t);
200 	else if (STREQ(spec, SUFFIX_2P))
201 	    (void) scan_string(suffix_2p);
202 	else if (STREQ(spec, SUFFIX_3P))
203 	    (void) scan_string(suffix_3p);
204 	else if (STREQ(spec, SUFFIX_MP))
205 	    (void) scan_string(suffix_mp);
206 	/* output line width */
207 	else if (STREQ(spec, LINEMAX)) {
208 	    SCAN_NO(&tmp);
209 	    if (tmp > 0)
210 		linemax = tmp;
211 	    else
212 		STY_ERROR2("%s must be positive (got %d)",
213 			   LINEMAX, tmp);
214 	    /* output line indentation length */
215 	} else if (STREQ(spec, INDENT_LENGTH)) {
216 	    SCAN_NO(&tmp);
217 	    if (tmp >= 0)
218 		indent_length = tmp;
219 	    else
220 		STY_ERROR2("%s must be nonnegative (got %d)",
221 			   INDENT_LENGTH, tmp);
222 	    /* output line indentation */
223 	} else if (STREQ(spec, INDENT_SPACE)) {
224 	    (void) scan_string(indent_space);
225 	    /* composite page delimiter */
226 	} else if (STREQ(spec, COMPOSITOR)) {
227 	    (void) scan_string(page_comp);
228 	    /* page precedence */
229 	} else if (STREQ(spec, PRECEDENCE)) {
230 	    (void) scan_string(page_prec);
231 	    (void) process_precedence();
232 	    /* index input format */
233 	} else if (STREQ(spec, KEYWORD))
234 	    (void) scan_string(idx_keyword);
235 	else if (STREQ(spec, AOPEN))
236 	    (void) scan_char(&idx_aopen);
237 	else if (STREQ(spec, ACLOSE))
238 	    (void) scan_char(&idx_aclose);
239 	else if (STREQ(spec, LEVEL))
240 	    (void) scan_char(&idx_level);
241 	else if (STREQ(spec, ROPEN))
242 	    (void) scan_char(&idx_ropen);
243 	else if (STREQ(spec, RCLOSE))
244 	    (void) scan_char(&idx_rclose);
245 	else if (STREQ(spec, QUOTE))
246 	    (void) scan_char(&idx_quote);
247 	else if (STREQ(spec, ACTUAL))
248 	    (void) scan_char(&idx_actual);
249 	else if (STREQ(spec, ENCAP))
250 	    (void) scan_char(&idx_encap);
251 	else if (STREQ(spec, ESCAPE))
252 	    (void) scan_char(&idx_escape);
253 	else {
254 	    (void) next_nonblank();
255 	    STY_SKIPLINE;
256 	    STY_ERROR1("Unknown specifier %s.\n", spec);
257 	    put_dot = FALSE;
258 	}
259 	if (put_dot) {
260 	    STY_DOT;
261 	}
262     }
263 
264     /* check if quote and escape are distinct */
265     if (idx_quote == idx_escape) {
266 	STY_ERROR1(
267 	       "Quote and escape symbols must be distinct (both `%c' now).\n",
268 	       idx_quote);
269 	idx_quote = IDX_QUOTE;
270 	idx_escape = IDX_ESCAPE;
271     }
272     DONE(sty_tc - sty_ec, "attributes redefined", sty_ec, "ignored");
273     CLOSE(sty_fp);
274 }
275 
276 static int
scan_spec(char spec[])277 scan_spec(char spec[])
278 {
279     int     i = 0;
280     int     c;
281 
282     while (TRUE)
283 	if ((c = next_nonblank()) == -1)
284 	    return (FALSE);
285 	else if (c == COMMENT) {
286 	    STY_SKIPLINE;
287 	} else
288 	    break;
289 
290     spec[0] = TOLOWER(c);
291     while ((i++ < STRING_MAX) && ((c = GET_CHAR(sty_fp)) != SPC) &&
292 	   (c != TAB) && (c != LFD) && (c != EOF))
293 	spec[i] = TOLOWER(c);
294     if (i < STRING_MAX) {
295 	spec[i] = NUL;
296 	if (c == EOF) {
297 	    STY_ERROR1(
298 		      "No attribute for specifier %s (premature EOF)\n",
299 		      spec);
300 	    return (-1);
301 	}
302 	if (c == LFD)
303 	    sty_lc++;
304 	return (TRUE);
305     } else {
306 	STY_ERROR2("Specifier %s too long (max %d).\n",
307 		   spec, STRING_MAX);
308 	return (FALSE);
309     }
310 }
311 
312 
313 static int
next_nonblank(void)314 next_nonblank(void)
315 {
316     int     c;
317 
318     while (TRUE) {
319 	switch (c = GET_CHAR(sty_fp)) {
320 	case EOF:
321 	    return (-1);
322 
323 	case LFD:
324 	    sty_lc++;
325 	case SPC:
326 	case TAB:
327 	    break;
328 	default:
329 	    return (c);
330 	}
331     }
332 }
333 
334 
335 static int
scan_string(char str[])336 scan_string(char str[])
337 {
338     char    clone[ARRAY_MAX];
339     int     i = 0;
340     int     c;
341 
342     switch (c = next_nonblank()) {
343     case STR_DELIM:
344 	while (TRUE)
345 	    switch (c = GET_CHAR(sty_fp)) {
346 	    case EOF:
347 		STY_ERROR1("No closing delimiter in %s.\n",
348 			  clone);
349 		return (FALSE);
350 	    case STR_DELIM:
351 		clone[i] = NUL;
352 		strcpy(str, clone);
353 		return (TRUE);
354 	    case BSH:
355 		switch (c = GET_CHAR(sty_fp)) {
356 		case 't':
357 		    clone[i++] = TAB;
358 		    break;
359 		case 'n':
360 		    clone[i++] = LFD;
361 		    break;
362 
363 		default:
364 		    clone[i++] = (char) c;
365 		    break;
366 		}
367 		break;
368 	    default:
369 		if (c == LFD)
370 		    sty_lc++;
371 		if (i < ARRAY_MAX)
372 		    clone[i++] = (char) c;
373 		else {
374 		    STY_SKIPLINE;
375 		    STY_ERROR2(
376 			       "Attribute string %s too long (max %d).\n",
377 			       clone, ARRAY_MAX);
378 		    return (FALSE);
379 		}
380 		break;
381 	    }
382 	break;
383     case COMMENT:
384 	STY_SKIPLINE;
385 	break;
386     default:
387 	STY_SKIPLINE;
388 	STY_ERROR("No opening delimiter.\n");
389 	return (FALSE);
390     }
391     return (TRUE);                     /* function value no longer used */
392 }
393 
394 
395 static int
scan_char(char * c)396 scan_char(char *c)
397 {
398     int     clone;
399 
400     switch (clone = next_nonblank()) {
401     case CHR_DELIM:
402 	switch (clone = GET_CHAR(sty_fp)) {
403 	case CHR_DELIM:
404 	    STY_SKIPLINE;
405 	    STY_ERROR("Premature closing delimiter.\n");
406 	    return (FALSE);
407 	case LFD:
408 	    sty_lc++;
409 	case EOF:
410 	    STY_ERROR("No character (premature EOF).\n");
411 	    return (FALSE);
412 	case BSH:
413 	    clone = GET_CHAR(sty_fp);
414 	default:
415 	    if (GET_CHAR(sty_fp) == CHR_DELIM) {
416 		*c = (char) clone;
417 		return (TRUE);
418 	    } else {
419 		STY_ERROR("No closing delimiter or too many letters.\n");
420 		return (FALSE);
421 	    }
422 	}
423 	/* break; */				/* NOT REACHED */
424     case COMMENT:
425 	STY_SKIPLINE;
426 	break;
427     default:
428 	STY_SKIPLINE;
429 	STY_ERROR("No opening delimiter.\n");
430 	return (FALSE);
431     }
432     return (TRUE);                     /* function value no longer used */
433 }
434 
435 
436 static int
count_lfd(char * str)437 count_lfd(char *str)
438 {
439     int     i = 0;
440     int     n = 0;
441 
442     while (str[i] != NUL) {
443 	if (str[i] == LFD)
444 	    n++;
445 	i++;
446     }
447     return (n);
448 }
449 
450 
451 static int
process_precedence(void)452 process_precedence(void)
453 {
454     int     order[PAGETYPE_MAX];
455     int     type[PAGETYPE_MAX];
456     int     i = 0;
457     int     last;
458     int     roml = FALSE;
459     int     romu = FALSE;
460     int     arab = FALSE;
461     int     alpl = FALSE;
462     int     alpu = FALSE;
463 
464     /* check for llegal specifiers first */
465     while ((i < PAGETYPE_MAX) && (page_prec[i] != NUL)) {
466 	switch (page_prec[i]) {
467 	case ROMAN_LOWER:
468 	    if (roml) {
469 		MULTIPLE(ROMAN_LOWER);
470 	    } else
471 		roml = TRUE;
472 	    break;
473 	case ROMAN_UPPER:
474 	    if (romu) {
475 		MULTIPLE(ROMAN_UPPER);
476 	    } else
477 		romu = TRUE;
478 	    break;
479 	case ARABIC:
480 	    if (arab) {
481 		MULTIPLE(ARABIC);
482 	    } else
483 		arab = TRUE;
484 	    break;
485 	case ALPHA_LOWER:
486 	    if (alpl) {
487 		MULTIPLE(ALPHA_UPPER);
488 	    } else
489 		alpl = TRUE;
490 	    break;
491 	case ALPHA_UPPER:
492 	    if (alpu) {
493 		MULTIPLE(ALPHA_UPPER);
494 	    } else
495 		alpu = TRUE;
496 	    break;
497 	default:
498 	    STY_SKIPLINE;
499 	    STY_ERROR1("Unknow type `%c' in page precedence specification.\n",
500 		      page_prec[i]);
501 	    return (FALSE);
502 	}
503 	i++;
504     }
505     if (page_prec[i] != NUL) {
506 	STY_SKIPLINE;
507 	STY_ERROR("Page precedence specification string too long.\n");
508 	return (FALSE);
509     }
510     last = i;
511     switch (page_prec[0]) {
512     case ROMAN_LOWER:
513 	order[0] = ROMAN_LOWER_OFFSET;
514 	type[0] = ROML;
515 	break;
516     case ROMAN_UPPER:
517 	order[0] = ROMAN_UPPER_OFFSET;
518 	type[0] = ROMU;
519 	break;
520     case ARABIC:
521 	order[0] = ARABIC_OFFSET;
522 	type[0] = ARAB;
523 	break;
524     case ALPHA_LOWER:
525 	order[0] = ALPHA_LOWER_OFFSET;
526 	type[0] = ALPL;
527 	break;
528     case ALPHA_UPPER:
529 	order[0] = ALPHA_LOWER_OFFSET;
530 	type[0] = ALPU;
531 	break;
532     }
533 
534     i = 1;
535     while (i < last) {
536 	switch (page_prec[i]) {
537 	case ROMAN_LOWER:
538 	    order[i] = order[i - 1] + ROMAN_LOWER_OFFSET;
539 	    type[i] = ROML;
540 	    break;
541 	case ROMAN_UPPER:
542 	    order[i] = order[i - 1] + ROMAN_UPPER_OFFSET;
543 	    type[i] = ROMU;
544 	    break;
545 	case ARABIC:
546 	    order[i] = order[i - 1] + ARABIC_OFFSET;
547 	    type[i] = ARAB;
548 	    break;
549 	case ALPHA_LOWER:
550 	    order[i] = order[i - 1] + ALPHA_LOWER_OFFSET;
551 	    type[i] = ALPL;
552 	    break;
553 	case ALPHA_UPPER:
554 	    order[i] = order[i - 1] + ALPHA_LOWER_OFFSET;
555 	    type[i] = ALPU;
556 	    break;
557 	}
558 	i++;
559     }
560 
561     for (i = 0; i < PAGETYPE_MAX; i++) {
562 	page_offset[i] = -1;
563     }
564     page_offset[type[0]] = 0;
565     for (i = 1; i < last; i++) {
566 	page_offset[type[i]] = order[i - 1];
567     }
568     for (i = 0; i < PAGETYPE_MAX; i++) {
569 	if (page_offset[i] == -1) {
570 	    switch (type[last - 1]) {
571 	    case ROML:
572 		order[last] = order[last - 1] + ROMAN_LOWER_OFFSET;
573 		break;
574 	    case ROMU:
575 		order[last] = order[last - 1] + ROMAN_UPPER_OFFSET;
576 		break;
577 	    case ARAB:
578 		order[last] = order[last - 1] + ARABIC_OFFSET;
579 		break;
580 	    case ALPL:
581 		order[last] = order[last - 1] + ALPHA_LOWER_OFFSET;
582 		break;
583 	    case ALPU:
584 		order[last] = order[last - 1] + ALPHA_UPPER_OFFSET;
585 		break;
586 	    }
587 	    type[last] = i;
588 	    page_offset[i] = order[last];
589 	    last++;
590 	}
591     }
592     return (TRUE);                     /* function value no longer used */
593 }
594