#34 patch for memory bug fix, mingw build fix, gnu output adds

L Michaels

Tried sending this information to the maintainer's e-mail listed on the web site and with the program, but got no response. Am submitting it here, just in case it didn't get through the other way.

Below is a patch of the changes I needed to get it hunspell to compile natively on
Windows using MinGW 4.4.0 and msys with gettext library (and related
libintl, libiconv libraries) installed. I did have to copy
C:\MinGW\lib\gcc\mingw32\4.4.0\libstdc++.a to
C:\MinGW\lib\gcc\mingw32\4.4.0\libstdc++.a\libstdc++.dll.a at one point,
but other than that and the patch below, was able to compile without

I've also added some functionality to use it with programming editors that can understand
GNU gcc style error messages.

The first fix I made was to the gettext define. Was getting errors with
libintl.h such as "expected unqualified-id before 'const'" when this is
defined. It doesn't match with the definition in libintl.h.

When I ran in the -u or -U modes, I was getting a memory crash, but -u2
mode works fine. I commented out free(wlst[0]); with the case AUTO0, AUTO
statement in the pipe_interface function to fix it, since
pMS[d]->free_list(&wlst, ns); is getting called further down and looked
like it was possibly freeing the same memory. AUTO2 was working and
didn't have the extra free call.

Last change was to add some extra flags very similar to the AUTO flags
(-u, -U, -u2). I wanted functionally just like it, but I need the output
to look similar to the gnu compiler errors so that any programming editor
that can recognize the gnu compiler errors standard and jump to a specific
location based on those errors can also work with the spell checker
output. I added a -u3 option. I needed the name of the file in the error
output, but looks like when you run with a file name, the program requires
curses and I wanted output to go to stdout. As a workaround, I passed the
file to spell check through stdout, but added a -f flag to display
whatever file name I want to work with to the stdout. That way, I can
call hunspell with hunspell.exe -d en_US -u3 -f %1 < %1 in a batch file
and simulate the error output of a compiler. Works really well with any
programming editors that are gnu compiler error aware.

Hope you may be able to incorporate all or at least some of the
changes to the hunspell program. Thanks.

Patches for hunspell.cxx:

--- hunspell.cxx 2010-02-27 09:37:14.000000000 -0500
+++ new\hunspell.cxx 2010-04-08 15:28:39.018282500 -0400
@@ -27,7 +27,9 @@

#ifdef WIN32

+#ifndef __MINGW32__
#define gettext
#define LIBDIR "C:\\Hunspell\\"
#define USEROOODIR "Application Data\\OpenOffice.org 2\\user\\wordbook"
#define OOODIR \ @@ -150,6 +152,7 @@ int wordchars_utf16_free = 0;
int wordchars_utf16_len;
char * dicname = NULL;
char * privdicname = NULL;
+char * stdoutfilename = NULL;

int modified; // modified file sign
enum { NORMAL,
@@ -161,7 +164,8 @@ enum { NORMAL,
PIPE, // print only stars for LyX compatibility
AUTO0, // search typical error (based on
AUTO, // automatic spelling to standard output
- AUTO2 }; // automatic spelling to standard output with sed log
+ AUTO2, // automatic spelling to standard output with sed log
+ AUTO3 }; // automatic spelling to standard output with gnu
compiler error format
int filter_mode = NORMAL;
int printgood = 0; // print only good words and lines
int showpath = 0; // show detected path of the dictionary
@@ -607,7 +611,8 @@ if (pos >= 0) {

case AUTO0:
case AUTO:
- case AUTO2: {
+ case AUTO2:
+ case AUTO3: {
FILE * f = (filter_mode == AUTO) ? stderr : stdout;
if (!check(pMS, &d, token, NULL, NULL)) {
char ** wlst = NULL;
@@ -616,12 +621,17 @@ if (pos >= 0) {
if (ns > 0) {
parser->change_token(chenc(wlst[0], dic_enc[d], io_enc));
if (filter_mode != AUTO2) {
+ if (filter_mode != AUTO3) {
fprintf(f,gettext("Line %d: %s -> "), lineno,
chenc(token, io_enc, ui_enc));
fprintf(f, "%s\n",
chenc(wlst[0], dic_enc[d], ui_enc));
- free(wlst[0]);
- } else {
+// free(wlst[0]);
+ } else {
+ fprintf(f,"%s:%d: Locate: %s | Try: %s\n",
(stdoutfilename==NULL) ? "": stdoutfilename,lineno,
+ token, chenc(wlst[0], dic_enc[d], io_enc));
+ } } else {
fprintf(f,"%ds/%s/%s/g; # %s\n", lineno,
token, chenc(wlst[0], dic_enc[d], io_enc), buf);
@@ -1414,10 +1424,15 @@ int main(int argc, char** argv)
} else if (argstate == 4) {
key = argv[i];
argstate = 0;
+ } else if (argstate == 5) {
+ if (stdoutfilename) free(stdoutfilename);
+ stdoutfilename = mystrdup(argv[i]);
+ argstate = 0;
} else if (strcmp(argv[i],"-d")==0) argstate=1;
else if (strcmp(argv[i],"-p")==0) argstate=2;
else if (strcmp(argv[i],"-i")==0) argstate=3;
else if (strcmp(argv[i],"-P")==0) argstate=4;
+ else if (strcmp(argv[i],"-f")==0) argstate=5;
else if ((strcmp(argv[i],"-h") == 0) || (strcmp(argv[i],"--help") == 0)) {
fprintf(stderr,gettext("Usage: hunspell [OPTION]... [FILE]...\n"));
fprintf(stderr,gettext("Check spelling of each FILE. Without FILE,
check standard input.\n\n"));
@@ -1530,6 +1545,9 @@ int main(int argc, char** argv)
if (filter_mode != PIPE)
filter_mode = AUTO2;
+ } else if ((strcmp(argv[i],"-u3")==0)) {
+ if (filter_mode != PIPE)
+ filter_mode = AUTO3;
} else if ((strcmp(argv[i],"-G")==0)) {
printgood = 1;
} else if ((strcmp(argv[i],"-1")==0)) {
@@ -1694,6 +1712,7 @@ int main(int argc, char** argv)
if (dicname) free(dicname);
if (privdicname) free(privdicname);
if (path) free(path);
+ if (stdoutfilename) free(stdoutfilename);
if (aff) free(aff);
if (dic) free(dic);
if (wordchars) free(wordchars);


    • assigned_to: nobody --> caolan
  • I've just checked in your fix for the double free, and checked in a buildfix for mingw. For the remainder could you "attach" your patch to this issue using "add a file" on this web-page, seeing as its rather mangled with pasted inline

  • L Michaels
    L Michaels

    Patch file in Unix file format (linefeeds and no carriage returns)

  • L Michaels
    L Michaels

    Thanks. Hope the attached patch file works. If you need another format, please let me know.

  • Hmm, I think it would be better to remove the need for the -f flag, i.e. rejig the code a bit so that when we are not in "normal" mode then we don't need to use curses at all, and so allowing -uX with a file name + no curses support, and bubble the filename down from argv from -u2 to use.

    So I committed that to cvs, i.e. -u3 with or without curses support like...
    "hunspell -u3 apple"
    will say, e.g.
    apple:1: Locate: sitted | Try: sited
    without any need for a -f

    • assigned_to: caolan --> nobody
    • status: open --> closed-fixed