/* -*- Mode:Text -*- */
#ifndef lint
static char Rcs_Id[] =
    "$Id: dump.c,v 1.5 91/07/11 19:52:01 geoff Exp $";
#endif

/*
 * dump.c - Ispell's dump mode
 *
 * This code originally resided in ispell.c, but was moved here to keep
 * file sizes smaller.
 *
 * Copyright 1987, 1988, 1989, by Geoff Kuenning, Manhattan Beach, CA
 * Permission for non-profit use is hereby granted.
 * All other rights reserved.
 * See "version.h" for a more complete copyright notice.
 */

/*
 * $Log:	dump.c,v $
 * Revision 1.5  91/07/11  19:52:01  geoff
 * Remove the include of stdio.h, since ispell.h now does this.
 * 
 * Revision 1.4  90/12/31  00:59:08  geoff
 * Reformat to follow a consistent convention throughout ispell
 * 
 * Revision 1.3  90/04/26  22:43:55  geoff
 * Add the canonicaliethe call to ichartosstr.
 * 
 * Revision 1.2  89/10/20  00:10:36  geoff
 * Remove version.h
 * 
 * Revision 1.1  89/06/27  01:56:22  geoff
 * Break ispell.c up into smaller files
 * 
 *
 * The following log lines are from when this code was in ispell.c:
 *
 * Revision 1.67  89/04/27  23:31:25  geoff
 * Fix extraletter() to work properly with string characters (it didn't
 * actually delete the extra letter).  Get rid of a couple of duplicate
 * tests for backslashing the flag marker in dumpmode().
 * 
 * Revision 1.60  88/12/12  02:18:16  geoff
 * Correctly handle null additions in dump mode
 * 
 * Revision 1.46  88/02/20  23:11:30  geoff
 * Fix a bug that caused multiple single quotes (e.g., ``xx'' as in many
 * troff source files) to be considered as part of the word.  Major changes
 * to add support for the new capitalization handling.  If a word has wrong
 * capitalization, don't try other corrections.  Fix entdump to handle
 * flags with null affixes.
 * 
 */

#include "config.h"
#include "ispell.h"

void		dumpmode ();		/* Execute -D flag */
static void	tbldump ();		/* Dump a flag table */
static void	entdump ();		/* Dump one flag entry */
static void	setdump ();		/* Dump a set specification */
static void	subsetdump ();		/* Dump part of a set spec */

void dumpmode ()
    {

    if (hashheader.flagmarker == '\\'
      ||  hashheader.flagmarker == '#'
      ||  hashheader.flagmarker == '>'
      ||  hashheader.flagmarker == ':'
      ||  hashheader.flagmarker == '-'
      ||  hashheader.flagmarker == ','
      ||  hashheader.flagmarker == '[')
	(void) printf ("flagmarker \\%c\n", hashheader.flagmarker);
    else if (hashheader.flagmarker < ' '  ||  hashheader.flagmarker >= 0177)
	(void) printf ("flagmarker \\%3.3o\n", hashheader.flagmarker & 0xFF);
    else	    
	(void) printf ("flagmarker %c\n", hashheader.flagmarker);
    if (numpflags)
	{
	(void) printf ("prefixes\n");
	tbldump (pflaglist, numpflags);
	}
    if (numsflags)
	{
	(void) printf ("suffixes\n");
	tbldump (sflaglist, numsflags);
	}
    }

static void tbldump (flagp, numflags)	/* Dump a flag table */
    register struct flagent *	flagp;	/* First flag entry to dump */
    register int		numflags; /* Number of flags to dump */
    {

    while (--numflags >= 0)
	entdump (flagp++);
    }

static void entdump (flagp)		/* Dump one flag entry */
    register struct flagent *	flagp;	/* Flag entry to dump */
    {
    register int		cond;	/* Condition number */

    (void) printf ("  flag %s%c: ",
      (flagp->flagflags & FF_CROSSPRODUCT) ? "*" : " ",
      BITTOCHAR (flagp->flagbit));
    for (cond = 0;  cond < flagp->numconds;  cond++)
	{
	setdump (flagp->conds, 1 << cond);
	if (cond < flagp->numconds - 1)
	    (void) putc (' ', stdout);
	}
    if (cond == 0)			/* No conditions at all? */
	(void) putc ('.', stdout);
    (void) printf ("\t> ");
    (void) putc ('\t', stdout);
    if (flagp->stripl)
	(void) printf ("-%s,", flagp->strip);
    (void) printf ("%s\n", flagp->affl ? ichartosstr (flagp->affix, 1) : "-");
    }

static void setdump (setp, mask)	/* Dump a set specification */
    register char *		setp;	/* Set to be dumped */
    register int		mask;	/* Mask for bit to be dumped */
    {
    register int		cnum;	/* Next character's number */
    register int		firstnz; /* Number of first NZ character */
    register int		numnz;	/* Number of NZ characters */

    numnz = 0;
    for (cnum = SET_SIZE;  --cnum >= 0;  )
	{
	if (setp[cnum] & mask)
	    {
	    numnz++;
	    firstnz = cnum;
	    }
	}
    if (numnz == 1)
	(void) putc (firstnz, stdout);
    else if (numnz == SET_SIZE)
	(void) putc ('.', stdout);
    else if (numnz > SET_SIZE / 2)
	{
	(void) printf ("[^");
	subsetdump (setp, mask, 0);
	(void) putc (']', stdout);
	}
    else
	{
	(void) putc ('[', stdout);
	subsetdump (setp, mask, mask);
	(void) putc (']', stdout);
	}
    }

static void subsetdump (setp, mask, dumpval) /* Dump part of a set spec */
    register char *		setp;	/* Set to be dumped */
    register int		mask;	/* Mask for bit to be dumped */
    register int		dumpval; /* Value to be printed */
    {
    register int		cnum;	/* Next character's number */
    register int		rangestart; /* Value starting a range */

    for (cnum = 0;  cnum < SET_SIZE;  setp++, cnum++)
	{
	if (((*setp ^ dumpval) & mask) == 0)
	    {
	    for (rangestart = cnum;  cnum < SET_SIZE;  setp++, cnum++)
		{
		if ((*setp ^ dumpval) & mask)
		    break;
		}
	    if (cnum == rangestart + 1)
		(void) putc (rangestart, stdout);
	    else if (cnum <= rangestart + 3)
		{
		while (rangestart < cnum)
		    {
		    (void) putc (rangestart, stdout);
		    rangestart++;
		    }
		}
	    else
		(void) printf ("%c-%c", rangestart, cnum - 1);
	    }
	}
    }
