source: trunk/third/ispell/defmt.c @ 10334

Revision 10334, 23.4 KB checked in by ghudson, 27 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r10333, which included commits to RCS files with non-trunk default branches.
Line 
1#ifndef lint
2static char Rcs_Id[] =
3    "$Id: defmt.c,v 1.1.1.1 1997-09-03 21:08:11 ghudson Exp $";
4#endif
5
6/*
7 * defmt.c - Handle formatter constructs, mostly by scanning over them.
8 *
9 * This code originally resided in ispell.c, but was moved here to keep
10 * file sizes smaller.
11 *
12 * Copyright (c), 1983, by Pace Willisson
13 *
14 * Copyright 1992, 1993, Geoff Kuenning, Granada Hills, CA
15 * All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 *
21 * 1. Redistributions of source code must retain the above copyright
22 *    notice, this list of conditions and the following disclaimer.
23 * 2. Redistributions in binary form must reproduce the above copyright
24 *    notice, this list of conditions and the following disclaimer in the
25 *    documentation and/or other materials provided with the distribution.
26 * 3. All modifications to the source code must be clearly marked as
27 *    such.  Binary redistributions based on modified source code
28 *    must be clearly marked as modified versions in the documentation
29 *    and/or other materials provided with the distribution.
30 * 4. All advertising materials mentioning features or use of this software
31 *    must display the following acknowledgment:
32 *      This product includes software developed by Geoff Kuenning and
33 *      other unpaid contributors.
34 * 5. The name of Geoff Kuenning may not be used to endorse or promote
35 *    products derived from this software without specific prior
36 *    written permission.
37 *
38 * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND
39 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41 * ARE DISCLAIMED.  IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE
42 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
43 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
44 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
45 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
46 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
47 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 *
50 * The TeX code is originally by Greg Schaffer, with many improvements from
51 * Ken Stevens.  The nroff code is primarily from Pace Willisson, although
52 * other people have improved it.
53 */
54
55/*
56 * $Log: not supported by cvs2svn $
57 * Revision 1.41  1995/08/05  23:19:47  geoff
58 * Get rid of an obsolete comment.  Add recognition of documentclass and
59 * usepackage for Latex2e support.
60 *
61 * Revision 1.40  1995/03/06  02:42:43  geoff
62 * Change TeX backslash processing so that it only assumes alpha
63 * characters and the commonly-used "@" character are part of macro
64 * names, and so that any other backslashed character (specifically
65 * dollar signs) is skipped.
66 *
67 * Revision 1.39  1995/01/08  23:23:54  geoff
68 * Fix typos in a couple of comments.
69 *
70 * Revision 1.38  1995/01/03  19:24:14  geoff
71 * Add code to handle the LaTeX \verb command.
72 *
73 * Revision 1.37  1994/12/27  23:08:54  geoff
74 * Fix a bug in TeX backslash processing that caused ispell to become
75 * confused when it encountered an optional argument to a
76 * double-backslash command.  Be a little smarter about scanning for
77 * curly-brace matches, so that we avoid missing a math-mode transition
78 * during the scan.
79 *
80 * Revision 1.36  1994/10/25  05:46:34  geoff
81 * Recognize a few more Latex commands: pagestyle, pagenumbering,
82 * setcounter, addtocounter, setlength, addtolength, settowidth.
83 *
84 * Revision 1.35  1994/10/18  04:03:19  geoff
85 * Add code to skip hex numbers if they're preceded by '0x'.
86 *
87 * Revision 1.34  1994/10/04  03:51:24  geoff
88 * Modify the parsing so that TeX commands are ignored even within
89 * comments, but do not affect the overall parsing state.  (This is
90 * slightly imperfect, in that some types of modality are ignored when
91 * comments are entered.  But it should solve nearly all the problems
92 * with commented-out TeX commands.)  This also fixes a couple of minor
93 * bugs with TeX deformatting.
94 *
95 * Revision 1.33  1994/10/03  17:06:07  geoff
96 * Remember to use contextoffset when reporting complete misses
97 *
98 * Revision 1.32  1994/08/31  05:58:41  geoff
99 * Report the offset-within-line correctly in -a mode even if the line is
100 * longer than BUFSIZ characters.
101 *
102 * Revision 1.31  1994/05/25  04:29:28  geoff
103 * If two boundary characters appear in a row, consider it the end of the
104 * word.
105 *
106 * Revision 1.30  1994/05/17  06:44:08  geoff
107 * Add the new argument to all calls to good and compoundgood.
108 *
109 * Revision 1.29  1994/03/16  06:30:41  geoff
110 * Don't lose track of math mode when an array environment is embedded.
111 *
112 * Revision 1.28  1994/03/15  05:31:57  geoff
113 * Add TeX_strncmp, which allows us to handle AMS-TeX constructs like
114 * \endroster without getting confused.
115 *
116 * Revision 1.27  1994/02/14  00:34:53  geoff
117 * Pass length arguments to correct().
118 *
119 * Revision 1.26  1994/01/25  07:11:25  geoff
120 * Get rid of all old RCS log lines in preparation for the 3.1 release.
121 *
122 */
123
124#include <ctype.h>
125#include "config.h"
126#include "ispell.h"
127#include "proto.h"
128#include "msgs.h"
129
130static char *   skiptoword P ((char * bufp));
131char *          skipoverword P ((char * bufp));
132void            checkline P ((FILE * ofile));
133static int      TeX_math_end P ((char ** bufp));
134static int      TeX_math_begin P ((char ** bufp));
135static int      TeX_LR_begin P ((char ** bufp));
136static int      TeX_LR_check P ((int begin_p, char ** bufp));
137static void     TeX_skip_args P ((char ** bufp));
138static int      TeX_math_check P ((int cont_char, char ** bufp));
139static void     TeX_skip_parens P ((char ** bufp));
140static void     TeX_open_paren P ((char ** bufp));
141static void     TeX_skip_check P ((char ** bufp));
142static int      TeX_strncmp P ((char * a, char * b, int n));
143
144#define ISTEXTERM(c)   (((c) == TEXLEFTCURLY) || \
145                        ((c) == TEXRIGHTCURLY) || \
146                        ((c) == TEXLEFTSQUARE) || \
147                        ((c) == TEXRIGHTSQUARE))
148#define ISMATHCH(c)    (((c) == TEXBACKSLASH) || \
149                        ((c) == TEXDOLLAR) || \
150                        ((c) == TEXPERCENT))
151
152static int          TeX_comment = 0;
153
154/*
155 * The following variables are used to save the parsing state when
156 * processing comments.  This allows comments to be parsed without
157 * affecting the overall nesting.
158 */
159
160static int save_math_mode;
161static char save_LaTeX_Mode;
162
163static char * skiptoword (bufp)         /* Skip to beginning of a word */
164    char *      bufp;
165    {
166
167    while (*bufp
168      &&  ((!isstringch (bufp, 0)  &&  !iswordch (chartoichar (*bufp)))
169        ||  isboundarych (chartoichar (*bufp))
170        ||  (tflag  &&  (math_mode & 1)))
171      )
172        {
173        /* check paren necessity... */
174        if (tflag) /* TeX or LaTeX stuff */
175            {
176            /* Odd numbers mean we are in "math mode" */
177            /* Even numbers mean we are in LR or */
178            /* paragraph mode */
179            if (*bufp == TEXPERCENT)
180                {
181                if (!TeX_comment)
182                    {
183                    save_math_mode = math_mode;
184                    save_LaTeX_Mode = LaTeX_Mode;
185                    math_mode = 0;
186                    LaTeX_Mode = 'P';
187                    TeX_comment = 1;
188                    }
189                }
190            else if (math_mode & 1)
191                {
192                if ((LaTeX_Mode == 'e'  &&  TeX_math_check('e', &bufp))
193                  || (LaTeX_Mode == 'm'  &&  TeX_LR_check(1, &bufp)))
194                    math_mode--;    /* end math mode */
195                else
196                    {
197                    while (*bufp  && !ISMATHCH(*bufp))
198                        bufp++;
199                    if (*bufp == 0)
200                        break;
201                    if (TeX_math_end(&bufp))
202                        math_mode--;
203                    }
204                if (math_mode < 0)
205                    {
206                    (void) fprintf (stderr,
207                     DEFMT_C_TEX_MATH_ERROR);
208                    math_mode = 0;
209                    }
210                }
211            else
212                {
213                if (math_mode > 1
214                  &&  *bufp == TEXRIGHTCURLY
215                  &&  (math_mode < (math_mode & 127) * 128))
216                    math_mode--;    /* re-enter math */
217                else if (LaTeX_Mode == 'm'
218                    || (math_mode && (math_mode >= (math_mode & 127) * 128)
219                  &&  (TeX_strncmp(bufp, "\\end", 4)
220                    == 0)))
221                    {
222                    if (TeX_LR_check(0, &bufp))
223                        math_mode--;
224                    }
225                else if (LaTeX_Mode == 'b'  &&  TeX_math_check('b', &bufp))
226                    {
227                    /* continued begin */
228                    math_mode++;
229                    }
230                else if (LaTeX_Mode == 'r')
231                    {
232                    /* continued "reference" */
233                    TeX_skip_parens(&bufp);
234                    LaTeX_Mode = 'P';
235                    }
236                else if (TeX_math_begin(&bufp))
237                    /* checks references and */
238                    /* skips \ commands */
239                    math_mode++;
240                }
241            if (*bufp == 0)
242                break;
243            }
244        else                    /* formatting escape sequences */
245            {
246            if (*bufp == NRBACKSLASH)
247                {
248                switch ( bufp[1] )
249                    {
250                    case 'f':
251                        if(bufp[2] == NRLEFTPAREN)
252                            {
253                            /* font change: \f(XY */
254                            bufp += 5;
255                            }
256                        else
257                            {
258                            /* ) */
259                            /* font change: \fX */
260                            bufp += 3;
261                            }
262                        continue;
263                    case 's':
264                        /* size change */
265                        bufp += 2;
266                        if (*bufp == '+'  ||  *bufp == '-')
267                            bufp++;
268                        /* This looks wierd 'cause we
269                        ** assume *bufp is now a digit.
270                        */
271                        bufp++;
272                        if (isdigit (*bufp))
273                            bufp++;
274                        continue;
275                    default:
276                        if (bufp[1] == NRLEFTPAREN)
277                            {
278                            /* extended char set */
279                            /* escape:  \(XX */
280                            /* ) */
281                            bufp += 4;
282                            continue;
283                            }
284                        else if (bufp[1] == NRSTAR)
285                            {
286                            if (bufp[2] == NRLEFTPAREN)
287                                bufp += 5;
288                            else
289                                bufp += 3;
290                            continue;
291                            }
292                        break;
293                    }
294                }
295            }
296        /*
297         * Skip hex numbers, but not if we're in non-terse askmode.
298         * (In that case, we'd lose sync if we skipped hex.)
299         */
300        if (*bufp == '0'
301          &&  (bufp[1] == 'x'  ||  bufp[1] == 'X')
302          &&  (terse  ||  !aflag))
303            {
304            bufp += 2;
305            while (isxdigit (*bufp))
306                bufp++;
307            }
308        else
309            bufp++;
310        }
311    if (*bufp == '\0')
312        {
313        if (TeX_comment)
314            {
315            math_mode = save_math_mode;
316            LaTeX_Mode = save_LaTeX_Mode;
317            TeX_comment = 0;
318            }
319        }
320    return bufp;
321    }
322
323char * skipoverword (bufp)      /* Return pointer to end of a word */
324    register char *     bufp;   /* Start of word -- MUST BE A REAL START */
325    {
326    register char *     lastboundary;
327    register int        scharlen; /* Length of a string character */
328
329    lastboundary = NULL;
330    for (  ;  ;  )
331        {
332        if (*bufp == '\0')
333            {
334            if (TeX_comment)
335                {
336                math_mode = save_math_mode;
337                LaTeX_Mode = save_LaTeX_Mode;
338                TeX_comment = 0;
339                }
340            break;
341            }
342        else if (l_isstringch(bufp, scharlen, 0))
343            {
344            bufp += scharlen;
345            lastboundary = NULL;
346            }
347        /*
348        ** Note that we get here if a character satisfies
349        ** isstringstart() but isn't in the string table;  this
350        ** allows string characters to start with word characters.
351        */
352        else if (iswordch (chartoichar (*bufp)))
353            {
354            bufp++;
355            lastboundary = NULL;
356            }
357        else if (isboundarych (chartoichar (*bufp)))
358            {
359            if (lastboundary == NULL)
360                lastboundary = bufp;
361            else if (lastboundary == bufp - 1)
362                break;                  /* Double boundary -- end of word */
363            bufp++;
364            }
365        else
366            break;                      /* End of the word */
367        }
368    /*
369    ** If the word ended in one or more boundary characters,
370    ** the address of the first of these is in lastboundary, and it
371    ** is the end of the word.  Otherwise, bufp is the end.
372    */
373    return (lastboundary != NULL) ? lastboundary : bufp;
374    }
375
376void checkline (ofile)
377    FILE *              ofile;
378    {
379    register char *     p;
380    register char *     endp;
381    int                 hadlf;
382    register int        len;
383    register int        i;
384    int                 ilen;
385
386    currentchar = contextbufs[0];
387    len = strlen (contextbufs[0]) - 1;
388    hadlf = contextbufs[0][len] == '\n';
389    if (hadlf)
390        contextbufs[0][len] = 0;
391
392    if (!tflag)
393        {
394        /* skip over .if */
395        if (*currentchar == NRDOT
396          &&  (strncmp (currentchar + 1, "if t", 4) == 0
397            ||  strncmp (currentchar + 1, "if n", 4) == 0))
398            {
399            copyout (&currentchar,5);
400            while (*currentchar
401              &&  myspace (chartoichar (*currentchar)))
402                copyout (&currentchar, 1);
403            }
404
405        /* skip over .ds XX or .nr XX */
406        if (*currentchar == NRDOT
407          &&  (strncmp (currentchar + 1, "ds ", 3) == 0
408            ||  strncmp (currentchar + 1, "de ", 3) == 0
409            ||  strncmp (currentchar + 1, "nr ", 3) == 0))
410            {
411            copyout (&currentchar, 4);
412            while (*currentchar
413              &&  myspace (chartoichar (*currentchar)))
414                copyout(&currentchar, 1);
415            while (*currentchar
416              &&  !myspace (chartoichar (*currentchar)))
417                copyout(&currentchar, 1);
418            if (*currentchar == 0)
419                {
420                if (!lflag  &&  (aflag  ||  hadlf))
421                    (void) putc ('\n', ofile);
422                return;
423                }
424            }
425        }
426
427
428    /* if this is a formatter command, skip over it */
429    if (!tflag && *currentchar == NRDOT)
430        {
431        while (*currentchar  &&  !myspace (chartoichar (*currentchar)))
432            {
433            if (!aflag && !lflag)
434                (void) putc (*currentchar, ofile);
435            currentchar++;
436            }
437        if (*currentchar == 0)
438            {
439            if (!lflag  &&  (aflag  ||  hadlf))
440                (void) putc ('\n', ofile);
441            return;
442            }
443        }
444
445    for (  ;  ;  )
446        {
447        p = skiptoword (currentchar);
448        if (p != currentchar)
449            copyout (&currentchar, p - currentchar);
450
451        if (*currentchar == 0)
452            break;
453
454        p = ctoken;
455        endp = skipoverword (currentchar);
456        while (currentchar < endp  &&  p < ctoken + sizeof ctoken - 1)
457            *p++ = *currentchar++;
458        *p = 0;
459        if (strtoichar (itoken, ctoken, INPUTWORDLEN * sizeof (ichar_t), 0))
460            (void) fprintf (stderr, WORD_TOO_LONG (ctoken));
461        ilen = icharlen (itoken);
462
463        if (lflag)
464            {
465            if (ilen > minword
466              &&  !good (itoken, 0, 0, 0, 0)
467              &&  !cflag  &&  !compoundgood (itoken, 0))
468                (void) fprintf (ofile, "%s\n", ctoken);
469            }
470        else
471            {
472            if (aflag)
473                {
474                if (ilen <= minword)
475                    {
476                    /* matched because of minword */
477                    if (!terse)
478                        (void) fprintf (ofile, "*\n");
479                    continue;
480                    }
481                if (good (itoken, 0, 0, 0, 0))
482                    {
483                    if (hits[0].prefix == NULL
484                      &&  hits[0].suffix == NULL)
485                        {
486                        /* perfect match */
487                        if (!terse)
488                            (void) fprintf (ofile, "*\n");
489                        }
490                    else if (!terse)
491                        {
492                        /* matched because of root */
493                        (void) fprintf (ofile, "+ %s\n",
494                          hits[0].dictent->word);
495                        }
496                    }
497                else if (compoundgood (itoken, 0))
498                    {
499                    /* compound-word match */
500                    if (!terse)
501                        (void) fprintf (ofile, "-\n");
502                    }
503                else
504                    {
505                    makepossibilities (itoken);
506                    if (pcount)
507                        {
508                        /*
509                        ** print &  or ?, ctoken, then
510                        ** character offset, possibility
511                        ** count, and the possibilities.
512                        */
513                        (void) fprintf (ofile, "%c %s %d %d",
514                          easypossibilities ? '&' : '?',
515                          ctoken,
516                          easypossibilities,
517                          (int) ((currentchar - contextbufs[0])
518                            - strlen (ctoken)) + contextoffset);
519                        for (i = 0;  i < MAXPOSSIBLE;  i++)
520                            {
521                            if (possibilities[i][0] == 0)
522                                break;
523                            (void) fprintf (ofile, "%c %s",
524                              i ? ',' : ':', possibilities[i]);
525                            }
526                        (void) fprintf (ofile, "\n");
527                        }
528                    else
529                        {
530                        /*
531                        ** No possibilities found for word TOKEN
532                        */
533                        (void) fprintf (ofile, "# %s %d\n",
534                          ctoken,
535                          (int) ((currentchar - contextbufs[0])
536                            - strlen (ctoken)) + contextoffset);
537                        }
538                    }
539                }
540            else
541                {
542                if (!quit)
543                   correct (ctoken, sizeof ctoken, itoken, sizeof itoken,
544                     &currentchar);
545                }
546            }
547        if (!aflag  &&  !lflag)
548           (void) fprintf (ofile, "%s", ctoken);
549        }
550
551    if (!lflag  &&  (aflag  ||  hadlf))
552       (void) putc ('\n', ofile);
553   }
554
555/* must check for \begin{mbox} or whatever makes new text region. */
556static int TeX_math_end (bufp)
557    char **     bufp;
558    {
559
560    if (**bufp == TEXDOLLAR)
561        {
562        if ((*bufp)[1] == TEXDOLLAR)
563            (*bufp)++;
564        return 1;
565        }
566    else if (**bufp == TEXPERCENT)
567        {
568        if (!TeX_comment)
569            {
570            save_math_mode = math_mode;
571            save_LaTeX_Mode = LaTeX_Mode;
572            math_mode = 0;
573            LaTeX_Mode = 'P';
574            TeX_comment = 1;
575            }
576        return 0;
577        }
578    /* processing extended TeX command */
579    (*bufp)++;
580    if (**bufp == TEXRIGHTPAREN  ||  **bufp == TEXRIGHTSQUARE)
581        return 1;
582    if (TeX_LR_begin (bufp))    /* check for switch back to LR mode */
583        return 1;
584    if (TeX_strncmp (*bufp, "end", 3) == 0)
585        /* find environment that is ending */
586        return TeX_math_check ('e', bufp);
587    else
588        return 0;
589    }
590
591static int TeX_math_begin (bufp)
592    char **     bufp;
593    {
594
595    if (**bufp == TEXDOLLAR)
596        {
597        if ((*bufp)[1] == TEXDOLLAR)
598            (*bufp)++;
599        return 1;
600        }
601    while (**bufp == TEXBACKSLASH)
602        {
603        (*bufp)++; /* check for null char here? */
604        if (**bufp == TEXLEFTPAREN  ||  **bufp == TEXLEFTSQUARE)
605            return 1;
606        else if (!isalpha(**bufp)  &&  **bufp != '@')
607            {
608            (*bufp)++;
609            continue;
610            }
611        else if (TeX_strncmp (*bufp, "begin", 5) == 0)
612            {
613            if (TeX_math_check ('b', bufp))
614                return 1;
615            else
616                (*bufp)--;
617            }
618        else
619            {
620            TeX_skip_check (bufp);
621            return 0;
622            }
623        }
624      /*
625       * Ignore references for the tib (1) bibliography system, that
626       * is, text between a ``[.'' or ``<.'' and ``.]'' or ``.>''.
627       * We don't care whether they match, tib doesn't care either.
628       *
629       * A limitation is that the entire tib reference must be on one
630       * line, or we break down and check the remainder anyway.
631       */
632    if ((**bufp == TEXLEFTSQUARE  ||  **bufp == TEXLEFTANGLE)
633      &&  (*bufp)[1] == TEXDOT)
634        {
635        (*bufp)++;
636        while (**bufp)
637            {
638            if (*(*bufp)++ == TEXDOT
639              &&  (**bufp == TEXRIGHTSQUARE  ||  **bufp == TEXRIGHTANGLE))
640                return TeX_math_begin (bufp);
641            }
642        return 0;
643        }
644    else
645        return 0;
646    }
647
648static int TeX_LR_begin (bufp)
649    char **     bufp;
650    {
651
652    if ((TeX_strncmp (*bufp, "mbox", 4) == 0)
653      ||  (TeX_strncmp (*bufp, "makebox", 7) == 0)
654      ||  (TeX_strncmp (*bufp, "fbox", 4) == 0)
655      || (TeX_strncmp (*bufp, "framebox", 8) == 0))
656        math_mode += 2;
657    else if ((TeX_strncmp(*bufp, "parbox", 6) == 0)
658      || (TeX_strncmp(*bufp, "raisebox", 8) == 0))
659        {
660        math_mode += 2;
661        TeX_open_paren (bufp);
662        if (**bufp)
663            (*bufp)++;
664        else
665            LaTeX_Mode = 'r'; /* same as reference -- skip {} */
666        }
667    else if (TeX_strncmp(*bufp, "begin", 5) == 0)
668        return TeX_LR_check (1, bufp);  /* minipage */
669    else
670        return 0;
671
672    /* skip tex command name and optional or width arguments. */
673    TeX_open_paren (bufp);
674    return 1;
675    }
676
677static int TeX_LR_check (begin_p, bufp)
678    int         begin_p;
679    char **     bufp;
680    {
681
682    TeX_open_paren (bufp);
683    if (**bufp == 0)    /* { */
684        {
685        LaTeX_Mode = 'm';
686        return 0;       /* remain in math mode until '}' encountered. */
687        }
688    else
689        LaTeX_Mode = 'P';
690    if (strncmp (++(*bufp), "minipage", 8) == 0)
691        {
692        TeX_skip_parens (bufp);
693        if (**bufp)
694            (*bufp)++;
695        if (begin_p)
696            {
697            TeX_skip_parens (bufp); /* now skip opt. args if on this line. */
698            math_mode += 2;
699            /* indicate minipage mode. */
700            math_mode += ((math_mode & 127) - 1) * 128;
701            }
702        else
703            {
704            math_mode -= (math_mode & 127) * 128;
705            if (math_mode < 0)
706                {
707                (void) fprintf (stderr, DEFMT_C_LR_MATH_ERROR);
708                math_mode = 1;
709                }
710            }
711        return 1;
712        }
713    (*bufp)--;
714    return 0;
715    }
716
717/* Skips the begin{ARG}, and optionally up to two {PARAM}{PARAM}'s to
718 *  the begin if they are required.  However, Only skips if on this line.
719 */
720static void TeX_skip_args (bufp)
721    char **     bufp;
722    {
723    register int skip_cnt = 0; /* Max of 2. */
724
725    if (strncmp(*bufp, "tabular", 7) == 0
726      ||  strncmp(*bufp, "minipage", 8) == 0)
727        skip_cnt++;
728    if (strncmp(*bufp, "tabular*", 8) == 0)
729        skip_cnt++;
730    TeX_skip_parens (bufp);     /* Skip to the end of the \begin{} parens */
731    if (**bufp)
732        (*bufp)++;
733    else
734        return;
735    if (skip_cnt--)
736        TeX_skip_parens (bufp); /* skip 1st {PARAM}. */
737    else
738        return;
739    if (**bufp)
740        (*bufp)++;
741    else
742        return;
743    if (skip_cnt)
744        TeX_skip_parens (bufp); /* skip to end of 2nd {PARAM}. */
745    }
746
747static int TeX_math_check (cont_char, bufp)
748    int         cont_char;
749    char **     bufp;
750    {
751
752    TeX_open_paren (bufp);
753    /* Check for end of line, continue later. */
754    if (**bufp == 0)
755        {
756        LaTeX_Mode = (char) cont_char;
757        return 0;
758        }
759    else
760        LaTeX_Mode = 'P';
761
762    if (strncmp (++(*bufp), "equation", 8) == 0
763      ||  strncmp (*bufp, "eqnarray", 8) == 0
764      ||  strncmp (*bufp, "displaymath", 11) == 0
765      ||  strncmp (*bufp, "picture", 7) == 0
766#ifdef IGNOREBIB
767      ||  strncmp (*bufp, "thebibliography", 15) == 0
768#endif
769      ||  strncmp (*bufp, "math", 4) == 0)
770        {
771        (*bufp)--;
772        TeX_skip_parens (bufp);
773        return 1;
774        }
775    if (cont_char == 'b')
776        TeX_skip_args (bufp);
777    else
778        TeX_skip_parens (bufp);
779    return 0;
780    }
781
782static void TeX_skip_parens (bufp)
783    char **     bufp;
784    {
785
786    while (**bufp  &&  **bufp != TEXRIGHTCURLY  &&  **bufp != TEXDOLLAR)
787        (*bufp)++;
788    }
789
790static void TeX_open_paren (bufp)
791    char **     bufp;
792    {
793    while (**bufp  &&  **bufp != TEXLEFTCURLY  &&  **bufp != TEXDOLLAR)
794        (*bufp)++;
795    }
796
797static void TeX_skip_check (bufp)
798    char **     bufp;
799    {
800    int         skip_ch;
801
802    if (TeX_strncmp(*bufp, "end", 3) == 0
803      ||  TeX_strncmp(*bufp, "vspace", 6) == 0
804      ||  TeX_strncmp(*bufp, "hspace", 6) == 0
805      ||  TeX_strncmp(*bufp, "cite", 4) == 0
806      ||  TeX_strncmp(*bufp, "ref", 3) == 0
807      ||  TeX_strncmp(*bufp, "parbox", 6) == 0
808      ||  TeX_strncmp(*bufp, "label", 5) == 0
809      ||  TeX_strncmp(*bufp, "input", 5) == 0
810      ||  TeX_strncmp(*bufp, "nocite", 6) == 0
811      ||  TeX_strncmp(*bufp, "include", 7) == 0
812      ||  TeX_strncmp(*bufp, "includeonly", 11) == 0
813      ||  TeX_strncmp(*bufp, "documentstyle", 13) == 0
814      ||  TeX_strncmp(*bufp, "documentclass", 13) == 0
815      ||  TeX_strncmp(*bufp, "usepackage", 10) == 0
816      ||  TeX_strncmp(*bufp, "pagestyle", 9) == 0
817      ||  TeX_strncmp(*bufp, "pagenumbering", 13) == 0
818#ifndef IGNOREBIB
819      ||  TeX_strncmp(*bufp, "bibliography", 12) == 0
820      ||  TeX_strncmp(*bufp, "bibitem", 7) == 0
821#endif
822      ||  TeX_strncmp(*bufp, "hyphenation", 11) == 0
823      ||  TeX_strncmp(*bufp, "pageref", 7) == 0)
824        {
825        TeX_skip_parens (bufp);
826        if (**bufp == 0)
827            LaTeX_Mode = 'r';
828        }
829    else if (TeX_strncmp(*bufp, "rule", 4) == 0         /* skip two args. */
830      ||  TeX_strncmp(*bufp, "setcounter", 10) == 0
831      ||  TeX_strncmp(*bufp, "addtocounter", 12) == 0
832      ||  TeX_strncmp(*bufp, "setlength", 9) == 0
833      ||  TeX_strncmp(*bufp, "addtolength", 11) == 0
834      ||  TeX_strncmp(*bufp, "settowidth", 10) == 0)
835        {
836        TeX_skip_parens (bufp);
837        if (**bufp == 0)        /* Only skips one {} if not on same line. */
838            LaTeX_Mode = 'r';
839        else                    /* Skip second arg. */
840            {
841            (*bufp)++;
842            TeX_skip_parens (bufp);
843            if (**bufp == 0)
844                LaTeX_Mode = 'r';
845            }
846        }
847    else if (TeX_strncmp (*bufp, "verb", 4) == 0)
848        {
849        skip_ch = (*bufp)[4];
850        *bufp += 5;
851        while (**bufp != skip_ch  &&  **bufp != '\0')
852            (*bufp)++;
853        }
854    else
855        {
856        /* Optional tex arguments sometimes should and
857        ** sometimes shouldn't be checked
858        ** (eg \section [C Programming] {foo} vs
859        **     \rule [3em] {0.015in} {5em})
860        ** SO -- we'll always spell-check it rather than make a
861        ** full LaTeX parser.
862        */
863
864        /* Must look at the space after the command. */
865        while (isalpha(**bufp)  ||  **bufp == '@')
866            (*bufp)++;
867        /*
868        ** Our caller expects to skip over a single character.  So we
869        ** need to back up by one.  Ugh.
870        */
871        (*bufp)--;
872        }
873    }
874
875/*
876 * TeX_strncmp is like strncmp, except that it returns inequality if
877 * the following character of a is alphabetic.  We do not use
878 * iswordch here because TeX itself won't normally accept
879 * nonalphabetics (except maybe on ISO Latin-1 installations?  I'll
880 * have to look into that).  As a special hack, because LaTeX uses the
881 * @ sign so much, we'll also accept that character.
882 *
883 * Properly speaking, the @ sign should be settable in the hash file
884 * header, but I doubt that it varies, and I don't want to change the
885 * syntax of affix files right now.
886 */
887static int TeX_strncmp (a, b, n)
888    char *      a;              /* Strings to compare */
889    char *      b;              /* ... */
890    int         n;              /* Number of characters to compare */
891    {
892    int         cmpresult;      /* Result of calling strncmp */
893
894    cmpresult = strncmp (a, b, n);
895    if (cmpresult == 0)
896        {
897        if (isascii (a[n])  &&  isalpha (a[n]))
898            return 1;           /* Force inequality if alpha follows */
899        }
900    return cmpresult;
901    }
Note: See TracBrowser for help on using the repository browser.