summaryrefslogtreecommitdiff
path: root/Build/source/texk/chktex/chktex-1.7.1/FindErrs.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/chktex/chktex-1.7.1/FindErrs.c')
-rw-r--r--Build/source/texk/chktex/chktex-1.7.1/FindErrs.c1967
1 files changed, 0 insertions, 1967 deletions
diff --git a/Build/source/texk/chktex/chktex-1.7.1/FindErrs.c b/Build/source/texk/chktex/chktex-1.7.1/FindErrs.c
deleted file mode 100644
index 5877d7ec011..00000000000
--- a/Build/source/texk/chktex/chktex-1.7.1/FindErrs.c
+++ /dev/null
@@ -1,1967 +0,0 @@
-/*
- * ChkTeX, error searching & report routines.
- * Copyright (C) 1995-96 Jens T. Berger Thielemann
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- * Contact the author at:
- * Jens Berger
- * Spektrumvn. 4
- * N-0666 Oslo
- * Norway
- * E-mail: <jensthi@ifi.uio.no>
- *
- *
- */
-
-
-#include "ChkTeX.h"
-#include "FindErrs.h"
-#include "OpSys.h"
-#include "Utility.h"
-#include "Resource.h"
-
-#if !(defined HAVE_DECL_STPCPY && HAVE_DECL_STPCPY)
-static inline char *
-stpcpy(char *dest, const char *src)
-{
- return strcpy(dest, src) + strlen(src);
-}
-#endif
-
-#if HAVE_PCRE || HAVE_POSIX_ERE
-
-#if HAVE_PCRE
-#include <pcreposix.h>
-#else
-#include <regex.h>
-#endif
-
-#define REGEX_FLAGS REG_EXTENDED
-#define NUM_MATCHES 10
-#define ERROR_STRING_SIZE 100
-
-regex_t* RegexArray = NULL;
-regex_t* SilentRegex = NULL;
-int NumRegexes = 0;
-
-#endif
-
-/***************************** ERROR MESSAGES ***************************/
-
-#undef MSG
-#define MSG(num, type, inuse, ctxt, text) {num, type, inuse, ctxt, text},
-
-struct ErrMsg LaTeXMsgs[emMaxFault + 1] = {
- ERRMSGS {emMaxFault, etErr, iuOK, 0, INTERNFAULT}
-};
-
-#define istex(c) (isalpha((unsigned char)c) || (AtLetter && (c == '@')))
-#define CTYPE(func) \
-static int my_##func(int c) \
-{ \
- return(func(c)); \
-}
-
-#define SUPPRESSED_ON_LINE(c) (LineSuppressions & ((uint64_t)1<<c))
-
-#define INUSE(c) \
- ((LaTeXMsgs[(enum ErrNum) c].InUse == iuOK) && !SUPPRESSED_ON_LINE(c))
-
-#define PSERR2(pos,len,err,a,b) \
- PrintError(CurStkName(&InputStack), RealBuf, pos, len, Line, err, a, b)
-
-#define PSERRA(pos,len,err,a) \
- PrintError(CurStkName(&InputStack), RealBuf, pos, len, Line, err, a)
-
-#define HEREA(len, err, a) PSERRA(BufPtr - Buf - 1, len, err, a)
-#define PSERR(pos,len,err) PSERRA(pos,len,err,"")
-
-#define HERE(len, err) HEREA(len, err, "")
-
-#define SKIP_BACK(ptr, c, check) \
- while((c = *ptr--)) \
- { \
- if (!(check)) break; \
- } \
- ptr++;
-
-#define SKIP_AHEAD(ptr, c, check) \
- while((c = *ptr++)) \
- { \
- if (!(check)) \
- break; \
- } \
- ptr--;
-
-
-/* -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- -=><=- */
-
-/*
- * A list of characters LaTeX considers as an end-of-sentence characters, which
- * should be detected when whether sentence spacing is correct.
- *
- */
-static const char LTX_EosPunc[] = { '.', ':', '?', '!', 0 };
-
-/*
- * General punctuation characters used on your system.
- */
-static const char LTX_GenPunc[] = { ',', ';', 0 };
-
-/*
- * A list of characters LaTeX considers as an small punctuation characters,
- * which should not be preceded by a \/.
- */
-static const char LTX_SmallPunc[] = { '.', ',', 0 };
-
-/*
- * String used to delimit a line suppression. This string must be
- * followed immediately by the number of the warning to be suppressed.
- * If more than one warning is to be suppressed, then multiple copies
- * of LineSuppDelim+number must be used.
- */
-const char LineSuppDelim[] = "chktex ";
-
-/*
- * String used to delimit a file suppression. This string must be
- * followed immediately by the number of the warning to be suppressed.
- * If more than one warning is to be suppressed, then multiple copies
- * of FileSuppDelim+number must be used.
- */
-const char FileSuppDelim[] = "chktex-file ";
-
-/*
- * A bit field used to hold the suppressions for the current line.
- */
-static uint64_t LineSuppressions;
-/*
- * A bit field used to hold the suppressions of numbered user warnings
- * for the current line.
- */
-static uint64_t UserLineSuppressions;
-
-static unsigned long Line;
-
-static const char *RealBuf;
-static char *LineCpy;
-static char *BufPtr;
-
-static int ItFlag = efNone;
-static int MathFlag = efNone;
-
-NEWBUF(Buf, BUFSIZ);
-NEWBUF(CmdBuffer, BUFSIZ);
-NEWBUF(ArgBuffer, BUFSIZ);
-
-static enum ErrNum PerformCommand(const char *Cmd, char *Arg);
-
-#ifdef isdigit
-CTYPE(isdigit)
-#else
-# define my_isdigit isdigit
-#endif
-
-#ifdef isalpha
-CTYPE(isalpha)
-#else
-# define my_isalpha isalpha
-#endif
-
-/*
- * Reads in a TeX token from Src and puts it in Dest.
- *
- */
-
-
-static char *GetLTXToken(char *Src, char *Dest)
-{
- int Char;
-
- if (Src && *Src)
- {
- if (*Src == '\\')
- {
- *Dest++ = *Src++;
- Char = *Dest++ = *Src++;
-
- if (istex(Char))
- {
- while (istex(Char))
- Char = *Dest++ = *Src++;
-
- Src--;
- Dest--;
- }
-
- }
- else
- *Dest++ = *Src++;
- *Dest = 0;
- }
- else
- Src = NULL;
-
- return (Src);
-}
-
-
-/*
- * Scans the `SrcBuf' for a LaTeX arg, and puts that arg into `Dest'.
- * `Until' specifies what we'll copy. Assume the text is
- * "{foo}bar! qux} baz".
- * GET_TOKEN => "{foo}"
- * GET_STRIP_TOKEN => "foo"
- * '!' => "{foo}bar!" (i.e. till the first "!")
- * Returns NULL if we can't find the argument, ptr to the first character
- * after the argument in other cases.
- *
- * If one of the tokens found is in the wl wordlist, and we're in the
- * outer most paren, and Until isn't a single character, we'll stop.
- * You may pass NULL as wl.
- *
- * We assume that you've previously skipped over leading spaces.
- *
- */
-
-#define GET_TOKEN 256
-#define GET_STRIP_TOKEN 257
-
-static char *GetLTXArg(char *SrcBuf, char *OrigDest, const int Until,
- struct WordList *wl)
-{
- char *Retval;
- char *TmpPtr;
- char *Dest = OrigDest;
- unsigned long DeliCnt = 0;
-
- *Dest = 0;
- TmpPtr = SrcBuf;
-
- switch (Until)
- {
- case GET_STRIP_TOKEN:
- case GET_TOKEN:
- while ((Retval = GetLTXToken(TmpPtr, Dest)))
- {
- switch (*Dest)
- {
- case '{':
- DeliCnt++;
- break;
- case '}':
- DeliCnt--;
- }
- Dest += Retval - TmpPtr;
- TmpPtr = Retval;
-
- if (!DeliCnt || ((DeliCnt == 1) && wl && HasWord(Dest, wl)))
- break;
- }
-
- if (Retval && (*OrigDest == '{') && (Until == GET_STRIP_TOKEN))
- {
- int len = strlen(OrigDest+1);
- memmove(OrigDest, OrigDest + 1, len + 1);
- /* Strip the last '}' off */
- OrigDest[len-1] = 0;
- }
- break;
- default:
- DeliCnt = TRUE;
- while ((Retval = GetLTXArg(TmpPtr, Dest, GET_TOKEN, NULL)))
- {
- if (*Dest == Until)
- DeliCnt = FALSE;
-
- Dest += Retval - TmpPtr;
- TmpPtr = Retval;
-
- if (!DeliCnt)
- break;
- }
- break;
- }
- *Dest = 0;
-
- return (Retval);
-}
-
-
-static char *MakeCpy(void)
-{
- if (!LineCpy)
- LineCpy = strdup(RealBuf);
-
- if (!LineCpy)
- PrintPrgErr(pmStrDupErr);
-
- return (LineCpy);
-}
-
-static char *PreProcess(void)
-{
- char *TmpPtr;
-
- /* Reset any line suppressions */
-
- LineSuppressions = FileSuppressions;
- UserLineSuppressions = UserFileSuppressions;
-
- /* Kill comments. */
- strcpy(Buf, RealBuf);
-
- TmpPtr = Buf;
-
- while ((TmpPtr = strchr(TmpPtr, '%')))
- {
- char *EscapePtr = TmpPtr;
- int NumBackSlashes = 0;
- while (EscapePtr != Buf && EscapePtr[-1] == '\\')
- {
- ++NumBackSlashes;
- --EscapePtr;
- }
-
- /* If there is an even number of backslashes, then it's a comment. */
- if ((NumBackSlashes % 2) == 0)
- {
- PSERR(TmpPtr - Buf, 1, emComment);
- *TmpPtr = 0;
- /* Check for line suppressions */
- if (!NoLineSupp)
- {
- int error;
- const int MaxSuppressionBits = 63;
-
- /* Convert to lowercase to compare with LineSuppDelim */
- EscapePtr = ++TmpPtr; /* move past NUL terminator */
- while ( *EscapePtr )
- {
- *EscapePtr = tolower(*EscapePtr);
- ++EscapePtr;
- }
-
- EscapePtr = TmpPtr; /* Save it for later */
- while ((TmpPtr = strstr(TmpPtr, FileSuppDelim))) {
- TmpPtr += STRLEN(FileSuppDelim);
- error = atoi(TmpPtr);
-
- if (abs(error) > MaxSuppressionBits)
- {
- PrintPrgErr(pmSuppTooHigh, error, MaxSuppressionBits);
- }
- if (error > 0)
- {
- FileSuppressions |= ((uint64_t)1 << error);
- LineSuppressions |= ((uint64_t)1 << error);
- }
- else
- {
- UserFileSuppressions |= ((uint64_t)1 << (-error));
- UserLineSuppressions |= ((uint64_t)1 << (-error));
- }
- }
- TmpPtr = EscapePtr;
-
- while ((TmpPtr = strstr(TmpPtr, LineSuppDelim))) {
-
- TmpPtr += STRLEN(LineSuppDelim);
- error = atoi(TmpPtr);
-
- if (abs(error) > MaxSuppressionBits)
- {
- PrintPrgErr(pmSuppTooHigh, error, MaxSuppressionBits);
- }
-
- if (error > 0)
- {
- LineSuppressions |= ((uint64_t)1 << error);
- }
- else
- {
- UserLineSuppressions |= ((uint64_t)1 << (-error));
- }
- }
- }
- break;
- }
- TmpPtr++;
- }
- return (Buf);
-}
-
-/*
- * Interpret environments
- */
-
-static void PerformEnv(char *Env, int Begin)
-{
- static char VBStr[BUFSIZ] = "";
-
- if (HasWord(Env, &MathEnvir))
- {
- MathMode += Begin ? 1 : -1;
- MathMode = max(MathMode, 0);
- }
-
- if (Begin && HasWord(Env, &VerbEnvir))
- {
- VerbMode = TRUE;
- strcpy(VBStr, "\\end{");
- strcat(VBStr, Env);
- strcat(VBStr, "}");
- VerbStr = VBStr;
- }
-}
-
-static char *SkipVerb(void)
-{
- char *TmpPtr = BufPtr;
- int TmpC;
-
- if (VerbMode && BufPtr)
- {
- if (!(TmpPtr = strstr(BufPtr, VerbStr)))
- BufPtr = &BufPtr[strlen(BufPtr)];
- else
- {
- VerbMode = FALSE;
- BufPtr = &TmpPtr[strlen(VerbStr)];
- SKIP_AHEAD(BufPtr, TmpC, LATEX_SPACE(TmpC));
- if (*BufPtr)
- PSERR(BufPtr - Buf, strlen(BufPtr) - 2, emIgnoreText);
- }
- }
- return (TmpPtr);
-}
-
-#define CHECKDOTS(wordlist, dtval) \
-for(i = 0; (i < wordlist.Stack.Used) && !(Back && Front); i++) \
- { if(!strafter(PstPtr, wordlist.Stack.Data[i])) \
- Back = dtval; \
- if(!strinfront(PrePtr, wordlist.Stack.Data[i])) \
- Front = dtval; }
-
-
-
-/*
- * Checks that the dots are correct
- */
-
-static enum DotLevel CheckDots(char *PrePtr, char *PstPtr)
-{
- unsigned long i;
- int TmpC;
- enum DotLevel Front = dtUnknown, Back = dtUnknown;
-
- if (MathMode)
- {
- PrePtr--;
-#define SKIP_EMPTIES(macro, ptr) macro(ptr, TmpC, \
-(LATEX_SPACE(TmpC) || (TmpC == '{') || (TmpC == '}')))
-
- SKIP_EMPTIES(SKIP_BACK, PrePtr);
- SKIP_EMPTIES(SKIP_AHEAD, PstPtr);
-
- CHECKDOTS(CenterDots, dtCDots);
-
- if (!(Front && Back))
- {
- CHECKDOTS(LowDots, dtLDots);
- }
- return (Front & Back);
- }
- else
- return (dtLDots);
-
-}
-
-static const char *Dot2Str(enum DotLevel dl)
-{
- const char *Retval = INTERNFAULT;
- switch (dl)
- {
- case dtUnknown:
- Retval = "\\cdots or \\ldots";
- break;
- case dtDots:
- Retval = "\\dots";
- break;
- case dtCDots:
- Retval = "\\cdots";
- break;
- case dtLDots:
- Retval = "\\ldots";
- break;
- }
- return Retval;
-}
-
-/*
- * Wipes a command, according to the definition in WIPEARG
- */
-
-static void WipeArgument(const char *Cmd, char *CmdPtr)
-{
- unsigned long CmdLen = strlen(Cmd);
- const char *Format;
- char *TmpPtr;
- int c, TmpC;
-
- if (Cmd && *Cmd)
- {
- TmpPtr = &CmdPtr[CmdLen];
- Format = &Cmd[CmdLen + 1];
-
- while (TmpPtr && *TmpPtr && *Format)
- {
- switch (c = *Format++)
- {
- case '*':
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
- if (*TmpPtr == '*')
- TmpPtr++;
- break;
- case '[':
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
- if (*TmpPtr == '[')
- TmpPtr = GetLTXArg(TmpPtr, ArgBuffer, ']', NULL);
- break;
- case '(':
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
- if (*TmpPtr == '(')
- TmpPtr = GetLTXArg(TmpPtr, ArgBuffer, ')', NULL);
- break;
- case '{':
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
- TmpPtr = GetLTXArg(TmpPtr, ArgBuffer, GET_TOKEN, NULL);
- case '}':
- case ']':
- case ')':
- break;
- default:
- PrintPrgErr(pmWrongWipeTemp, &Cmd[strlen(Cmd) + 1]);
- break;
- }
- }
-
- if (TmpPtr)
- strwrite(CmdPtr+CmdLen, VerbClear, TmpPtr - CmdPtr - CmdLen);
- else
- strxrep(CmdPtr+CmdLen, "()[]{}", *VerbClear);
- }
-}
-
-/*
- * Checks italic.
- *
- */
-
-static void CheckItal(const char *Cmd)
-{
- int TmpC;
- char *TmpPtr;
- if (HasWord(Cmd, &NonItalic))
- ItState = itOff;
- else if (HasWord(Cmd, &Italic))
- ItState = itOn;
- else if (HasWord(Cmd, &ItalCmd))
- {
- TmpPtr = BufPtr;
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
- if (*TmpPtr == '{')
- {
- ItFlag = ItState ? efItal : efNoItal;
- ItState = itOn;
- }
- }
-}
-
-/*
- * Interpret isolated commands.
- *
- */
-
-static void PerformBigCmd(char *CmdPtr)
-{
- char *TmpPtr;
- const char *ArgEndPtr;
- unsigned long CmdLen = strlen(CmdBuffer);
- int TmpC;
- enum ErrNum ErrNum;
- struct ErrInfo *ei;
-
- enum DotLevel dotlev, realdl = dtUnknown;
-
- TmpPtr = BufPtr;
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
-
- ArgEndPtr = GetLTXArg(TmpPtr, ArgBuffer, GET_STRIP_TOKEN, NULL);
-
- /* Kill `\verb' commands */
-
- if (WipeVerb)
- {
- if (!strcmp(CmdBuffer, "\\verb"))
- {
- if (*BufPtr && (*BufPtr != '*' || BufPtr[1]))
- {
- if (*BufPtr == '*')
- TmpPtr = strchr(&BufPtr[2], BufPtr[1]);
- else
- TmpPtr = strchr(&BufPtr[1], *BufPtr);
- if (TmpPtr)
- strwrite(CmdPtr, VerbClear, (TmpPtr - CmdPtr) + 1);
- else
- PSERR(CmdPtr - Buf, 5, emNoArgFound);
- }
- }
- }
-
- if (HasWord(CmdBuffer, &IJAccent))
- {
- if (ArgEndPtr)
- {
- TmpPtr = ArgBuffer;
- SKIP_AHEAD(TmpPtr, TmpC, TmpC == '{'); /* } */
-
- if ((*TmpPtr == 'i') || (*TmpPtr == 'j'))
- PrintError(CurStkName(&InputStack), RealBuf,
- CmdPtr - Buf,
- (long) strlen(CmdBuffer), Line,
- emAccent, CmdBuffer, *TmpPtr,
- MathMode ? "math" : "");
- }
- else
- PSERR(CmdPtr - Buf, CmdLen, emNoArgFound);
- }
-
- if (HasWord(CmdBuffer, &NotPreSpaced) && isspace((unsigned char)CmdPtr[-1]))
- PSERRA(CmdPtr - Buf - 1, 1, emRemPSSpace, CmdBuffer);
-
- if ((TmpPtr = HasWord(CmdBuffer, &NoCharNext)))
- {
- char *BPtr = BufPtr;
-
- TmpPtr += strlen(TmpPtr) + 1;
- SKIP_AHEAD(BPtr, TmpC, LATEX_SPACE(TmpC));
-
- if (strchr(TmpPtr, *BPtr))
- {
- PSERR2(CmdPtr - Buf, CmdLen, emNoCharMean, CmdBuffer, *BPtr);
- }
- }
-
- if (!strcmp(CmdBuffer, "\\begin") || !strcmp(CmdBuffer, "\\end"))
- {
- if (ArgEndPtr)
- {
- if (!strcmp(ArgBuffer, "document"))
- InHeader = FALSE;
-
- if (CmdBuffer[1] == 'b')
- {
- if (!(PushErr(ArgBuffer, Line, CmdPtr - Buf,
- CmdLen, MakeCpy(), &EnvStack)))
- PrintPrgErr(pmNoStackMem);
- }
- else
- {
- if ((ei = PopErr(&EnvStack)))
- {
- if (strcmp(ei->Data, ArgBuffer))
- PrintError(CurStkName(&InputStack), RealBuf,
- CmdPtr - Buf,
- (long) strlen(CmdBuffer),
- Line, emExpectC, ei->Data, ArgBuffer);
-
- FreeErrInfo(ei);
- }
- else
- PrintError(CurStkName(&InputStack), RealBuf,
- CmdPtr - Buf,
- (long) strlen(CmdBuffer),
- Line, emSoloC, ArgBuffer);
- }
-
- PerformEnv(ArgBuffer, (int) CmdBuffer[1] == 'b');
- }
- else
- PSERR(CmdPtr - Buf, CmdLen, emNoArgFound);
- }
-
- CheckItal(CmdBuffer);
-
- if ((ErrNum = PerformCommand(CmdBuffer, BufPtr)))
- PSERR(CmdPtr - Buf, CmdLen, ErrNum);
-
- if (!strcmp(CmdBuffer, "\\cdots"))
- realdl = dtCDots;
-
- if (!strcmp(CmdBuffer, "\\ldots"))
- realdl = dtLDots;
-
- if (!strcmp(CmdBuffer, "\\dots"))
- realdl = dtLDots;
-
- if (realdl != dtUnknown)
- {
- dotlev = CheckDots(CmdPtr, BufPtr);
- if (dotlev && (dotlev != realdl))
- {
- const char *cTmpPtr = Dot2Str(dotlev);
- PSERRA(CmdPtr - Buf, CmdLen, emEllipsis, cTmpPtr);
- }
- }
-
- if ((TmpPtr = HasWord(CmdBuffer, &WipeArg)))
- WipeArgument(TmpPtr, CmdPtr);
-}
-
-/*
- * Check user abbreviations. Pass a pointer to the `.';
- * also ensure that it's followed by spaces, etc.
- *
- * Note: We assume that all abbrevs have been transferred from
- * AbbrevCase into Abbrev.
- */
-
-static void CheckAbbrevs(const char *Buffer)
-{
- long i;
- char *TmpPtr;
- const char *AbbPtr;
-
- if (INUSE(emInterWord))
- {
- TmpPtr = TmpBuffer + Abbrev.MaxLen + 2;
- *TmpPtr = 0;
- AbbPtr = Buffer;
-
- for (i = Abbrev.MaxLen; i >= 0; i--)
- {
- *--TmpPtr = *AbbPtr--;
- if (!isalpha((unsigned char)*AbbPtr) && HasWord(TmpPtr, &Abbrev))
- PSERR(Buffer - Buf + 1, 1, emInterWord);
- if (!*AbbPtr)
- break;
- }
- }
-}
-
-
-/*
- * Check misc. things which can't be included in the main loop.
- *
- */
-
-static void CheckRest(void)
-{
- unsigned long Count;
- long CmdLen;
- char *UsrPtr;
-
- /* Search for user-specified warnings */
-
-#if ! (HAVE_PCRE || HAVE_POSIX_ERE)
-
- if (INUSE(emUserWarnRegex) && UserWarnRegex.Stack.Used > 0)
- {
- PrintPrgErr(pmNoRegExp);
- ClearWord( &UserWarnRegex );
- }
- else if (INUSE(emUserWarn))
- {
- strcpy(TmpBuffer, Buf);
- }
-
-#else
-
- if (INUSE(emUserWarnRegex) && UserWarnRegex.Stack.Used > 0)
- {
- static char error[ERROR_STRING_SIZE];
- static regmatch_t MatchVector[NUM_MATCHES];
- int rc;
- int len = strlen(TmpBuffer);
- strcpy(TmpBuffer, Buf);
-
- /* Compile all regular expressions if not already compiled. */
- if ( !RegexArray && UserWarnRegex.Stack.Used > 0 )
- {
- RegexArray = (regex_t*)malloc( sizeof(regex_t) * UserWarnRegex.Stack.Used );
- if (!RegexArray)
- {
- /* Allocation failed. */
- PrintPrgErr(pmNoRegexMem);
- ClearWord(&UserWarnRegex);
- NumRegexes = 0;
- }
- else
- {
- NumRegexes = 0;
- FORWL(Count, UserWarnRegex)
- {
- char *pattern = UserWarnRegex.Stack.Data[Count];
- char *CommentEnd = NULL;
-
- /* See if it's got a special name that it goes by.
- Only use the comment if it's at the very beginning. */
- if ( strncmp(pattern,"(?#",3) == 0 )
- {
- CommentEnd = strchr(pattern, ')');
- /* TODO: check for PCRE/POSIX only regexes */
- *CommentEnd = '\0';
- /* We're leaking a little here, but this was never freed until exit anyway... */
- UserWarnRegex.Stack.Data[NumRegexes] = pattern+3;
-
- /* Compile past the end of the comment so that it works with POSIX too. */
- pattern = CommentEnd + 1;
- }
-
- /* Ignore PCRE and POSIX specific regexes.
- * This is mostly to make testing easier. */
- if ( strncmp(pattern,"PCRE:",5) == 0 )
- {
- #if HAVE_PCRE
- pattern += 5;
- #else
- continue;
- #endif
- }
- if ( strncmp(pattern,"POSIX:",6) == 0 )
- {
- #if HAVE_POSIX_ERE
- pattern += 6;
- #else
- continue;
- #endif
- }
-
- rc = regcomp((regex_t*)(&RegexArray[NumRegexes]),
- pattern, REGEX_FLAGS);
-
- /* Compilation failed: print the error message */
- if (rc != 0)
- {
- /* TODO: decide whether a non-compiling regex should completely stop, or just be ignored */
- regerror(rc,(regex_t*)(&RegexArray[NumRegexes]),
- error, ERROR_STRING_SIZE);
- PrintPrgErr(pmRegexCompileFailed, pattern, error);
- }
- else
- {
- if ( !CommentEnd )
- {
- ((char*)UserWarnRegex.Stack.Data[NumRegexes])[0] = '\0';
- }
- ++NumRegexes;
- }
- }
- }
- }
-
- for (Count = 0; Count < NumRegexes; ++Count)
- {
- int offset = 0;
- char *ErrMessage = UserWarnRegex.Stack.Data[Count];
- const int NamedWarning = strlen(ErrMessage) > 0;
-
- while (offset < len)
- {
- /* Check if this warning should be suppressed. */
- if (UserLineSuppressions && NamedWarning)
- {
- /* The warning can be named with positive or negative numbers. */
- int UserWarningNumber = abs(atoi(ErrMessage));
- if (UserLineSuppressions & ((uint64_t)1 << UserWarningNumber))
- {
- break;
- }
- }
-
- rc = regexec( (regex_t*)(&RegexArray[Count]), TmpBuffer+offset,
- NUM_MATCHES, MatchVector, 0);
- /* Matching failed: handle error cases */
- if (rc != 0)
- {
- switch(rc)
- {
- case REG_NOMATCH:
- /* no match, no problem */
- break;
- default:
- regerror(rc, (regex_t*)(&RegexArray[Count]),
- error, ERROR_STRING_SIZE);
- PrintPrgErr(pmRegexMatchingError, error);
- break;
- }
-
- offset = len; /* break out of loop */
- }
- else
- {
-#define MATCH (MatchVector[0])
- if ( NamedWarning )
- {
- /* User specified error message */
- PSERR2(offset + MATCH.rm_so, MATCH.rm_eo - MATCH.rm_so,
- emUserWarnRegex,
- strlen(ErrMessage), ErrMessage);
- }
- else
- {
- /* Default -- show the match */
- PSERR2(offset + MATCH.rm_so, MATCH.rm_eo - MATCH.rm_so,
- emUserWarnRegex,
- (int)(MATCH.rm_eo - MATCH.rm_so),
- TmpBuffer + offset + MATCH.rm_so);
- }
- offset += MATCH.rm_eo;
-#undef MATCH
- }
- }
- }
- }
- else if (INUSE(emUserWarn))
- {
- strcpy(TmpBuffer, Buf);
- }
-
-#endif
-
-
- if (INUSE(emUserWarn))
- {
- FORWL(Count, UserWarn)
- {
- for (UsrPtr = TmpBuffer;
- (UsrPtr = strstr(UsrPtr, UserWarn.Stack.Data[Count]));
- UsrPtr++)
- {
- CmdLen = strlen(UserWarn.Stack.Data[Count]);
- PSERRA(UsrPtr - TmpBuffer, CmdLen, emUserWarn, UserWarn.Stack.Data[Count]);
- }
- }
-
- strlwr(TmpBuffer);
-
- FORWL(Count, UserWarnCase)
- {
- for (UsrPtr = TmpBuffer;
- (UsrPtr = strstr(UsrPtr, UserWarnCase.Stack.Data[Count]));
- UsrPtr++)
- {
- CmdLen = strlen(UserWarnCase.Stack.Data[Count]);
- PSERRA(UsrPtr - TmpBuffer, CmdLen, emUserWarn, UserWarnCase.Stack.Data[Count]);
- }
- }
- }
-}
-
-
-/*
- * Checks that the dash-len is correct.
- */
-
-static void CheckDash(void)
-{
- char *TmpPtr;
- int TmpC;
- long TmpCount, Len;
- struct WordList *wl = NULL;
- unsigned long i;
- int Errored;
- char *PrePtr = &BufPtr[-2];
-
- TmpPtr = BufPtr;
- SKIP_AHEAD(TmpPtr, TmpC, TmpC == '-');
- TmpCount = TmpPtr - BufPtr + 1;
-
- if (MathMode)
- {
- if (TmpCount > 1)
- HERE(TmpCount, emWrongDash);
- }
- else
- {
- if (LATEX_SPACE(*PrePtr) && LATEX_SPACE(*TmpPtr))
- wl = &WordDash;
- if (isdigit((unsigned char)*PrePtr) && isdigit((unsigned char)*TmpPtr))
- wl = &NumDash;
- if (isalpha((unsigned char)*PrePtr) && isalpha((unsigned char)*TmpPtr))
- wl = &HyphDash;
-
- if (wl)
- {
- Errored = TRUE;
- FORWL(i, *wl)
- {
- Len = strtol(wl->Stack.Data[i], NULL, 0);
- if (TmpCount == Len)
- {
- Errored = FALSE;
- break;
- }
- }
- if (Errored)
- HERE(TmpCount, emWrongDash);
- }
- }
-}
-
-/*
- * Pushes and pops nesting characters.
- *
- */
-
-static void HandleBracket(char Char)
-{
- unsigned long BrOffset; /* Offset into BrOrder array */
- struct ErrInfo *ei;
- char TmpC, Match;
- char ABuf[2], BBuf[2];
- char *TmpPtr;
-
- AddBracket(Char);
-
- if ((BrOffset = BrackIndex(Char)) != ~0UL)
- {
- if (BrOffset & 1) /* Closing bracket of some sort */
- {
- if ((ei = PopErr(&CharStack)))
- {
- Match = MatchBracket(*(ei->Data));
- /* Return italics to proper state */
- if (ei->Flags & efNoItal)
- {
- if (ItState == itOn)
- {
- TmpPtr = BufPtr;
- SKIP_AHEAD(TmpPtr, TmpC, TmpC == '}');
-
- /* If the next character is a period or comma,
- * or the last character is, then it's not an
- * error. */
- /* Checking 2 characters back seems dangerous,
- * but it's already done in CheckDash. */
- if ( !strchr(LTX_SmallPunc, *TmpPtr) &&
- !strchr(LTX_SmallPunc, *(TmpPtr-2)) )
- HERE(1, emNoItFound);
- }
-
- ItState = FALSE;
- }
- else if (ei->Flags & efItal)
- ItState = TRUE;
-
- /* Same for math mode */
- if (ei->Flags & efMath)
- {
- MathMode = 1;
- }
- else if (ei->Flags & efNoMath)
- {
- MathMode = 0;
- }
-
- FreeErrInfo(ei);
- }
- else
- Match = 0;
-
- if (Match != Char)
- {
- ABuf[0] = Match;
- BBuf[0] = Char;
- ABuf[1] = BBuf[1] = 0;
- if (Match)
- PrintError(CurStkName(&InputStack), RealBuf,
- BufPtr - Buf - 1, 1, Line, emExpectC,
- ABuf, BBuf);
- else
- HEREA(1, emSoloC, BBuf);
- }
-
- }
- else /* Opening bracket of some sort */
- {
- if ((ei = PushChar(Char, Line, BufPtr - Buf - 1,
- &CharStack, MakeCpy())))
- {
- if (Char == '{')
- {
- switch (ItFlag)
- {
- default:
- ei->Flags |= ItFlag;
- ItFlag = efNone;
- break;
- case efNone:
- ei->Flags |= ItState ? efItal : efNoItal;
- }
-
- switch (MathFlag)
- {
- default:
- ei->Flags |= MathFlag;
- MathFlag = efNone;
- break;
- case efNone:
- ei->Flags |= MathMode ? efMath : efNoMath;
- }
- }
- }
-
- else
- PrintPrgErr(pmNoStackMem);
- }
- }
-}
-
-
-/*
- * Checks to see if CmdBuffer matches any of the words in Silent, or
- * any of the regular expressions in SilentCase.
- *
- */
-
-int CheckSilentRegex(void)
-{
-
-#if ! (HAVE_PCRE || HAVE_POSIX_ERE)
-
- return HasWord(CmdBuffer, &Silent);
-
-#else
-
- static char error[ERROR_STRING_SIZE];
- char *pattern;
- char *tmp;
- int i;
- int rc;
- int len = 4; /* Enough for the (?:) */
-
- /* Initialize regular expression */
- if (INUSE(emSpaceTerm) && SilentCase.Stack.Used > 0)
- {
- /* Find the total length we need */
- /* There is 1 for | and the final for null terminator */
- FORWL(i, SilentCase)
- {
- len += strlen( SilentCase.Stack.Data[i] ) + 1;
- }
-
- /* (A|B|...) */
- tmp = (pattern = (char*)malloc( sizeof(char) * len ));
-
- #if HAVE_PCRE
- tmp = stpcpy(tmp,"(?:");
- #else
- tmp = stpcpy(tmp,"(");
- #endif
-
- FORWL(i, SilentCase)
- {
- tmp = stpcpy(tmp, SilentCase.Stack.Data[i]);
- *tmp++ = '|';
- }
- tmp = stpcpy(--tmp, ")");
-
- SilentRegex = malloc( sizeof(regex_t) );
- rc = regcomp(SilentRegex, pattern, REGEX_FLAGS);
-
- /* Compilation failed: print the error message */
- if (rc != 0)
- {
- regerror(rc, SilentRegex, error, ERROR_STRING_SIZE);
- PrintPrgErr(pmRegexCompileFailed, pattern, error);
- SilentRegex = NULL;
- }
- /* Ensure we won't initialize it again */
- SilentCase.Stack.Used = 0;
- free(pattern);
- }
-
- /* Check against the normal */
- if ( HasWord(CmdBuffer, &Silent) )
- return 1;
- if (!SilentRegex)
- return 0;
-
- /* Check against the regexes */
- rc = regexec(SilentRegex, CmdBuffer, 0, NULL, 0);
- if (rc == 0)
- return 1;
-
- /* Matching failed: handle error cases */
- switch(rc)
- {
- case REG_NOMATCH:
- return 0;
- break;
- default:
- regerror(rc, SilentRegex, error, ERROR_STRING_SIZE);
- PrintPrgErr(pmRegexMatchingError, error);
- break;
- }
- return 0;
-
-#endif
-}
-
-/*
- * Searches the `Buf' for possible errors, and prints the errors. `Line'
- * is supplied for error printing.
- */
-
-int FindErr(const char *_RealBuf, const unsigned long _Line)
-{
- char *CmdPtr; /* We'll have to copy each command out. */
- char *PrePtr; /* Ptr to char in front of command, NULL if
- * the cmd appears as the first character */
- char *TmpPtr; /* Temporary pointer */
- char *ErrPtr; /* Ptr to where an error started */
-
- char TmpC, /* Just a temp var used throughout the proc. */
- MatchC, Char; /* Char. currently processed */
- unsigned long CmdLen; /* Length of misc. things */
- int MixingQuotes;
-
- int (*pstcb) (int c);
-
- enum DotLevel dotlev;
-
- LineCpy = NULL;
-
- if (_RealBuf)
- {
- RealBuf = _RealBuf;
- Line = _Line;
-
- BufPtr = PreProcess();
-
- BufPtr = SkipVerb();
-
- while (BufPtr && *BufPtr)
- {
- PrePtr = BufPtr - 1;
- Char = *BufPtr++;
- if (isspace((unsigned char)Char))
- Char = ' ';
-
- switch (Char)
- {
- case '~':
- TmpPtr = NULL;
- if (isspace((unsigned char)*PrePtr))
- TmpPtr = PrePtr;
- else if (isspace((unsigned char)*BufPtr))
- TmpPtr = BufPtr;
-
- if (TmpPtr)
- PSERR(TmpPtr - Buf, 1, emDblSpace);
- break;
-
- case 'X':
- case 'x':
- TmpPtr = PrePtr;
-
- SKIP_BACK(TmpPtr, TmpC,
- (LATEX_SPACE(TmpC) || strchr("{}$", TmpC)));
-
- if (isdigit((unsigned char)*TmpPtr))
- {
- TmpPtr = BufPtr;
-
- SKIP_AHEAD(TmpPtr, TmpC,
- (LATEX_SPACE(TmpC) || strchr("{}$", TmpC)));
-
- if (isdigit((unsigned char)*TmpPtr))
- HERE(1, emUseTimes);
- }
- /* FALLTHRU */
- /* CTYPE: isalpha() */
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- case 'i':
- case 'j':
- case 'k':
- case 'l':
- case 'm':
- case 'n':
- case 'o':
- case 'p':
- case 'q':
- case 'r':
- case 's':
- case 't':
- case 'u':
- case 'v':
- case 'w': /* case 'x': */
- case 'y':
- case 'z':
-
- case 'A':
- case 'B':
- case 'C':
- case 'D':
- case 'E':
- case 'F':
- case 'G':
- case 'H':
- case 'I':
- case 'J':
- case 'K':
- case 'L':
- case 'M':
- case 'N':
- case 'O':
- case 'P':
- case 'Q':
- case 'R':
- case 'S':
- case 'T':
- case 'U':
- case 'V':
- case 'W': /* case 'X': */
- case 'Y':
- case 'Z':
- if (!isalpha((unsigned char)*PrePtr) && (*PrePtr != '\\') && MathMode)
- {
- TmpPtr = BufPtr;
- CmdPtr = CmdBuffer;
- do
- {
- *CmdPtr++ = Char;
- Char = *TmpPtr++;
- }
- while (isalpha((unsigned char)Char));
-
- *CmdPtr = 0;
-
- if (HasWord(CmdBuffer, &MathRoman))
- HEREA(strlen(CmdBuffer), emWordCommand, CmdBuffer);
- }
-
- break;
- case ' ':
- TmpPtr = BufPtr;
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
-
- if (*TmpPtr && *PrePtr)
- {
- if ((TmpPtr - BufPtr) > 0)
- {
- HERE(TmpPtr - BufPtr + 1, emMultiSpace);
- strwrite(BufPtr, VerbClear, TmpPtr - BufPtr - 1);
- }
- }
- break;
-
- case '.':
- if ((Char == *BufPtr) && (Char == BufPtr[1]))
- {
- const char *cTmpPtr;
- dotlev = CheckDots(&PrePtr[1], &BufPtr[2]);
- cTmpPtr = Dot2Str(dotlev);
- HEREA(3, emEllipsis, cTmpPtr);
- }
-
- /* Regexp: "([^A-Z@.])\.[.!?:]*\s+[a-z]" */
-
- TmpPtr = BufPtr;
- SKIP_AHEAD(TmpPtr, TmpC, strchr(LTX_EosPunc, TmpC));
- if (LATEX_SPACE(*TmpPtr))
- {
- if (!isupper((unsigned char)*PrePtr) && (*PrePtr != '@') &&
- (*PrePtr != '.'))
- {
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
- if (islower((unsigned char)*TmpPtr))
- PSERR(BufPtr - Buf, 1, emInterWord);
- else
- CheckAbbrevs(&BufPtr[-1]);
- }
- }
-
- /* FALLTHRU */
- case ':':
- case '?':
- case '!':
- case ';':
- /* Regexp: "[A-Z][A-Z][.!?:;]\s+" */
-
- if (isspace((unsigned char)*BufPtr) && isupper((unsigned char)*PrePtr) &&
- (isupper((unsigned char)PrePtr[-1]) || (Char != '.')))
- HERE(1, emInterSent);
-
- /* FALLTHRU */
- case ',':
- if (isspace((unsigned char)*PrePtr) &&
- !(isdigit((unsigned char)*BufPtr) &&
- ((BufPtr[-1] == '.') || (BufPtr[-1] == ','))))
- PSERR(PrePtr - Buf, 1, emSpacePunct);
-
- if (MathMode &&
- (((*BufPtr == '$') && (BufPtr[1] != '$')) ||
- (!strafter(BufPtr, "\\)"))))
- HEREA(1, emPunctMath, "outside inner");
-
- if (!MathMode &&
- (((*PrePtr == '$') && (PrePtr[-1] == '$')) ||
- (!strinfront(PrePtr, "\\]"))))
- HEREA(1, emPunctMath, "inside display");
-
- break;
- case '\'':
- case '`':
- if ((Char == *BufPtr) && (Char == BufPtr[1]))
- {
- PrintError(CurStkName(&InputStack), RealBuf,
- BufPtr - Buf - 1, 3, Line,
- emThreeQuotes,
- Char, Char, Char, Char, Char, Char);
- }
-
- if (Char == '\'')
- MatchC = '`';
- else
- MatchC = '\'';
-
- TmpPtr = BufPtr;
- SKIP_AHEAD(TmpPtr, TmpC, TmpC == Char);
-
- MixingQuotes = FALSE;
-
- if ((*TmpPtr == MatchC) || (*TmpPtr == '\"') ||
- (*TmpPtr == '´'))
- MixingQuotes = TRUE;
-
- SKIP_AHEAD(TmpPtr, TmpC, strchr("`\'\"´", TmpC));
-
- if (MixingQuotes)
- HERE(TmpPtr - BufPtr + 1, emQuoteMix);
-
- switch (Char)
- {
- case '\'':
- if (isalpha((unsigned char)*TmpPtr) &&
- (strchr(LTX_GenPunc, *PrePtr) || isspace((unsigned char)*PrePtr)))
- HERE(TmpPtr - BufPtr + 1, emBeginQ);
-
- /* Now check quote style */
-#define ISPUNCT(ptr) (strchr(LTX_GenPunc, *ptr) && (ptr[-1] != '\\'))
-
- /* We ignore all single words/abbreviations in quotes */
-
- {
- char *WordPtr = PrePtr;
- SKIP_BACK(WordPtr, TmpC, (isalnum((unsigned char)TmpC) ||
- strchr(LTX_GenPunc, TmpC)));
-
- if (*WordPtr != '`')
- {
- if (*PrePtr && (Quote != quTrad)
- && ISPUNCT(PrePtr))
- PSERRA(PrePtr - Buf, 1,
- emQuoteStyle, "in front of");
-
- if (*TmpPtr && (Quote != quLogic)
- && ISPUNCT(TmpPtr))
- PSERRA(TmpPtr - Buf, 1,
- emQuoteStyle, "after");
- }
- }
-
- break;
- case '`':
- if (isalpha((unsigned char)*PrePtr) &&
- (strchr(LTX_GenPunc, *TmpPtr) || isspace((unsigned char)*TmpPtr)))
- HERE(TmpPtr - BufPtr + 1, emEndQ);
- break;
- }
- BufPtr = TmpPtr;
- break;
- case '"':
- HERE(1, emUseQuoteLiga);
- break;
-
- case '\264': /* '´' */
- HERE(1, emUseOtherQuote);
- break;
-
- case '_':
- case '^':
- if (*PrePtr != '\\')
- {
- TmpPtr = PrePtr;
- SKIP_BACK(TmpPtr, TmpC, LATEX_SPACE(TmpC));
-
- CmdLen = 1;
-
- switch (*TmpPtr)
- {
- /*{ */
- case '}':
- if (PrePtr[-1] != '\\')
- break;
-
- CmdLen++;
- PrePtr--;
- /* FALLTHRU */
- /*[( */
- case ')':
- case ']':
- PSERR(PrePtr - Buf, CmdLen, emEnclosePar);
- }
-
- TmpPtr = BufPtr;
- SKIP_AHEAD(TmpPtr, TmpC, LATEX_SPACE(TmpC));
-
- ErrPtr = TmpPtr;
-
- if (isalpha((unsigned char)*TmpPtr))
- pstcb = &my_isalpha;
- else if (isdigit((unsigned char)*TmpPtr))
- pstcb = &my_isdigit;
- else
- break;
-
- while ((*pstcb) (*TmpPtr++))
- ;
- TmpPtr--;
-
- if ((TmpPtr - ErrPtr) > 1)
- PSERR(ErrPtr - Buf, TmpPtr - ErrPtr, emEmbrace);
- }
- break;
- case '-':
- CheckDash();
- break;
- case '\\': /* Command encountered */
- BufPtr = GetLTXToken(--BufPtr, CmdBuffer);
-
- if (LATEX_SPACE(*PrePtr))
- {
- if (HasWord(CmdBuffer, &Linker))
- PSERR(PrePtr - Buf, 1, emNBSpace);
- if (HasWord(CmdBuffer, &PostLink))
- PSERR(PrePtr - Buf, 1, emFalsePage);
- }
-
- if (LATEX_SPACE(*BufPtr) && !MathMode &&
- !CheckSilentRegex() &&
- (strlen(CmdBuffer) != 2))
- {
- PSERR(BufPtr - Buf, 1, emSpaceTerm);
- }
- else if ((*BufPtr == '\\') && (!isalpha((unsigned char)BufPtr[1])) &&
- (!LATEX_SPACE(BufPtr[1])))
- PSERR(BufPtr - Buf, 2, emNotIntended);
-
- PerformBigCmd(PrePtr + 1);
- BufPtr = SkipVerb();
-
- break;
-
- case '(':
- if (*PrePtr && !LATEX_SPACE(*PrePtr) && !isdigit((unsigned char)*PrePtr)
- && !strchr("([{`~", *PrePtr))
- {
- if (PrePtr[-1] != '\\') /* Short cmds */
- {
- TmpPtr = PrePtr;
- SKIP_BACK(TmpPtr, TmpC, istex(TmpC));
- if (*TmpPtr != '\\') /* Long cmds */
- PSERRA(BufPtr - Buf - 1, 1, emSpaceParen,
- "in front of");
- }
- }
- if (isspace((unsigned char)*BufPtr))
- PSERRA(BufPtr - Buf, 1, emNoSpaceParen, "after");
- HandleBracket(Char);
- break;
-
- case ')':
- if (isspace((unsigned char)*PrePtr))
- PSERRA(BufPtr - Buf - 1, 1, emNoSpaceParen,
- "in front of");
- if (isalpha((unsigned char)*BufPtr))
- PSERRA(BufPtr - Buf, 1, emSpaceParen, "after");
- HandleBracket(Char);
- break;
-
- case '}':
- case '{':
- case '[':
- case ']':
- HandleBracket(Char);
- break;
- case '$':
- if (*PrePtr != '\\')
- {
- if (*BufPtr == '$')
- BufPtr++;
- MathMode ^= TRUE;
- }
-
- break;
- }
- }
-
- if (!VerbMode)
- {
- CheckRest();
- }
-
- }
-
- return (TRUE);
-}
-
-/*
- * Tries to create plural forms for words. Put a '%s' where a
- * suffix should be put, e.g. "warning%s". Watch your %'s!
- */
-
-static void Transit(FILE * fh, unsigned long Cnt, const char *Str)
-{
- switch (Cnt)
- {
- case 0:
- fputs("No ", fh);
- fprintf(fh, Str, "s");
- break;
- case 1:
- fputs("One ", fh);
- fprintf(fh, Str, "");
- break;
- default:
- fprintf(fh, "%ld ", Cnt);
- fprintf(fh, Str, "s");
- break;
- }
-}
-
-/*
- * Prints the status/conclusion after doing all the testing, including
- * bracket stack status, math mode, etc.
- */
-
-void PrintStatus(unsigned long Lines)
-{
- unsigned long Cnt;
- struct ErrInfo *ei;
-
-
- while ((ei = PopErr(&CharStack)))
- {
- PrintError(ei->File, ei->LineBuf, ei->Column,
- ei->ErrLen, ei->Line, emNoMatchC, (char *) ei->Data);
- FreeErrInfo(ei);
- }
-
- while ((ei = PopErr(&EnvStack)))
- {
- PrintError(ei->File, ei->LineBuf, ei->Column,
- ei->ErrLen, ei->Line, emNoMatchC, (char *) ei->Data);
- FreeErrInfo(ei);
- }
-
- if (MathMode)
- {
- PrintError(CurStkName(&InputStack), "", 0L, 0L, Lines, emMathStillOn);
- }
-
- for (Cnt = 0L; Cnt < (NUMBRACKETS >> 1); Cnt++)
- {
- if (Brackets[Cnt << 1] != Brackets[(Cnt << 1) + 1])
- {
- PrintError(CurStkName(&InputStack), "", 0L, 0L, Lines,
- emNoMatchCC,
- BrOrder[Cnt << 1], BrOrder[(Cnt << 1) + 1]);
- }
- }
-
- if (!Quiet)
- {
- Transit(stderr, ErrPrint, "error%s printed; ");
- Transit(stderr, WarnPrint, "warning%s printed; ");
- Transit(stderr, UserSupp, "user suppressed warning%s; ");
- Transit(stderr, LineSupp, "line suppressed warning%s.\n");
- }
-}
-
-
-
-/*
- * Uses OutputFormat. Be sure that `String'
- * does not contain tabs, newlines, etc.
- * Prints a formatted string. Formatting codes understood:
- * %b - string to print Between fields (from -s option)
- * %c - Column position of error
- * %d - lenght of error (Digit)
- * %f - current Filename
- * %i - Turn on inverse printing mode.
- * %I - Turn off inverse printing mode.
- * %k - Kind of error (warning, error, message)
- * %l - Line number of error
- * %m - warning Message
- * %n - warning Number
- * %u - an Underlining line (like the one which appears when using -v1)
- * %r - part of line in front of error ('S' - 1)
- * %s - part of line which contains error (String)
- * %t - part of line after error ('S' + 1)
- */
-
-
-void
-PrintError(const char *File, const char *String,
- const long Position, const long Len,
- const long LineNo, const enum ErrNum Error, ...)
-{
- static /* Just to reduce stack usage... */
- char PrintBuffer[BUFSIZ];
- va_list MsgArgs;
-
- char *LastNorm = OutputFormat;
- char *of;
- int c;
-
- enum Context Context;
-
- if (betw(emMinFault, Error, emMaxFault))
- {
- switch (LaTeXMsgs[Error].InUse)
- {
- case iuOK:
- if (SUPPRESSED_ON_LINE(Error))
- {
- LineSupp++;
- }
- else
- {
- Context = LaTeXMsgs[Error].Context;
-
- if (!HeadErrOut)
- Context |= ctOutHead;
-
-#define RGTCTXT(Ctxt, Var) if((Context & Ctxt) && !(Var)) break;
-
- RGTCTXT(ctInMath, MathMode);
- RGTCTXT(ctOutMath, !MathMode);
- RGTCTXT(ctInHead, InHeader);
- RGTCTXT(ctOutHead, !InHeader);
-
- switch (LaTeXMsgs[Error].Type)
- {
- case etWarn:
- WarnPrint++;
- break;
- case etErr:
- ErrPrint++;
- break;
- case etMsg:
- break;
- }
-
- while ((of = strchr(LastNorm, '%')))
- {
- c = *of;
- *of = 0;
-
- fputs(LastNorm, OutputFile);
-
- *of++ = c;
-
- switch (c = *of++)
- {
- case 'b':
- fputs(Delimit, OutputFile);
- break;
- case 'c':
- fprintf(OutputFile, "%ld", Position + 1);
- break;
- case 'd':
- fprintf(OutputFile, "%ld", Len);
- break;
- case 'f':
- fputs(File, OutputFile);
- break;
- case 'i':
- fputs(ReverseOn, OutputFile);
- break;
- case 'I':
- fputs(ReverseOff, OutputFile);
- break;
- case 'k':
- switch (LaTeXMsgs[Error].Type)
- {
- case etWarn:
- fprintf(OutputFile, "Warning");
- break;
- case etErr:
- fprintf(OutputFile, "Error");
- break;
- case etMsg:
- fprintf(OutputFile, "Message");
- break;
- }
- break;
- case 'l':
- fprintf(OutputFile, "%ld", LineNo);
- break;
- case 'm':
- va_start(MsgArgs, Error);
- vfprintf(OutputFile,
- LaTeXMsgs[Error].Message, MsgArgs);
- va_end(MsgArgs);
- break;
- case 'n':
- fprintf(OutputFile, "%d", Error);
- break;
- case 'u':
- sfmemset(PrintBuffer, ' ', (long) Position);
-
- sfmemset(&PrintBuffer[Position], '^', Len);
- PrintBuffer[Position + Len] = 0;
- fputs(PrintBuffer, OutputFile);
- break;
- case 'r':
- substring(String, PrintBuffer, 0L, Position);
- fputs(PrintBuffer, OutputFile);
- break;
- case 's':
- substring(String, PrintBuffer, Position, Len);
- fputs(PrintBuffer, OutputFile);
- break;
- case 't':
- substring(String, PrintBuffer,
- Position + Len, LONG_MAX);
- fputs(PrintBuffer, OutputFile);
- break;
- default:
- fputc(c, OutputFile);
- break;
- }
- LastNorm = of;
- }
- fputs(LastNorm, OutputFile);
- }
- break;
- case iuNotUser:
- UserSupp++;
- break;
- case iuNotSys:
- break;
- }
- }
-}
-
-/*
- * All commands isolated is routed through this command, so we can
- * update global statuses like math mode and whether @ is a letter
- * or not.
- */
-
-static enum ErrNum PerformCommand(const char *Cmd, char *Arg)
-{
- const char *Argument = "";
- enum ErrNum en = emMinFault;
- int TmpC;
-
- if (!strcmp(Cmd, "\\makeatletter"))
- AtLetter = TRUE;
- else if (!strcmp(Cmd, "\\makeatother"))
- AtLetter = FALSE;
- else if (InputFiles && !(strcmp(Cmd, "\\input") && strcmp(Cmd, "\\include")))
- {
- SKIP_AHEAD(Arg, TmpC, LATEX_SPACE(TmpC));
- if (*Arg == '{') /* } */
- {
- if (GetLTXArg(Arg, TmpBuffer, GET_STRIP_TOKEN, NULL))
- Argument = TmpBuffer;
- }
- else
- Argument = strip(Arg, STRP_BTH);
-
- if (!(Argument && PushFileName(Argument, &InputStack)))
- en = emNoCmdExec;
- }
- else if (HasWord(Cmd, &Primitives))
- en = emTeXPrim;
- else if (HasWord(Cmd, &MathCmd))
- {
- SKIP_AHEAD(Arg, TmpC, LATEX_SPACE(TmpC));
- if (*Arg == '{')
- {
- MathFlag = MathMode ? efMath : efNoMath;
- MathMode = 1;
- }
- }
- else if (HasWord(Cmd, &TextCmd))
- {
- SKIP_AHEAD(Arg, TmpC, LATEX_SPACE(TmpC));
- if (*Arg == '{')
- {
- MathFlag = MathMode ? efMath : efNoMath;
- MathMode = 0;
- }
- }
- else if (*Cmd == '\\')
- {
- /* Quicker check of single lettered commands. */
- switch (Cmd[1])
- {
- case '(':
- case '[':
- MathMode = TRUE;
- break;
- case ']':
- case ')':
- MathMode = FALSE;
- break;
- case '/':
- switch (ItState)
- {
- case itOn:
- ItState = itCorrected;
- Argument = Arg;
-
- SKIP_AHEAD(Argument, TmpC, TmpC == '{' || TmpC == '}');
-
- if (strchr(".,", *Argument))
- en = emItPunct;
-
- break;
- case itCorrected:
- en = emItDup;
- break;
- case itOff:
- en = emItInNoIt;
- }
- break;
- }
- }
-
- return (en);
-}