Hugs has a Bug by My WindowsME

Sigbjorn Finne sof@galconn.com
Wed, 31 Oct 2001 11:38:20 -0800


This is a multi-part message in MIME format.

------=_NextPart_000_1029_01C16200.8A852C30
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hi,

my guess is that you've accidentally corrupted your Hugs98
settings, causing the fatal errors below.

Attached is some code for a utility that will restore your settings
back to the default ones; I posted this utility to this mailing list
a couple of months back, see

http://haskell.cs.yale.edu/pipermail/hugs-users/2001-August/000122.html

for more info.

hth
--sigbjorn

----- Original Message -----
From: <belal@web.de>
To: <hugs-users@haskell.org>
Sent: Tuesday, October 30, 2001 04:44
Subject: Hugs has a Bug by My WindowsME


> I've installed Hugs-Interpreter at my WIndowsME. And then it did not
functioned. I have becomed a messege:
> "FATAL ERROR:unable to load Prelude"..
> And another messege, which was in the hugs windows:
> "ERROR c:\Programme\hugs98\lib\Prelude.hs
> Garbage Collection fails to reclaim sufficient space"..
> I hope you can help me...
> PS: the file Prelude.hs is in the correct directory.


------=_NextPart_000_1029_01C16200.8A852C30
Content-Type: application/octet-stream;
	name="restore.c"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="restore.c"

/*
 * Hugs98 Registry reset app - get rid off the
 * user-specific Hugs98 options settings from the Registry.
 *
 * The reason why this util is needed is that Hugs doesn't=20
 * perform any validity checks when persisting the :set'able
 * options to the Registry. As a result, the user might end
 * up inadvertently zapping the search path, causing Hugs=20
 * to be unable to locate the Prelude the next time it starts
 * up. Which is undesirable, since it'll then exit before
 * the useris able to get to get to the interpreter prompt
 * & repair the damage done via another :set !!
 *
 * The only way to exit from this unhappy state of affairs
 * is to either be Registry-savy and do the mods 'regedit',
 * or reinstall. So, clearly some room for improvement in
 * usability here.
 *
 * This util is a stop-gap measure which lets the user rid
 * him/herself of the *user-specific* option settings that
 * Hugs will have saved in the Registry. By deleting the
 * user-specific settings, the next time Hugs starts up,
 * it'll default back to using the machine-wide default
 * options. i.e., the user may end up having to go in=20
 * and tweak these settings again, but at least Hugs has
 * been brought back into a useable state.
 *
 * To compile this utility, you'll need a Win32 C compiler;
 * here are the options to use with the three compilers I've
 * tested it with:
 *
 *  MSVC:       cl /o restorer restore.c advapi32.lib
 *  gcc:        gcc -mno-cygwin -o restorer restore.c
 *  lcc-win32:  lc restore.c -o main.exe
 *=20
 * 7/01 -- sof
 */
#include <windows.h>
#include <malloc.h>
#include <stdio.h>

#define MAX(x,y) ( x > y ? x : y)

#define HUGS_HCU_ROOT "Software\\Haskell\\Hugs"

/* This util inspects the Registry looking for
   existing Hugs installations in the current
   user hive.

   Store each one of the installs found in a table,
   so that we can later on go in and selectively
   reset each one of them.
*/

typedef struct {
  TCHAR*  keyName;
  HKEY    hKey;
} HugsInstall;

typedef struct {
  unsigned int size;
  unsigned int idx;
  HugsInstall* tab;
} InstallTable;

/*
 * Function:  initInstallTable ( unsigned int sz )
 *
 * Purpose:   Allocate a table (of 'sz' elements) that will
 *            hold information about available Hugs installation.
 *
 * Returns:   empty Hugs InstallTable of size 'sz' elements.
 */
InstallTable*
initInstallTable(unsigned int size)
{
  HugsInstall*  tab;
  InstallTable* table;
 =20
  table =3D (InstallTable*)malloc(sizeof(InstallTable));
 =20
  if (table =3D=3D NULL) {
    return table;
  }

  tab =3D (HugsInstall*)malloc(size * sizeof(HugsInstall));
 =20
  if (tab =3D=3D NULL) {
    free(table);
    return NULL;
  }
 =20
  table->size =3D size;
  table->idx  =3D 0;
  table->tab  =3D tab;
 =20
  return table;
}

void
DestroyTable(InstallTable* table)
{
  int i;
  if (!table)=20
    return;

  for ( i=3D0; i < (int)table->idx ; i++ ) {
    free(table->tab[i].keyName);
    RegCloseKey(table->tab[i].hKey);
  }
 =20
  free(table->tab);
  free(table);
} =20

/*
 * Function:  expandTable(InstallTable*)
 *
 * Purpose:   expand the installation table by 50%.
 *            Helper routine used by addInstall().
 *
 * Returns:   boolean indicating whether the expansion
 *            was successful or not.
 */
BOOL
expandTable(InstallTable* table)
{
  HugsInstall* tab;
  unsigned int newSz;
  if (!table) {
    return FALSE;
  }
 =20
  newSz =3D table->size + MAX(1, (table -> size / 2));
  tab =3D (HugsInstall*)realloc(table->tab, sizeof(HugsInstall) * =
newSz);

  if (tab =3D=3D NULL) {
    return FALSE;
  }

  table->size =3D newSz;
  table->tab  =3D tab;

  return TRUE;
}

BOOL
addHugsInstall(InstallTable* table, char* dirName, HKEY hKey)
{
  char* tmp;
  if (!table)
    return FALSE;

  /* idx points to the next available slot */
  if ( table->idx =3D=3D table->size ) {
    if ( !expandTable(table) ) {
      return FALSE;
    }
  }
 =20
  tmp =3D (char*)malloc(sizeof(char) * (strlen(dirName) + 1));
 =20
  if (!tmp)=20
    return FALSE;
 =20
  strcpy(tmp, dirName);
  table->tab[table->idx].keyName =3D tmp;
  table->tab[table->idx].hKey    =3D hKey;
 =20
  table->idx +=3D 1;
 =20
  return TRUE;
}

#define HandleRegError(msg, rc) printf("Error calling %s - return code =
=3D 0x%x\n", msg, rc)

void
ResetOption(InstallTable* table, int idx)
{
  LONG lRes;
 =20
  lRes =3D RegDeleteValue(table->tab[idx].hKey, "Options");
  printf("Finished resetting %s\n\n", table->tab[idx].keyName);
}

void
HandleDeletion(InstallTable* table)
{
  int i, idx;
  int ch;
  int val;
  char line[10];
  BOOL* delVector;
  int*  idxVector;
 =20
  printf("Hugs98 Repair Tool\n\n");

  printf("By selecting one of the installations below, you'll reset\n");
  printf("your user-specific options that Hugs98 has saved away\n");
  printf("in the Windows Registry (Resetting just gets you back\n");
  printf("to using the default Hugs options).\n\n");
 =20
  if (!table || table->idx =3D=3D 0) {
    printf("\n\n No local Hugs installations found. Exiting\n");
    return;
  }
 =20
  idxVector=3D(int*)malloc(sizeof(int) * (table->idx));
  delVector=3D(int*)malloc(sizeof(BOOL) * (table->idx));

  for (i=3D0;i < (int)table->idx; i++) {
    delVector[i]=3DFALSE;
    idxVector[i]=3D-1;
  }
  do {
    idx =3D 0;
    printf("Local Hugs98 installations: \n");
    for (i=3D0; i < (int)table->idx ; i++ ) {
      if (delVector[i]) {
	continue;
      }
      idxVector[idx] =3D i;
      printf("  %i - %s\n", idx+1, table->tab[i].keyName);
      idx++;
    }
 =20
    printf("\nInstallation to reset (0 =3D=3D reset all; ENTER to exit) =
? ");
    fflush(stdout);
    if (fgets(line,10,stdin) !=3D NULL) {
      if (line[0] =3D=3D '\n') {
	free(delVector);
	free(idxVector);
	return;
      }
      val =3D atoi(line);
      if (val !=3D 0) {
	if ( val > idx ) {
	  printf("Selection, %u, out of range\n", val);
	  continue;
	}
	ResetOption(table, idxVector[val-1]);
	delVector[idxVector[val-1]]=3DTRUE;
      } else {
	for (i=3D0; i < table->idx ; i++) {
	  if (!delVector[i]) {
	    ResetOption(table, i);
	  }
	}
	free(delVector);
	free(idxVector);
	break;
      }
    }
  } while (1);

}

int
main()
{
  HKEY hHugsKey;
  HKEY hSubKey;
  LONG lRes;
  TCHAR nameBuf [ 511 ];
  TCHAR nameBuf2 [ 2048 ];
  DWORD dwSize, dwIndex;
  InstallTable* table;
  FILETIME ft;

  lRes =3D=20
    RegOpenKeyEx ( HKEY_CURRENT_USER,
		   HUGS_HCU_ROOT,
		   0,
		   KEY_ALL_ACCESS,
		   &hHugsKey);
		  =20
  if ( lRes !=3D ERROR_SUCCESS ) {
    HandleRegError("RegOpenKey", lRes);
    return 1;
  }
 =20
  dwIndex =3D -1;
 =20
  table =3D initInstallTable(2);

  do {
    dwSize =3D sizeof ( nameBuf );
    dwIndex++;
    lRes =3D=20
      RegEnumKeyEx ( hHugsKey,
		     dwIndex,
		     nameBuf,
		     &dwSize,
		     NULL,
		     NULL,
		     NULL,
		     &ft);
    if ( lRes =3D=3D ERROR_SUCCESS ||
	 lRes =3D=3D ERROR_MORE_DATA ||=20
	 lRes =3D=3D ERROR_NO_MORE_ITEMS ) {
      strcpy(nameBuf2, HUGS_HCU_ROOT);
      strcat(nameBuf2, "\\");
      strcat(nameBuf2, nameBuf);

      RegOpenKeyEx ( HKEY_CURRENT_USER,
		     nameBuf2,
		     0,
		     KEY_ALL_ACCESS,
		     &hSubKey);
      if ( !addHugsInstall(table, nameBuf, hSubKey) ) {
	break;
      }
    }
  } while ( lRes =3D=3D ERROR_SUCCESS ||=20
	    lRes =3D=3D ERROR_MORE_DATA );=20
 =20
  if ( lRes !=3D ERROR_MORE_DATA && lRes !=3D ERROR_NO_MORE_ITEMS ) {
    HandleRegError("RegEnumKeyEx", lRes);
    return 0;
  }
 =20
  HandleDeletion(table);
 =20
  DestroyTable(table);
  RegCloseKey(hHugsKey);
 =20
  return 0;
}

------=_NextPart_000_1029_01C16200.8A852C30--