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