/* -*- Mode: C; c-file-style: "stroustrup" -*- */ /** * @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-2006, * Ulisses Pinto, * José João Almeida, * Alberto Simões, * * Projecto Natura, * Universidade do Minho */ #include #include #include #include #include #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[]) { cpd = (*argv)+2; if (*cpd == '\0') { argv++; argc--; add_inc = 1; if (argc == 0) usage(cmd); cpd = *argv; if (*cpd == '\0') cpd = NULL; } 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) return 0; 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); } }