/* * defmt.c - Handle formatter constructs, mostly by scanning over them. * * Copyright (c), 1983, by Pace Willisson * * Copyright 1992, 1993, Geoff Kuenning, Granada Hills, CA * All rights reserved. * * Copyright 1994 by Ulisses Pinto & Jose' Joa~o Almeida, Universidade do Minho * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. All modifications to the source code must be clearly marked as * such. Binary redistributions based on modified source code * must be clearly marked as modified versions in the documentation * and/or other materials provided with the distribution. * 4. All advertising materials mentioning features or use of this software * must display the following acknowledgment: * This product includes software developed by Geoff Kuenning and * other unpaid contributors. * 5. The name of Geoff Kuenning may not be used to endorse or promote * products derived from this software without specific prior * written permission. * * THIS SOFTWARE IS PROVIDED BY GEOFF KUENNING AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL GEOFF KUENNING OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * The TeX code is originally by Greg Schaffer, with many improvements from * Ken Stevens. The nroff code is primarily from Pace Willisson, although * other people have improved it. */ #include #include #include "jsconfig.h" #include "jspell.h" #include "proto.h" #include "msgs.h" #include "defmt.h" #include "good.h" #define ISTEXTERM(c) (((c) == TEXLEFTCURLY) || \ ((c) == TEXRIGHTCURLY) || \ ((c) == TEXLEFTSQUARE) || \ ((c) == TEXRIGHTSQUARE)) #define ISMATHCH(c) (((c) == TEXBACKSLASH) || \ ((c) == TEXDOLLAR) || \ ((c) == TEXPERCENT)) char aux[3][MAXSOLLEN]; /* * */ char is_sign(char ch) { int i = 0; while (signs[i] != '\0' && signs[i] != ch) i++; if (signs[i] == ch) return 1; else return 0; } char *macro(char *strg) { static int c = 0; int i, i2, i3; char def[20]; struct dent *d; c++; /* para rodar */ if (c == 3) c = 0; i = i2 = 0; while (strg[i] && i2 < MAXSOLLEN) { if (strg[i] != MACRO_MARK) { aux[c][i2] = strg[i]; i++; i2++; } else { /* substitution */ def[0] = strg[i]; /* put # */ i++; /* advance # */ i3 = 1; while (((strg[i] >= 'a' && strg[i] <= 'z') || (strg[i] >= 'A' && strg[i] <= 'Z') || (strg[i] >= '0' && strg[i] <= '9')) && (i3 < 20)) { def[i3] = strg[i]; i++; i3++; } def[i3] = '\0'; /* printf("DEB def=%s", def); */ if ((d = lookup(strtosichar(def, 0), 0))) { if (i2+strlen(d->jclass) < MAXSOLLEN) strcpy(aux[c]+i2, d->jclass); i2 += strlen(d->jclass); } else fprintf(stderr, DEFMT_C_MACRO_NOT_FOUND, def); } } if (i2 < MAXSOLLEN) /* ok */ aux[c][i2] = '\0'; else fprintf(stderr, DEFMT_C_MACRO_SP_OUT); /* printf("DEB aux[c]=%s", aux[c]); */ return aux[c]; } /*---------------------------------------------------------------------------* * TeX routines * *---------------------------------------------------------------------------*/ static void TeX_open_paren(char **bufp) { while (**bufp && **bufp != TEXLEFTCURLY) (*bufp)++; } /* * */ static void TeX_skip_parens(char **bufp) { while (**bufp && **bufp != TEXRIGHTCURLY) (*bufp)++; } /* * Skips the begin{ARG}, and optionally up to two {PARAM}{PARAM}'s to * the begin if they are required. However, Only skips if on this * line. */ static void TeX_skip_args(char **bufp) { register int skip_cnt = 0; /* Max of 2. */ if (strncmp(*bufp, "tabular", 7) == 0 || strncmp(*bufp, "minipage", 8) == 0 || strncmp(*bufp, "tabular*", 8) == 0) skip_cnt++; TeX_skip_parens(bufp); /* Skip to the end of the \begin{} parens */ if (**bufp) (*bufp)++; else return; if (skip_cnt--) TeX_skip_parens(bufp); /* skip 1st {PARAM}. */ else return; if (**bufp) (*bufp)++; else return; if (skip_cnt) TeX_skip_parens(bufp); /* skip to end of 2nd {PARAM}. */ } /* * */ static int TeX_LR_check(int begin_p, char **bufp) { TeX_open_paren(bufp); if (**bufp == 0) { LaTeX_Mode = 'm'; return 0; /* remain in math mode until '}' encountered. */ } else LaTeX_Mode = 'P'; if (strncmp(++(*bufp), "minipage", 8) == 0) { TeX_skip_parens(bufp); if (**bufp) (*bufp)++; if (begin_p) { TeX_skip_parens(bufp); /* now skip opt. args if on this line. */ math_mode += 2; /* indicate minipage mode. */ math_mode += ((math_mode & 127) - 1) * 128; } else { math_mode -= (math_mode & 127) * 128; if (math_mode < 0) { fprintf(stderr, DEFMT_C_LR_MATH_ERROR); math_mode = 1; } } return 1; } (*bufp)--; return 0; } /* * */ static int TeX_LR_begin(char **bufp) { if ((strncmp(*bufp, "mbox", 4) == 0) || (strncmp(*bufp, "makebox", 7) == 0) || (strncmp(*bufp, "fbox", 4) == 0) || (strncmp(*bufp, "framebox", 8) == 0)) math_mode += 2; else if ((strncmp(*bufp, "parbox", 6) == 0) || (strncmp(*bufp, "raisebox", 8) == 0)) { math_mode += 2; TeX_open_paren(bufp); if (**bufp) (*bufp)++; else LaTeX_Mode = 'r'; /* same as reference -- skip {} */ } else if (strncmp(*bufp, "begin", 5) == 0) return TeX_LR_check(1, bufp); /* minipage */ else return 0; /* skip tex command name and optional or width arguments. */ TeX_open_paren(bufp); return 1; } /* * */ static int TeX_math_check(int cont_char, char **bufp) { TeX_open_paren(bufp); /* Check for end of line, continue later. */ if (**bufp == 0) { LaTeX_Mode = (char) cont_char; return 0; } else LaTeX_Mode = 'P'; if (strncmp(++(*bufp), "equation", 8) == 0 || strncmp(*bufp, "eqnarray", 8) == 0 || strncmp(*bufp, "displaymath", 11) == 0 || strncmp(*bufp, "array", 5) == 0 || strncmp(*bufp, "picture", 7) == 0 #ifdef IGNOREBIB || strncmp(*bufp, "thebibliography", 15) == 0 #endif || strncmp(*bufp, "math", 4) == 0) { (*bufp)--; TeX_skip_parens(bufp); return 1; } if (cont_char == 'b') TeX_skip_args(bufp); else TeX_skip_parens(bufp); return 0; } /* * must check for \begin{mbox} or whatever makes new text region. */ static int TeX_math_end(char **bufp) { if (TeX_comment) return 0; else if (**bufp == TEXDOLLAR) { if ((*bufp)[1] == TEXDOLLAR) (*bufp)++; return 1; } else if (**bufp == TEXPERCENT) { TeX_comment = 1; return 0; } /* processing extended TeX command */ (*bufp)++; if (**bufp == TEXRIGHTPAREN || **bufp == TEXRIGHTSQUARE) return 1; if (TeX_LR_begin(bufp)) /* check for switch back to LR mode */ return 1; if (strncmp(*bufp, "end", 3) == 0) /* find environment that is ending */ return TeX_math_check('e', bufp); else return 0; } /* * */ static void TeX_skip_check(char **bufp) { int charlen; /* ADDITIONALLY, MAY WANT TO ADD: * input, include, includeonly, documentstyle, pagestyle, pagenumbering * WITH TWO {} {}'S TO SKIP: * setcounter, addtocounter, setlength, addtolength, settowidth */ if (strncmp(*bufp, "end", 3) == 0 || strncmp(*bufp, "vspace", 6) == 0 || strncmp(*bufp, "hspace", 6) == 0 || strncmp(*bufp, "cite", 4) == 0 || strncmp(*bufp, "ref", 3) == 0 || strncmp(*bufp, "parbox", 6) == 0 || strncmp(*bufp, "label", 5) == 0 || strncmp(*bufp, "input", 5) == 0 || strncmp(*bufp, "nocite", 6) == 0 || strncmp(*bufp, "include", 7) == 0 || strncmp(*bufp, "includeonly", 11) == 0 || strncmp(*bufp, "documentstyle", 13) == 0 #ifndef IGNOREBIB || strncmp(*bufp, "bibliography", 12) == 0 || strncmp(*bufp, "bibitem", 7) == 0 #endif || strncmp(*bufp, "hyphenation", 11) == 0 || strncmp(*bufp, "pageref", 7) == 0) { TeX_skip_parens(bufp); if (**bufp == 0) LaTeX_Mode = 'r'; } else if (strncmp(*bufp, "rule", 4) == 0) { /* skip two args. */ TeX_skip_parens(bufp); if (**bufp == 0) /* Only skips one {} if not on same line. */ LaTeX_Mode = 'r'; else { /* Skip second arg. */ (*bufp)++; TeX_skip_parens(bufp); if (**bufp == 0) LaTeX_Mode = 'r'; } } else { /* Optional tex arguments sometimes should and * sometimes shouldn't be checked * (eg \section [C Programming] {foo} vs * \rule [3em] {0.015in} {5em}) * SO -- we'll just igore it rather than make a full LaTeX parser. */ /* Must look at the space after the command. */ while (**bufp && (l1_isstringch(*bufp, charlen, 0) || iswordch(chartoichar (**bufp)))) { if (!isstringch(*bufp + charlen, 0) && !iswordch(chartoichar((*bufp)[charlen]))) break; *bufp += charlen; } } } /* * */ static int TeX_math_begin(char **bufp) { if (**bufp == TEXDOLLAR) { if ((*bufp)[1] == TEXDOLLAR) (*bufp)++; return 1; } while (**bufp == TEXBACKSLASH) { (*bufp)++; /* check for null char here? */ if (**bufp == TEXLEFTPAREN || **bufp == TEXLEFTSQUARE) return 1; if (strncmp(*bufp, "begin", 5) == 0) { if (TeX_math_check('b', bufp)) return 1; else (*bufp)--; } else { TeX_skip_check(bufp); return 0; } } /* * Ignore references for the tib (1) bibliography system, that * is, text between a ``[.'' or ``<.'' and ``.]'' or ``.>''. * We don't care whether they match, tib doesn't care either. * * A limitation is that the entire tib reference must be on one * line, or we break down and check the remainder anyway. */ if ((**bufp == TEXLEFTSQUARE || **bufp == TEXLEFTANGLE) && (*bufp)[1] == TEXDOT) { (*bufp)++; while (**bufp) { if (*(*bufp)++ == TEXDOT && (**bufp == TEXRIGHTSQUARE || **bufp == TEXRIGHTANGLE)) return TeX_math_begin(bufp); } return 0; } else return 0; } /* * Skip to beginning of a word */ char *skiptoword(char *bufp) { /* char strg_out[80]; */ while (*bufp && (!isstringch(bufp, 0) && (!iswordch(chartoichar (*bufp)) || isboundarych(chartoichar(*bufp)) || (tflag && (math_mode & 1) && !TeX_comment)) && (!signal_is_word || !is_sign(*bufp)))) { /* check paren necessity... */ if (tflag) { /* TeX or LaTeX stuff */ /* Odd numbers mean we are in "math mode" */ /* Even numbers mean we are in LR or */ /* paragraph mode */ if (!TeX_comment) { /* Don't check comments */ if (*bufp == TEXPERCENT) TeX_comment = 1; else if (math_mode & 1) { if ((LaTeX_Mode == 'e' && TeX_math_check('e', &bufp)) || (LaTeX_Mode == 'm' && TeX_LR_check(1, &bufp))) math_mode--; /* end math mode */ else { while (*bufp && !ISMATHCH(*bufp)) bufp++; if (*bufp == 0) break; if (TeX_math_end(&bufp)) math_mode--; } if (math_mode < 0) { fprintf(stderr, DEFMT_C_TEX_MATH_ERROR); math_mode = 0; } } else { if (math_mode > 1 && *bufp == TEXRIGHTCURLY && (math_mode < (math_mode & 127) * 128)) math_mode--; /* re-enter math */ else if (LaTeX_Mode == 'm' || (math_mode && (math_mode >= (math_mode & 127) * 128) && (strncmp(bufp, "\\end", 4) == 0))) { if (TeX_LR_check(0, &bufp)) math_mode--; } else if (LaTeX_Mode == 'b' && TeX_math_check('b', &bufp)) { /* continued begin */ math_mode++; } else if (LaTeX_Mode == 'r') { /* continued "reference" */ TeX_skip_parens(&bufp); LaTeX_Mode = 'P'; } else if (TeX_math_begin(&bufp)) /* checks references and */ /* skips \ commands */ math_mode++; } if (*bufp == 0) break; } } else { /* formatting escape sequences */ if (*bufp == NRBACKSLASH) { switch (bufp[1]) { case 'f': if (bufp[2] == NRLEFTPAREN) { /* font change: \f(XY */ bufp += 5; } else { /* ) */ /* font change: \fX */ bufp += 3; } continue; case 's': /* size change */ bufp += 2; if (*bufp == '+' || *bufp == '-') bufp++; /* This looks wierd 'cause we assume *bufp is now a digit */ bufp++; if (isdigit(*bufp)) bufp++; continue; default: if (bufp[1] == NRLEFTPAREN) { /* extended char set escape: \(XX) */ bufp += 4; continue; } else if (bufp[1] == NRSTAR) { if (bufp[2] == NRLEFTPAREN) bufp += 5; else bufp += 3; continue; } break; } } } bufp++; } if (*bufp == '\0') TeX_comment = 0; return bufp; } /* * Return pointer to end of a word */ char *skipoverword(char *bufp) { /* bufp - Start of word -- MUST BE A REAL START */ register char *lastboundary; register int scharlen; /* Length of a string character */ if (signal_is_word && is_sign(*bufp)) return bufp+1; lastboundary = NULL; for ( ; ; ) { if (*bufp == '\0') { TeX_comment = 0; break; } else if (l_isstringch(bufp, scharlen, 0)) { bufp += scharlen; lastboundary = NULL; } /* * Note that we get here if a character satisfies * isstringstart() but isn't in the string table; this * allows string characters to start with word characters. */ else if (iswordch(chartoichar(*bufp))) { bufp++; lastboundary = NULL; } else if (isboundarych(chartoichar(*bufp))) { if (lastboundary == NULL) lastboundary = bufp; bufp++; } else break; /* End of the word */ } /* * If the word ended in one or more boundary characters, * the address of the first of these is in lastboundary, and it * is the end of the word. Otherwise, bufp is the end. */ return (lastboundary != NULL) ? lastboundary : bufp; } /* * */ char *cut_by_dollar(char *staux) { while (*staux != '$' && *staux != '\0') staux++; if (*staux != '\0') { *staux = '\0'; staux++; } return staux; } static char root[INPUTWORDLEN], *root_class, used_flags[5]; static char pre_class[MAXCLASS], suf_class[MAXCLASS], suf2_class[MAXCLASS]; /* static char staux[MAXCLASS]; */ void treat_caps(char *root, int captype1) { ichar_t iroot[INPUTWORDLEN]; if (captype1 == ANYCASE || captype1 == CAPITALIZED) { strtoichar(iroot, root, INPUTWORDLEN, 1); lowcase(iroot); /* ichartostr(root, lowcase(strtosichar(root, 1)), INPUTWORDLEN, 1); */ if (captype1 == CAPITALIZED) iroot[0] = mytoupper(iroot[0]); ichartostr(root, iroot, INPUTWORDLEN, 1); } } /* * fills suf_class, suf2_class, pre_class, root and root_class * variables */ void get_info(struct success hit) { int i; strcpy(root, hit.dictent->word); treat_caps(root, captype(hit.dictent->flagfield)); root_class = hit.dictent->jclass; i = 0; pre_class[0] = suf_class[0] = suf2_class[0] = '\0'; /* null string */ if (hit.prefix) { ichartostr(pre_class, (hit.prefix)->jclass, (hit.prefix)->classl+1, 1); used_flags[i++] = BITTOCHAR(hit.prefix->flagbit); } if (hit.suffix) { ichartostr(suf_class, (hit.suffix)->jclass, (hit.suffix)->classl+1, 1); used_flags[i++] = BITTOCHAR(hit.suffix->flagbit); } if (hit.suffix2) { ichartostr(suf2_class, (hit.suffix2)->jclass, (hit.suffix2)->classl+1, 1); used_flags[i++] = BITTOCHAR(hit.suffix2->flagbit); } used_flags[i] = '\0'; if (hit.dictent->jclass[0] == '$') { /* $ means "forced" derivation */ /* class format: $root word$root word class$word class */ strcpy(suf2_class, suf_class); strcpy(root/*staux*/, root_class+1); /* root = staux; */ root_class = cut_by_dollar(root); strcpy(suf_class, cut_by_dollar(root_class)); } } /* * */ void cab_pipe_resp(char *strg_out, char exists_ch, char *word, int posinline) { sprintf(strg_out, "%c %s %d :", exists_ch, word, posinline); } void compound_info(char *strg_out, char *word, char *root, char *root_class, char *pre_class, char *suf_class, char *suf2_class) { char form_aux[MAXWLEN+MAXSOLLEN]; sprintf(form_aux, "%s%s%s", word, SEP3, o_form); sprintf(strg_out, form_aux, ichartosstr(strtosichar(macro(root), 1), 0), macro(root_class), pre_class, macro(suf_class), suf2_class); put_flag_info(strg_out); } /* * */ void copy_array(char ar1[MAXPOSSIBLE][MAXSOLLEN], char ar2[MAXPOSSIBLE][MAXSOLLEN]) { int i; i = -1; do { i++; strcpy(ar1[i], ar2[i]); } while (ar2[i][0] != '\0'); } /* * */ void copy_array2(char ar1[MAXPOSSIBLE], char ar2[MAXPOSSIBLE]) { int i; for (i = 0; i < MAXPOSSIBLE; i++) ar1[i] = ar2[i]; } /* * */ void get_roots(char *word, char solutions[MAXPOSSIBLE][MAXSOLLEN], char in_dic[MAXPOSSIBLE]) { /* solutions should already be allocated in the calling module */ int old_cflag, old_lflag, old_islib; old_cflag = cflag; old_lflag = lflag; old_islib = islib; cflag = 1; lflag = 1; islib = 1; strcpy(contextbufs[0], word); checkline(stdout); copy_array(solutions, sol_out2); copy_array2(in_dic, is_in_dic); cflag = old_cflag; lflag = old_lflag; islib = old_islib; } static void treat_sign(FILE *ofile) { char strg_out[MAXSOLLEN]; sprintf(strg_out, o_form, ichartosstr(itoken, 1), "CAT=punct", "", "", ""); if (islib) { strcpy(sol_out[0], strg_out); sol_out[1][0] = '\0'; numhits = 0; try_direct_match_in_dic(itoken, itoken, 1, 0, 1); } else if (!terse) fprintf(ofile, "%s%s", strg_out, SEP4); } /* * */ static void treat_minword(FILE *ofile) { if (islib) { strcpy(sol_out[0], "*"); sol_out[1][0] = '\0'; } else if (!terse) fprintf(ofile, "*"); } /* * */ void put_flag_info(char *strg_out) { if (showflags) { strcat(strg_out, "/"); strcat(strg_out, used_flags); } if (Jflag){ jclass(strg_out,strg_out); } } /* * */ static void treat_good(FILE *ofile) { register int i; char strg_out[MAXSOLLEN]; if (!islib) { cab_pipe_resp(strg_out, '*', ctoken, (int) ((currentchar - contextbufs[0]) - strlen(ctoken))); if (!terse) fprintf(ofile, strg_out); } for (i = 0; i < numhits; i++) { get_info(hits[i]); sprintf(strg_out, o_form, ichartosstr(strtosichar(macro(root), 1), 0), macro(root_class), pre_class, macro(suf_class), suf2_class); put_flag_info(strg_out); if (islib) strcpy(sol_out[i], strg_out); else { if (i < numhits-1) strcat(strg_out, SEP1); if (!terse) fprintf(ofile, "%s", strg_out); } } if (islib) sol_out[i][0] = '\0'; else if (!terse) fprintf(ofile, "%s", SEP4); } /* * */ static void treat_compoundgood(FILE *ofile) { /* compound-word match */ if (!terse) fprintf(ofile, "-\n"); /* ??????????? a mudar */ } /* * */ static void treat_not_good(FILE *ofile) { register int i; char strg_out[MAXSOLLEN]; if (!gflag) { makepossibilities(itoken); if (pcount) { /* print &, ctoken, the character offset and the possibilities */ if (!islib) { cab_pipe_resp(strg_out, '&', ctoken, (int) ((currentchar - contextbufs[0]) - strlen(ctoken))); fprintf(ofile, strg_out); } for (i = 0; i < my_poss_count/*MAXPOSSIBLE*/; i++) { get_info(my_poss[i].suc); compound_info(strg_out, my_poss[i].word, root, root_class, pre_class, suf_class, suf2_class); if (islib) { strcpy(misses_out[i], strg_out); } else { if (i < my_poss_count-1) { if (i != easypossibilities-1) strcat(strg_out, SEP1); else strcat(strg_out, SEP2); } fprintf(ofile, "%s", strg_out); } } misses_out[i][0] = '\0'; if (!islib) fprintf(ofile, SEP4); } else if (!islib) { /* No possibilities found for word TOKEN */ cab_pipe_resp(strg_out, '&', ctoken, (int) ((currentchar - contextbufs[0]) - strlen(ctoken))); if (!terse) { fprintf(ofile, strg_out); fprintf(ofile, SEP4); } } } else if (!islib) { cab_pipe_resp(strg_out, '&', ctoken, (int) ((currentchar - contextbufs[0]) - strlen(ctoken))); fprintf(ofile, strg_out); fprintf(ofile, SEP4); } } /* * */ char process_aflag(FILE *ofile, int ilen) { if (is_sign(itoken[0])) { treat_sign(ofile); return 0; /* or should be 1 ??? */ } if (ilen <= minword) { /* length of Word makes it always legal */ treat_minword(ofile); return 1; /* continue; */ } if (bgood(itoken, 0, 0, 0)) treat_good(ofile); else if (compoundgood(itoken)) treat_compoundgood(ofile); else treat_not_good(ofile); return 0; /* don't continue */ } /* * */ void skip_ntroff_text_formaters(int hadlf, FILE *ofile) { if (!tflag) { /* nroff/troff mode */ /* skip over .if */ if (*currentchar == NRDOT && (strncmp(currentchar + 1, "if t", 4) == 0 || strncmp(currentchar + 1, "if n", 4) == 0)) { copyout(¤tchar, 5); while (*currentchar && myspace(chartoichar(*currentchar))) copyout(¤tchar, 1); } /* skip over .ds XX or .nr XX */ if (*currentchar == NRDOT && (strncmp(currentchar + 1, "ds ", 3) == 0 || strncmp(currentchar + 1, "de ", 3) == 0 || strncmp(currentchar + 1, "nr ", 3) == 0)) { copyout(¤tchar, 4); while (*currentchar && myspace(chartoichar(*currentchar))) copyout(¤tchar, 1); while (*currentchar && !myspace(chartoichar(*currentchar))) copyout(¤tchar, 1); if (*currentchar == 0) { /* end of line */ if (!islib && !lflag && (aflag || hadlf)) putc('\n', ofile); return; } } } if (*currentchar == NRDOT && /* we don't wanna lose every dot */ (*(currentchar+1) == '\0' || *(currentchar+1) == ' ')) return; /* if this is a formatter command, skip over it */ if (!tflag && *currentchar == NRDOT) { while (*currentchar && !myspace(chartoichar(*currentchar))) { if (!aflag && !lflag) (void) putc(*currentchar, ofile); currentchar++; } if (*currentchar == 0) { if (!islib && !lflag && (aflag || hadlf)) putc('\n', ofile); return; } } } /* * */ void checkline(FILE *ofile) { register char *p; register char *endp; int hadlf; /* had linefeed */ register int len; int ilen; if (islib) { sol_out[0][0] = '\0'; misses_out[0][0] = '\0'; } currentchar = contextbufs[0]; len = strlen(contextbufs[0]) - 1; hadlf = contextbufs[0][len] == '\n'; if (hadlf) contextbufs[0][len] = 0; skip_ntroff_text_formaters(hadlf, ofile); for (;;) { p = skiptoword(currentchar); if (p != currentchar) copyout(¤tchar, p - currentchar); if (*currentchar == 0) break; p = ctoken; endp = skipoverword(currentchar); while (currentchar < endp && p < ctoken + sizeof ctoken - 1) *p++ = *currentchar++; *p = 0; if (strtoichar(itoken, ctoken, INPUTWORDLEN * sizeof(ichar_t), 0)) fprintf(stderr, WORD_TOO_LONG(ctoken)); ilen = icharlen(itoken); i_word_created = 0; /* important to the -c,-l flag */ /* the -c also activates the lflag */ if (lflag) { /* lflag - produce a list of misspelled words */ if (ilen > minword && !bgood(itoken, 0, 0, 0) && !cflag && !compoundgood(itoken)) fprintf(ofile, "%s\n", ctoken); } else { if (aflag) { /* do not remove these brackets */ if (process_aflag(ofile, ilen)) continue; } else { if (!quit) { jcorrect(ctoken, itoken, ¤tchar); } } } if (!aflag && !lflag) fprintf(ofile, "%s", ctoken); } if (!islib && !lflag && (aflag || hadlf)) putc('\n', ofile); } /** * buf - the buffer where the modifications will be made * start - points to the position in the buffer where we want the word to be replaced * tok - the new token (word) that will replace * curchar - the position in the buffer where the old word ends */ void replace_token(char *buf, char *start, register char *tok, char **curchar) { char copy[BUFSIZ]; char *p, *q, *ew; strcpy(copy, buf); for (p = buf, q = copy; p != start; p++, q++) *p = *q; q += *curchar - start; /* advance old word in buffer q */ /* copy the new word to the desired postion in buf */ ew = skipoverword(tok); /* ew points to the position at the end of token */ while (tok < ew) *p++ = *tok++; *curchar = p; if (*tok) { /* The token changed to two words. Split it up and save the ** second one for later. */ *p++ = *tok; *tok++ = '\0'; while (*tok) *p++ = *tok++; } /* copy the remaining of the buffer */ while((*p++ = *q++)) ; } /* * this should give only root words */ ID_TYPE word_id(char *word, char *feats, int *status) { int old_cflag, old_lflag; ID_TYPE id; int i, n_eq, flen; char root1[INPUTWORDLEN]; old_cflag = cflag; old_lflag = lflag; cflag = lflag = 0; strcpy(contextbufs[0], word); checkline(stdout); cflag = old_cflag; lflag = old_lflag; id = 0; n_eq = 0; flen = strlen(feats); for (i = 0; i < numhits; i++) { get_info(hits[i]); strcpy(root1, ichartosstr(strtosichar(macro(root), 1), 0)); if (strcmp(root1, word) == 0 && /* root word matches */ strncmp(feats, macro(root_class), flen) == 0) { if (n_eq == 0) /* printf("dictent=%p, hashtbl=%p subtraindo dá: %d sizeof=%d\n", hits[i].dictent, hashtbl, hits[i].dictent - hashtbl, sizeof(struct dent)); */ id = (ID_TYPE) (hits[i].dictent - hashtbl); n_eq++; } } /* if (n_eq == 0) fprintf(stderr, "numhits=%d, hits[0]=%s, word=%s, root=%s, root1=%s\n", numhits, hits[0].dictent->word, word, root, root1);*/ /* DEBUG */ *status = n_eq; return id; } char *word_f_id(ID_TYPE id) { struct dent *pd; static char root[INPUTWORDLEN]; pd = hashtbl + id; /* printf("s=%s pos=%d\n", ichartosstr(s, 0), hash(s, hashsize));*/ /*DEB*/ strcpy(root, pd->word); treat_caps(root, captype(pd->flagfield)); return ichartosstr(strtosichar(macro(root), 1), 0); } char *class_f_id(ID_TYPE id) { struct dent *pd; static char jclass[MAXCLASS]; pd = hashtbl + id; strcpy(jclass, macro(pd->jclass)); return jclass; } #define MAXFLAGS 32 char *flags_f_id(ID_TYPE id) { int i, bit; struct dent *pd; static char flags[MAXFLAGS]; pd = hashtbl + id; i = 0; for (bit = 0; bit < LARGESTFLAG && i < MAXFLAGS; bit++) if (TSTMASKBIT(pd->mask, bit)) flags[i++] = BITTOCHAR(bit); flags[i] = '\0'; return flags; }