/* -*- Mode: C; tab-width: 4; -*- */
/**
* @file
* @brief An interactive spelling corrector and word classificator
*/
/* jspell.c - An interactive spelling corrector and word classificator
*
* Copyright (c) 1983, by Pace Willisson
* Copyright (c) 1992, 1993, Geoff Kuenning, Granada Hills, CA
* Copyright (c) 1994-2010,
* Ulisses Pinto,
* José João Almeida,
* Alberto Simões,
*
* Projecto Natura,
* Universidade do Minho
*/
#include <string.h>
#include <ctype.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include "jsconfig.h"
#include "jspell.h"
#include "proto.h"
#include "msgs.h"
#include "version.h"
static void expandmode(int printorig);
/** ... */
struct dent *last_found;
static int add_inc = 0;
static void usage(char *cmd)
{
fprintf(stderr, ISPELL_C_USAGE1, cmd);
fprintf(stderr, ISPELL_C_USAGE2, cmd);
fprintf(stderr, ISPELL_C_USAGE3, cmd);
fprintf(stderr, ISPELL_C_USAGE4, cmd);
fprintf(stderr, ISPELL_C_USAGE5, cmd);
fprintf(stderr, ISPELL_C_USAGE6, cmd);
fprintf(stderr, ISPELL_C_USAGE7, cmd);
exit(1);
}
/* wchars - Characters in -w option, if any
* -w: may be used to specify characters other than
* alphabetics which may also appear in words
*/
static void initckch(char *wchars)
{
register ichar_t c;
char num[4];
for (c = 0; c < (ichar_t)(SET_SIZE + hashheader.nstrchars); ++c) {
if (iswordch(c)) {
if (!mylower(c)) {
Try[Trynum] = c;
++Trynum;
}
}
}
if (wchars != NULL) {
while (Trynum < SET_SIZE && *wchars != '\0') {
if (*wchars != 'n' && *wchars != '\\') {
c = *wchars;
++wchars;
}
else {
++wchars;
num[0] = '\0';
num[1] = '\0';
num[2] = '\0';
num[3] = '\0';
if (isdigit (wchars[0])) {
num[0] = wchars[0];
if (isdigit (wchars[1])) {
num[1] = wchars[1];
if (isdigit(wchars[2]))
num[2] = wchars[2];
}
}
if (wchars[-1] == 'n') {
wchars += strlen(num);
c = atoi(num);
}
else {
wchars += strlen(num);
c = 0;
if (num[0])
c = num[0] - '0';
if (num[1]) {
c <<= 3;
c += num[1] - '0';
}
if (num[2]) {
c <<= 3;
c += num[2] - '0';
}
}
}
c &= NOPARITY;
if (!hashheader.wordchars[c]) {
hashheader.wordchars[c] = 1;
hashheader.sortorder[c] = hashheader.sortval++;
Try[Trynum] = c;
++Trynum;
}
}
}
}
/* the -v option causes ispell to print its current version
* identification on the standard output and exit. If the switch is
* doubled, ispell will also print the options that it was compiled
* with.
*/
static void option_v(char *cmd, int argc, char *argv[], int arglen)
{
char ** versionp;
char *p;
if (arglen > 3)
usage(cmd);
for (versionp = Version_ID; *versionp; ) {
p = *versionp++;
if (strncmp(p, "(#) ", 5) == 0)
p += 5;
printf("%s\n", p);
}
if ((*argv)[2] == 'v') {
printf(ISPELL_C_OPTIONS_ARE);
printf("\tBAKEXT = \"%s\"\n", BAKEXT);
/* printf("\tBINDIR = \"%s\"\n", BINDIR); */
#ifdef BOTTOMCONTEXT
printf("\tBOTTOMCONTEXT\n");
#else /* BOTTOMCONTEXT */
printf("\t!BOTTOMCONTEXT\n");
#endif /* BOTTOMCONTEXT */
#if TERM_MODE == CBREAK
printf("\tCBREAK\n");
#endif /* TERM_MODE */
#ifdef COMMANDFORSPACE
printf("\tCOMMANDFORSPACE\n");
#else /* COMMANDFORSPACE */
printf("\t!COMMANDFORSPACE\n");
#endif /* COMMANDFORSPACE */
#ifdef CONTEXTROUNDUP
printf("\tCONTEXTROUNDUP\n");
#else /* CONTEXTROUNDUP */
printf("\t!CONTEXTROUNDUP\n");
#endif /* CONTEXTROUNDUP */
printf("\tCONTEXTPCT = %d\n", CONTEXTPCT);
printf("\tDEFHASH = \"%s\"\n", DEFHASH);
printf("\tDEFINCSTR = \"%s\"\n", DEFINCSTR);
printf("\tDEFLANG = \"%s\"\n", DEFLANG);
printf("\tDEFNOBACKUPFLAG = %d\n", DEFNOBACKUPFLAG);
printf("\tDEFPAFF = \"%s\"\n", DEFPAFF);
printf("\tDEFPDICT = \"%s\"\n", DEFPDICT);
printf("\tDEFTEXFLAG = %d\n", DEFTEXFLAG);
printf("\tEGREPCMD = \"%s\"\n", EGREPCMD);
#ifdef EQUAL_COLUMNS
printf("\tEQUAL_COLUMNS\n");
#else /* EQUAL_COLUMNS */
printf("\t!EQUAL_COLUMNS\n");
#endif /* EQUAL_COLUMNS */
#ifdef IGNOREBIB
printf ("\tIGNOREBIB\n");
#else /* IGNOREBIB */
printf ("\t!IGNOREBIB\n");
#endif /* IGNOREBIB */
printf("\tINCSTRVAR = \"%s\"\n", INCSTRVAR);
printf("\tINPUTWORDLEN = %d\n", INPUTWORDLEN);
printf("\tLANGUAGES = \"%s\"\n", LANGUAGES);
printf("\tLIBDIR = \"%s\"\n", LIBDIR);
#ifndef REGEX_LOOKUP
#endif /* REGEX_LOOKUP */
printf("\tMAKE_SORTTMP = \"%s\"\n", MAKE_SORTTMP);
printf("\tMALLOC_INCREMENT = %d\n", MALLOC_INCREMENT);
/* printf("\tMAN1DIR = \"%s\"\n", MAN1DIR); */
/* printf("\tMAN1EXT = \"%s\"\n", MAN1EXT); */
/* printf("\tMAN4DIR = \"%s\"\n", MAN4DIR); */
/* printf("\tMAN4EXT = \"%s\"\n", MAN4EXT); */
printf("\tMASKBITS = %d\n", MASKBITS);
printf("\tMASKTYPE = %s\n", MASKTYPE_STRING);
printf("\tMASKTYPE_WIDTH = %d\n", MASKTYPE_WIDTH);
printf("\tMAXAFFIXLEN = %d\n", MAXAFFIXLEN);
printf("\tMAXCONTEXT = %d\n", MAXCONTEXT);
printf("\tMAXINCLUDEFILES = %d\n", MAXINCLUDEFILES);
printf("\tMAXNAMLEN = %d\n", MAXNAMLEN);
printf("\tMAXPATHLEN = %d\n", MAXPATHLEN);
printf("\tMAXPCT = %d\n", MAXPCT);
printf("\tMAXSEARCH = %d\n", MAXSEARCH);
printf("\tMAXSTRINGCHARLEN = %d\n", MAXSTRINGCHARLEN);
printf("\tMAXSTRINGCHARS = %d\n", MAXSTRINGCHARS);
printf("\tMAX_HITS = %d\n", MAX_HITS);
printf("\tMINCONTEXT = %d\n", MINCONTEXT);
#ifdef MINIMENU
printf("\tMINIMENU\n");
#else /* MINIMENU */
printf("\t!MINIMENU\n");
#endif /* MINIMENU */
printf("\tMINWORD = %d\n", MINWORD);
printf("\tMSGLANG = %s\n", MSGLANG);
#ifdef NO_CAPITALIZATION_SUPPORT
printf("\tNO_CAPITALIZATION_SUPPORT\n");
#else /* NO_CAPITALIZATION_SUPPORT */
printf ("\t!NO_CAPITALIZATION_SUPPORT\n");
#endif /* NO_CAPITALIZATION_SUPPORT */
#ifdef NO8BIT
printf("\tNO8BIT\n");
#else /* NO8BIT */
printf("\t!NO8BIT (8BIT)\n");
#endif /* NO8BIT */
printf("\tNRSPECIAL = \"%s\"\n", NRSPECIAL);
printf("\tOLDPAFF = \"%s\"\n", OLDPAFF);
printf("\tOLDPDICT = \"%s\"\n", OLDPDICT);
printf("\tPDICTVAR = \"%s\"\n", PDICTVAR);
#ifdef PIECEMEAL_HASH_WRITES
printf("\tPIECEMEAL_HASH_WRITES\n");
#else /* PIECEMEAL_HASH_WRITES */
printf("\t!PIECEMEAL_HASH_WRITES\n");
#endif /* PIECEMEAL_HASH_WRITES */
#if TERM_MODE != CBREAK
printf("\tRAW\n");
#endif /* TERM_MODE */
#ifdef REGEX_LOOKUP
printf("\tREGEX_LOOKUP\n");
#else /* REGEX_LOOKUP */
printf ("\t!REGEX_LOOKUP\n");
#endif /* REGEX_LOOKUP */
printf("\tSIGNAL_TYPE = %s\n", SIGNAL_TYPE_STRING);
printf("\tSORTPERSONAL = %d\n", SORTPERSONAL);
printf("\tTEMPNAME = \"%s\"\n", TEMPNAME);
/* printf("\tTERMLIB = \"%s\"\n", TERMLIB); */
printf("\tTEXSPECIAL = \"%s\"\n", TEXSPECIAL);
printf("\tWORDS = \"%s\"\n", WORDS);
}
exit(0);
}
/* The input file is in nroff/troff format */
static char *option_n(char *cmd, char *preftype, int arglen)
{
if (arglen > 2)
usage(cmd);
tflag = 0; /* nroff/troff mode */
deftflag = 0;
if (preftype == NULL)
preftype = "nroff";
return preftype;
}
/* The input file is in TeX/LaTeX format */
static char *option_t(char *cmd, char *preftype, int arglen)
{
if (arglen > 2)
usage(cmd);
tflag = 1;
deftflag = 1;
if (preftype == NULL)
preftype = "tex";
return preftype;
}
/* -T type - Assume a given formatter type for all files */
static char *option_T(char *cmd, int argc, char *argv[])
{
char *p;
p = (*argv)+2;
if (*p == '\0') {
argv++; argc--;
add_inc = 1;
if (argc == 0)
usage(cmd);
p = *argv;
}
return p;
}
/* print a one-line verson identification message for each word */
static void option_A(char *cmd, int arglen)
{
if (arglen > 2)
usage(cmd);
incfileflag = 1;
aflag = 1;
}
/* Print after gclass */
static void option_J(char *cmd, int arglen)
{
if (arglen > 2)
usage(cmd);
Jflag = 1;
}
/* print a one-line verson identification message for each word */
static void option_a(char *cmd, int arglen)
{
if (arglen > 2)
usage(cmd);
aflag++;
}
/* causes the affix tables from the dictionary file to be dumped to
* stdout */
static void option_D(char *cmd, int arglen)
{
if (arglen > 2)
usage(cmd);
dumpflag++;
nodictflag++;
}
/* expands affix flags to produce a list of words
* is the reverse of -c */
static void option_e(char *cmd, int arglen, char *argv[])
{
if (arglen > 3) usage(cmd);
eflag = 1;
if ((*argv)[2] == 'e')
eflag = 2;
else if ((*argv)[2] >= '1' && (*argv)[2] <= '4')
eflag = (*argv)[2] - '0';
else if ((*argv)[2] != '\0')
usage(cmd);
nodictflag++;
}
/* causes a list of words to be read from the standard input for each
* word, a list of possible root words and affixes will be written to
* the standard output */
static void option_c(char *cmd, int arglen, char *argv[])
{
if (arglen > 2) usage(cmd);
cflag++;
lflag++;
}
/* Create a backup file by appending ".bak" to the name of the input
* file */
static void option_b(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
xflag = 0;
}
/* Don't create a backup file */
static void option_x(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
xflag = 1;
}
/* used in conjunction with -a or -A options -f filename: write its
* results to the given file, rather than std. output */
static void option_f(char *cmd, int argc, char *argv[])
{
char *p;
fflag++;
p = (*argv)+2;
if (*p == '\0') {
argv++; argc--;
add_inc = 1;
if (argc == 0)
usage(cmd);
p = *argv;
}
askfilename = p;
if (*askfilename == '\0')
askfilename = NULL;
}
/* L context: Look up words in system dictionary (controlled by the
* WORDS compilation option */
static void option_L(char *cmd, int argc, char *argv[])
{
char *p;
p = (*argv)+2;
if (*p == '\0') {
argv++; argc--;
if (argc == 0)
usage(cmd);
p = *argv;
}
contextsize = atoi(p);
}
/* produce a list of misspelled words */
static void option_l(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
lflag++;
}
/* Sort the list of guesses by probable correctness */
static void option_S(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
sortit = 0;
}
/* Report run-together words with missing blanks as spelling errors */
static void option_B(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
missingspaceflag = 1;
}
/* Consider run-together words as legal compounds */
static void option_C(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
missingspaceflag = 0;
}
/* Don't generate extra root/affix combinations */
static void option_P(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
tryhardflag = 0;
}
/* Make possible root/affix combinations that aren't in the
* dictionary */
static void option_m(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
tryhardflag = 1;
}
/* suppress the mini-menu */
static void option_N(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
minimenusize = 0;
}
/* activate mini-menu at the bottom of the screen with these
* options */
static void option_M(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
minimenusize = 2;
}
/* p file: specify an alternate personal dictionary */
static void option_p(char *LibDict, char **cpd, char *cmd, int argc, char *argv[])
{
char *c;
c = (*argv)+2;
if (*c == '\0') {
argv++; argc--;
add_inc = 1;
if (argc == 0)
usage(cmd);
c = *argv;
if (*c == '\0')
c = NULL;
}
*cpd = c;
LibDict = NULL;
}
/* d file: specify an alternate dictionary file */
static void option_d(char *LibDict, char *cpd, char *cmd, int argc, char *argv[])
{
char *p;
p = (*argv)+2;
if (*p == '\0') {
argv++; argc--;
add_inc = 1;
if (argc == 0)
usage(cmd);
p = *argv;
}
if (index(p, '/') != NULL)
strcpy(hashname, p);
else
sprintf(hashname, "%s/%s", LIBDIR, p);
if (cpd == NULL && *p != '\0')
LibDict = p;
p = rindex(p, '.');
if (p != NULL && strcmp(p, ".hash") == 0)
*p = '\0'; /* Don't want ext. in LibDict */
else
strcat(hashname, ".hash");
}
/* style to print characters not in the 7-bit ANSI character set */
static void option_V(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
vflag = 1;
}
/* Specify length of words that are always legal */
static void option_W(char *cmd, int argc, char *argv[])
{
if ((*argv)[2] == '\0') {
argv++; argc--;
add_inc = 1;
if (argc == 0)
usage(cmd);
minword = atoi(*argv);
}
else
minword = atoi(*argv + 2);
}
/* o - define new output format */
static void option_o(char *cmd, int argc, char *argv[])
{
char *o_form2;
oflag = 1;
o_form2 = (*argv)+2;
if (*o_form2 == '\0') {
argv++; argc--;
add_inc = 1;
if (argc == 0)
usage(cmd);
o_form2 = *argv;
if (*o_form2 == '\0')
o_form2 = NULL;
}
if (o_form2) strcpy(o_form, o_form2);
else o_form[0] = '\0';
}
/* g - display "good" options only - do not display "near misses" */
static void option_g(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
gflag = 1;
}
/* y - do not display typing errors in "near misses" */
static void option_y(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
yflag = 1;
}
/* u - no punct - signal is not word */
static void option_u(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
signal_is_word = 0;
}
/* z - */
static void option_z(char *cmd, int arglen)
{
if (arglen > 2) usage(cmd);
showflags = 1;
}
static void verify_files(int argc, char *argv[])
{
/* Because of the high cost of reading the dictionary, we stat the
* files specified first to see if they exist. If at least one
* exists, we continue.
*/
int argno;
for (argno = 0; argno < argc; argno++) {
if (access(argv[argno], R_OK) >= 0) break;
}
if (argno >= argc && !lflag && !aflag && !eflag && !dumpflag) {
fprintf(stderr, argc == 1 ? ISPELL_C_NO_FILE : ISPELL_C_NO_FILES);
exit(1);
}
}
static void det_prefstringchar(char *preftype)
{
if (preftype != NULL) {
prefstringchar = findfiletype(preftype, 1, &deftflag);
if (prefstringchar < 0 &&
strcmp(preftype, "tex") != 0 &&
strcmp(preftype, "nroff") != 0)
{
fprintf(stderr, ISPELL_C_BAD_TYPE, preftype);
exit(1);
}
}
}
static void process_LibDict(char *LibDict, char *cpd)
{
char *p;
static char libdictname[sizeof DEFHASH];
if (LibDict == NULL) {
strcpy(libdictname, DEFHASH);
LibDict = libdictname;
p = rindex(libdictname, '.');
if (p != NULL && strcmp(p, ".hash") == 0)
*p = '\0'; /* Don't want ext. in LibDict */
}
if (!nodictflag)
treeinit(cpd, LibDict);
}
static int process_a_e_and_d_flags(void)
{
int res;
res = 0;
if (aflag) {
if (!islib) {
askmode();
treeoutput();
}
} else if (eflag) {
expandmode(eflag);
} else if (dumpflag) {
dumpmode();
} else {
res = 1;
}
return res;
}
/**
* @brief Max number of...
*/
#define MAX_SOL 15
/**
* @brief ...
* @param argc
* @param argv
* @param lib
*/
int my_main(int argc, char *argv[], char lib)
{
char *wchars = NULL;
char *preftype = NULL;
static char outbuf[BUFSIZ];
int arglen, old_argc;
char *cpd = NULL;
char *Cmd = *argv;
/* Pointer to name of $(LIBDIR)/dict */
char *LibDict = NULL;
islib = lib;
old_argc = argc;
Trynum = 0;
sprintf(hashname, "%s/%s", LIBDIR, DEFHASH);
strcpy(signs, DEFAULT_SIGNS);
argv++;
argc--;
while (argc && **argv == '-') {
/*
* Trying to add a new flag? Can't remember what's been used?
* Here's a handy guide:
*
* Used:
* ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789
* ^^^^ ^^^ ^ ^^ ^^
* abcdefghijklmnopqrstuvwxyz
* ^^^^^^* ^^^*^ ^^*^^^*
*/
arglen = strlen(*argv);
add_inc = 0;
switch ((*argv)[1]) {
case 'v':
option_v(Cmd, argc, argv, arglen);
break;
case 'n':
preftype = option_n(Cmd, preftype, arglen);
break;
case 't': /* TeX mode */
preftype = option_t(Cmd, preftype, arglen);
break;
case 'T': /* Set preferred file type */
preftype = option_T(Cmd, argc, argv);
break;
case 'A':
option_A(Cmd, arglen);
break;
case 'a':
option_a(Cmd, arglen);
break;
case 'D':
option_D(Cmd, arglen);
break;
case 'J':
option_J(Cmd, arglen);
break;
case 'e':
option_e(Cmd, arglen, argv);
break;
case 'c':
option_c(Cmd, arglen, argv);
break;
case 'b':
option_b(Cmd, arglen);
break;
case 'x':
option_x(Cmd, arglen);
break;
case 'f':
option_f(Cmd, argc, argv);
break;
case 'L':
option_L(Cmd, argc, argv);
break;
case 'l':
option_l(Cmd, arglen);
break;
case 'S':
option_S(Cmd, arglen);
break;
case 'B': /* -B: report missing blanks */
option_B(Cmd, arglen);
break;
case 'C': /* -C: compound words are acceptable */
option_C(Cmd, arglen);
break;
case 'P': /* -P: don't gen non-dict poss's */
option_P(Cmd, arglen);
break;
case 'm': /* -m: make all poss affix combos*/
option_m(Cmd, arglen);
break;
case 'N': /* -N: suppress minimenu */
option_N(Cmd, arglen);
break;
case 'M':
option_M(Cmd, arglen);
break; /* -M: force minimenu */
case 'p':
option_p(LibDict, &cpd, Cmd, argc, argv);
break;
case 'd':
option_d(LibDict, cpd, Cmd, argc, argv);
break;
case 'V': /* Display 8-bit characters as M-xxx */
option_V(Cmd, arglen);
break;
case 'w':
wchars = (*argv)+2;
if (*wchars == '\0') {
argv++; argc--;
if (argc == 0)
usage(Cmd);
wchars = *argv;
}
break;
case 'W':
option_W(Cmd, argc, argv);
break;
case 'o':
option_o(Cmd, argc, argv);
break;
case 'g':
option_g(Cmd, arglen);
break;
case 'u':
option_u(Cmd, arglen);
break;
case 'y':
option_y(Cmd, arglen);
break;
case 'z':
option_z(Cmd, arglen);
break;
default:
usage(Cmd);
} /* end switch */
if (add_inc) {
argv++; argc--;
}
argv++; argc--;
}
if (!argc && !lflag && !aflag && !eflag && !dumpflag)
usage(Cmd);
verify_files(argc, argv);
if (!oflag) strcpy(o_form, DEF_OUT);
if (linit() < 0) exit(1); /* Force an error */
det_prefstringchar(preftype);
if (prefstringchar < 0)
defdupchar = 0;
else
defdupchar = prefstringchar;
if (missingspaceflag < 0)
missingspaceflag = hashheader.defspaceflag;
if (tryhardflag < 0)
tryhardflag = hashheader.defhardflag;
initckch(wchars);
process_LibDict(LibDict, cpd);
if (process_a_e_and_d_flags() == 0)
return 0;
if (!islib)
setbuf(stdout, outbuf);
/* process lflag (also used with the -c option) */
if (lflag) {
infile = stdin;
outfile = stdout;
if (!islib)
checkfile();
return 0;
}
/* n. of parameters advanced */
return old_argc - argc;
}
/**
* @brief ...
* @param opt
*/
void init_jspell(char *opt)
{
int i, argc;
static char aux[1];
char options[255];
static char *argv[MAX_SOL];
strcpy(options, opt);
argc = 1;
aux[0] = '\0';
argv[0] = aux;
i = 0;
while (options[i] != '\0') {
argv[argc] = options+i;
argc++;
/* advance letters */
while (options[i] != ' ' && options[i] != '\0')
i++;
/* advance spaces */
while (options[i] == ' ') {
options[i] = '\0';
i++;
}
}
/* for (i = 0; i < argc; i++)
printf("%d %s\n", i, argv[i]); */
my_main(argc, argv, 1);
}
static void det_tflag(char *filename)
{
char *cp;
/* See if the file is a .tex file. If so, set the appropriate flags. */
tflag = deftflag;
if ((cp = rindex(filename, '.')) != NULL && strcmp(cp, ".tex") == 0)
tflag = 1;
}
static void det_defdupchar(char *filename)
{
if (prefstringchar < 0) {
defdupchar = findfiletype(filename, 0, &tflag);
if (defdupchar < 0) defdupchar = 0;
}
}
static void det_readonly_access(char *filename)
{
readonly = access(filename, W_OK) < 0;
if (readonly) {
fprintf(stderr, ISPELL_C_CANT_WRITE, filename);
sleep((unsigned) 2);
}
}
static void open_outfile(struct stat *statbuf)
{
int file_descriptor;
fstat(fileno(infile), statbuf);
strcpy(tempfile, TEMPNAME);
#ifdef __WIN__
file_descriptor = open(mktemp(tempfile),O_CREAT | O_RDWR | O_BINARY);
#else
file_descriptor = mkstemp(tempfile);
#endif
if ((outfile = fdopen(file_descriptor, "w")) == NULL) {
fprintf(stderr, CANT_CREATE, tempfile);
sleep((unsigned) 2);
return;
}
chmod(tempfile, statbuf->st_mode);
}
static void update_file(char *filename, struct stat *statbuf)
{
char bakfile[256];
int c;
if ((infile = fopen(tempfile, "r")) == NULL) {
fprintf(stderr, ISPELL_C_TEMP_DISAPPEARED, tempfile);
sleep((unsigned) 2);
return;
}
sprintf(bakfile, "%s%s", filename, BAKEXT);
if (strncmp(filename, bakfile, MAXNAMLEN) != 0)
unlink(bakfile); /* unlink so we can write a new one. */
#ifdef __WIN__
#else
if (link(filename, bakfile) == 0)
unlink(filename);
#endif
/* if we can't write new, preserve .bak regardless of xflag */
if ((outfile = fopen(filename, "w")) == NULL) {
fprintf(stderr, CANT_CREATE, filename);
sleep((unsigned) 2);
return;
}
chmod(filename, statbuf->st_mode);
while ((c = getc(infile)) != EOF)
putc(c, outfile);
fclose(infile);
fclose(outfile);
if (xflag && strncmp(filename, bakfile, MAXNAMLEN) != 0)
unlink(bakfile);
}
/**
* @brief ...
* @param filename
*/
void dofile(char *filename)
{
struct stat statbuf;
currentfile = filename;
/* Checks if this is a tex file */
det_tflag(filename);
det_defdupchar(filename);
if ((infile = fopen(filename, "r")) == NULL) {
fprintf(stderr, CANT_OPEN, filename);
sleep((unsigned) 2);
return;
}
det_readonly_access(filename);
open_outfile(&statbuf);
quit = 0;
changes = 0;
checkfile();
fclose(infile);
fclose(outfile);
if (!cflag)
treeoutput();
if (changes && !readonly)
update_file(filename, &statbuf);
unlink(tempfile);
}
/** ... */
extern char *root;
/** ... */
extern char *root_class;
/** ... */
extern char suf_class[MAXCLASS];
/* How to print:
* 1 = expansions only
* 2 = original line + expansions
* 3 = original paired w/ expansions
* 4 = add length ratio
*/
static void expandmode(int option) {
char buf[BUFSIZ];
int explength; /* Total length of all expansions */
register char *flagp; /* Pointer to next flag char */
ichar_t ibuf[BUFSIZ];
MASKTYPE mask[MASKSIZE];
char origbuf[BUFSIZ]; /* Original contents of buf */
char ratiobuf[20]; /* Expansion/root length ratio */
int rootlength; /* Length of root word */
register int temp;
/* char strg_out[MAXSOLLEN]; */
while (xgets(buf, sizeof buf, stdin) != NULL) {
rootlength = strlen(buf);
if (buf[rootlength - 1] == '\n')
buf[--rootlength] = '\0';
strcpy(origbuf, buf);
if ((flagp = index(buf, hashheader.flagmarker)) != NULL) {
rootlength = flagp - buf;
*flagp++ = '\0';
}
if (option == 2 || option == 3 || option == 4)
printf("%s ", origbuf);
if (flagp != NULL) {
if (flagp - buf > INPUTWORDLEN)
buf[INPUTWORDLEN] = '\0';
}
else {
if ((int) strlen(buf) > INPUTWORDLEN - 1)
buf[INPUTWORDLEN] = '\0';
}
fputs(buf, stdout);
fputc(' ', stdout);
/* strtoichar(ibuf, buf, sizeof ibuf, 1);
if (good(ibuf, 0, 0, 0)) {
get_info(hits[0]);
sprintf(strg_out, o_form, root, macro(root_class), pre_class,
macro(suf_class), suf2_class);
printf("%s ", strg_out);
}
*/
if (flagp != NULL) {
bzero((char *) mask, sizeof(mask));
while (*flagp != '\0' && *flagp != '\n') {
#if MASKBITS <= 32
temp = CHARTOBIT(mytoupper(chartoichar(*flagp)));
#else
temp = CHARTOBIT((unsigned char) *flagp);
#endif
if (temp >= 0 && temp <= LARGESTFLAG)
SETMASKBIT (mask, temp);
flagp++;
/* Accept old-format dicts with extra slashes */
if (*flagp == hashheader.flagmarker)
flagp++;
}
if (strtoichar(ibuf, buf, sizeof ibuf, 1))
fprintf(stderr, WORD_TOO_LONG(buf));
explength = expand_pre(origbuf, ibuf, mask, option, "");
explength += expand_suf(origbuf, ibuf, mask, 0, option, "", "");
explength += rootlength;
if (option == 4) {
sprintf(ratiobuf, " %f",
(double) explength / (double) rootlength);
fputs(ratiobuf, stdout);
expand_pre(origbuf, ibuf, mask, 3, ratiobuf);
expand_suf(origbuf, ibuf, mask, 0, 3, ratiobuf, "");
}
}
printf(SEP4);
}
}