home *** CD-ROM | disk | FTP | other *** search
- /****************************************************************************
- *
- * main.c
- *
- * By John A. Schlack
- * Dates: October 1994 - November 1994
- *
- * Description:
- *
- * This module has the main module and support routines for generating
- * the irredundant prime implicants. It gathers data from the user,
- * handles error conditions and some memory allocation. The functions
- * that perform the real work are located in "decimal.c" and "ir.c".
- *
- *
- * Release Notes:
- *
- * 1.10 11/02/94 Created to manage generation of irredundant prime
- * implicants.
- * 1.20 11/28/94 Modified input routines to accept a range for
- * decimal function specification. One places a dash
- * between the numbers, no white spaces.
- *
- ****************************************************************************/
-
-
- #define MAIN_C
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- #include <ctype.h>
- #include <stdlib.h>
- #include <stdio.h>
- #include <string.h>
-
- #include "qmPrime.h"
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- #if DEBUG
- FILE * fp;
- #endif
-
- static char userData[120];
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /* PROTOTYPES */
-
- void main( void );
- static short getFunction( decimalArray * output, decimalArray * dontCare, short * vars );
- static short * getPartialFunction( char * prompt, short * len, short vars,
- short * ignore, short ignoreLen );
- static int ascendingOrder( const void * a1, const void * a2 );
- static short parseFunction( char * cp, short * dec, short * dnum, long max,
- short * ignore, short ignoreLen );
- static void makeDecimal( char * field1, char * field2, short * decList, short * decNum,
- long maxValue, short * ignore, short ignoreLen );
- static void freeIrredundant( irredundant * ir );
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- void main( void )
- {
- decimalArray output, dontCare;
- short actualVars;
-
- #if DEBUG
- fp = fopen( "debug.out", "wt" );
- if (fp == NULL)
- {
- printf( "Cannot open debug file...aborting\n" );
- exit( 4 );
- }
- #endif
-
- printf( "\n\n------------------------------------------------\n\n" );
- printf( "Quine-McClusky Method (version 1.2)\n\nby John A. Schlack\nNovember 29, 1994\n\n" );
-
- #if defined(powerc) || defined (__powerc)
- printf( "Power Macintosh version\nCompiled using Metrowerks CodeWarrior 4.5\n" );
- #elif defined(__MWERKS__)
- printf( "68K Macintosh version\nCompiled using Metrowerks CodeWarrior 4.5\n" );
- #else
- printf( "PC version\nCompiled using Borland C++ 2.0\n" );
- #endif
-
- printf( "(Originally developed on a Power Macintosh 6100/80 using CodeWarrior 4.5)\n\n" );
- printf( "------------------------------------------------\n\n" );
-
- // initialize
- memset( &output, 0, sizeof( output ) );
- memset( &dontCare, 0, sizeof( dontCare ) );
-
- // retrieve desired function from user
- if (getFunction( &output, &dontCare, &actualVars ))
- {
- QuineMcClusky( &output, &dontCare, actualVars );
- free( output.array );
- if (dontCare.array != NULL)
- free( dontCare.array );
- }
-
- #if DEBUG
- fclose( fp );
- #endif
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- void QuineMcClusky( decimalArray * output, decimalArray * dontCare, short actualVars )
- {
- irredundant * primes;
- short * function, funcLen;
-
- // build combined list of decimals
- funcLen = output->len + dontCare->len;
- function = (short *) malloc( funcLen * sizeof( short ) );
- if (function == NULL)
- lowMemory();
-
- memcpy( function, output->array, output->len * sizeof( short ) );
- if (dontCare->len)
- memcpy( function + output->len, dontCare->array, dontCare->len * sizeof( short ) );
- qsort( function, funcLen, sizeof( short ), ascendingOrder );
-
- // get prime implicants
- primes = doDecimal( function, funcLen, actualVars );
- free( function );
-
- // reduce to irredundant form
- if (primes != NULL)
- {
- irredundantForm( primes, output->array, output->len, actualVars );
- freeIrredundant( primes );
- }
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- void lowMemory( void )
- {
- printf( "Insufficient memory to execute this program. Exiting...\n" );
- exit( 1 );
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- void paramError( char * funcName, short param )
- {
- printf( "Parameter error in function %.32s argument %d\n", funcName, param );
- exit( 2 );
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- static short getFunction( decimalArray * output, decimalArray * dontCare, short * vars )
-
- Description:
- This routine controls the retrieval of function information from the user.
- The user is prompted for the number of variables in the function and the
- function expressed in decimal notation (sum of products entries).
-
- Input:
- none
-
- Output:
- "output" contains the actual decimal output array and its length.
- "dontCare" contains an array of decimal don't care conditions and its length.
- "vars" is the number of variables in the user's function.
-
- Globals Modified:
- none
-
- Returns:
- Boolean flag (1 or 0) indicating whether valid data has been entered.
- */
-
-
- static short getFunction( decimalArray * output, decimalArray * dontCare, short * vars )
- {
- long decNum;
-
- // get number of variables
- do
- {
- printf( "\nEnter the number of variables (2 to %d)...", MAX_VARS );
- gets( userData );
- sscanf( userData, "%ld", &decNum );
- *vars = (short) decNum;
- if (*vars <= 0)
- {
- printf( "Exiting...\n" );
- exit( 0 );
- }
- } while ((*vars < 2) || (*vars > MAX_VARS));
-
- output->array = getPartialFunction( "decimal function", &output->len, *vars,
- NULL, 0 );
- if (output->len <= 0)
- {
- printf( "Function undefined. Exiting...\n" );
- exit( 3 );
- }
-
- dontCare->array = getPartialFunction( "don't cares", &dontCare->len, *vars,
- output->array, output->len );
-
- return 1;
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- static short * getPartialFunction( char * prompt, short * len, short vars,
- short * ignore, short ignoreLen )
- {
- long decNum;
- size_t size;
- short * decimal, count, more;
-
- // allocate memory to store decimal representation of function
- decNum = 1L << vars;
- size = (size_t) (decNum * sizeof( short ));
- decimal = malloc( size );
- if (decimal == NULL)
- lowMemory();
- memset( decimal, 0xFF, size );
- count = 0;
-
- printf( "\n-------------\n" );
-
- // get function
- do
- {
- printf( "\n\nEnter the %.40s. Each entry must be separated by\n", prompt );
- printf( "a space or comma. If you need more than one line to enter\n" );
- printf( "the data, end the line with a comma or plus sign.\n\n" );
- userData[0] = 0;
- gets( userData );
- userData[sizeof( userData ) - 1] = 0; // make sure we are null terminated
- more = parseFunction( userData, decimal, &count, decNum, ignore, ignoreLen );
- } while (more);
-
- if (count > 0)
- {
- qsort( decimal, decNum, sizeof( short ), ascendingOrder );
- size = count * sizeof( short );
- decimal = realloc( decimal, size );
- }
- else
- {
- free( decimal );
- decimal = NULL;
- }
-
- *len = count;
- return decimal;
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- static int ascendingOrder( const void * a1, const void * a2 )
-
- Description:
- This function is used by qsort() to place the decimal function data
- into ascending order.
-
- Input:
- none
-
- Output:
- "a1" and "a2" are pointers to the elements being compared.
-
- Globals Modified:
- none
-
- Returns:
- -1 if a1<a2, 1 if a1>a2, 0 if a1=a2
- */
-
-
- static int ascendingOrder( const void * a1, const void * a2 )
- {
- unsigned short v1, v2;
-
- v1 = *((unsigned short *) a1);
- v2 = *((unsigned short *) a2);
- if (v1 < v2)
- return -1;
- if (v1 > v2)
- return 1;
- return 0;
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- static short parseFunction( char * cp, short * dec, short * dnum, long max,
- short * ignore, short ignoreLen )
- {
- #define MAX_STR_SIZE 15
-
- char str[MAX_STR_SIZE+1], str2[MAX_STR_SIZE+1], lastNonWhite;
- short i, i2, badFlag, doSecond;
-
- // scan line
- lastNonWhite = 0;
- badFlag = 0;
- doSecond = 0;
- for (i=i2=0; *cp; cp++)
- {
- if (!isspace( *cp ))
- lastNonWhite = *cp;
- if (isalnum( *cp ) || (*cp == '-'))
- {
- // flag error if field too long
- if ( (!doSecond && (i >= MAX_STR_SIZE)) || (doSecond && (i2 >= MAX_STR_SIZE)) )
- badFlag = 1;
-
- // start recording second digit
- else if (*cp == '-')
- {
- if (doSecond)
- badFlag = 1;
- else
- doSecond = 1;
- }
-
- // save character for conversion
- else if (isdigit( *cp ))
- {
- if (!doSecond && (i < MAX_STR_SIZE))
- str[i++] = *cp;
- else if (doSecond && (i2 < MAX_STR_SIZE))
- str2[i2++] = *cp;
- }
-
- // flag error for non-digit
- else
- badFlag = 1;
- }
- else
- {
- str[i] = 0;
- str2[i2] = 0;
- if (badFlag)
- {
- printf( "Invalid input" );
- if (i > 0)
- {
- printf( ": %.16s", str );
- if (i2 > 0)
- printf( ", %.16s", str2 );
- }
- putc( '\n', stdout );
- }
- else
- makeDecimal( str, str2, dec, dnum, max, ignore, ignoreLen );
-
- i = 0;
- i2 = 0;
- badFlag = 0;
- doSecond = 0;
- }
- }
-
- // in case have unprocessed decimal value
- if ((i > 0) && (!badFlag))
- {
- str[i] = 0;
- str2[i2] = 0;
- makeDecimal( str, str2, dec, dnum, max, ignore, ignoreLen );
- }
-
- // return whether more input lines are expected
- return (((lastNonWhite == ',') || (lastNonWhite == '+')) ? 1 : 0);
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- static void makeDecimal( char * field1, char * field2, short * decList, short * decNum,
- long maxValue, short * ignore, short ignoreLen )
- {
- long value, value2, j;
- short i;
-
- // convert field and verify range
- value = atol( field1 );
- if (field2[0])
- value2 = atol( field2 );
- else
- value2 = value;
-
- if ((value < 0) || (value >= maxValue) || (value2 < 0) || (value2 >= maxValue))
- {
- printf( "Invalid input range: %.16s %.16s\n", field1, field2 );
- return;
- }
-
- // do not permit don't cares with same decimal as output
- if (ignore != NULL)
- {
- for (j=value; j<=value2; j++)
- {
- i = (short) j;
- if (bsearch( &i, ignore, sizeof( short ), ignoreLen, ascendingOrder ) != NULL)
- {
- printf( "Duplicated input: %ld\n", value );
- return;
- }
- }
- }
-
- for (j=value; j<=value2; j++)
- {
- // determine if value is already in list
- for (i=0; i<*decNum; i++)
- if (decList[i] == (short) j)
- return;
-
- // insert entry in list
- decList[*decNum] = (short) j;
- (*decNum)++;
- }
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- Properly copies two blocks of data, even if they overlap.
- */
- void blockMove( char * dst, char * src, size_t len )
- {
- size_t i;
-
- if (len <= 0)
- return;
- if (dst > src)
- {
- len--;
- dst += len;
- src += len;
- for (i=len; i>=0; i--)
- *dst++ = *src++;
- }
- else if (dst < src)
- {
- for (i=0; i<len; i++)
- *dst++ = *src++;
- }
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- void printNumbers( FILE * fout, unsigned char * numStr, short len )
- {
- short i;
-
- for (i=0; i<len; i++)
- fprintf( fout, "%2d ", (int) (numStr[i]) );
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- static void freeIrredundant( irredundant * ir )
- {
- irElement * elem;
- short i;
-
- if (ir == NULL)
- return;
-
- if (ir->irArray != NULL)
- {
- elem = ir->irArray;
- for (i=0; i<ir->len; i++, elem++)
- {
- if (elem->decimal != NULL)
- free( elem->decimal );
- if (elem->difference != NULL)
- free( elem->difference );
- }
-
- free( ir->irArray );
- }
- free( ir );
- }
-
-
- /* --------------------------------------------------------------------------------------------- */
-
-
- /*
- void printEntry( unsigned char * decimal, unsigned char * difference,
- short level, short vars, short * minLevel )
-
- Description:
- This function prints a prime implicant to the screen.
-
- Input:
- "decimal" is the list of decimal functions that were used in creating
- this prime implicant.
- "difference" is an array of exclusing values that are used to display
- the prime implicant.
- "level" is the list number in which this prime implicant resides
- (used for determining the number of entries in "difference"
- and "decimal").
- "vars" is the number of variables for this function.
- "minLevel" is used for determining the number of spaces to print
- between prime implicant and decimal list. This is only used
- with the non-reduced list of primes.
-
- Output:
- none
-
- Globals Modified:
- none
-
- Returns:
- none
- */
-
-
- void printEntry( unsigned char * decimal, unsigned char * difference,
- short level, short vars, short * minLevel )
- {
- short count, i, spaces, numDec;
- unsigned char * diff, ignore, number, mask;
-
- if (decimal == NULL)
- return;
-
- // build a number with all "differences" ORed together
- ignore = 0;
- if (difference != NULL)
- {
- diff = difference;
- for (i=1; i<level; i++, diff++)
- {
- if (*diff)
- ignore |= *diff;
- else
- {
- printf( "\n*** ERROR! Invalid number of 'ignore' arguments (level=%d). ***\n", level );
- break;
- }
- }
- }
-
- // print individual elements of prime implicant
- number = *(decimal);
- mask = 1 << (vars - 1);
- for (i=1, count=0; i<=vars; i++, mask>>=1)
- {
- // if this var's ignore bit is set, skip it
- if (ignore & mask)
- continue;
-
- // print variable
- printf( "x%d%c ", vars - i, (number & mask) ? (' ') : ('\'') );
- count++;
- }
-
- // print decimal components
- if (minLevel != NULL)
- {
- if (*minLevel <= 0)
- *minLevel = level;
- spaces = (level - *minLevel) * 4 + 8;
- for (i=0; i<spaces; i++)
- putc( ' ', stdout );
- putc( '(', stdout );
- numDec = 1 << (level - 1);
- printNumbers( stdout, decimal, numDec );
- putc( ')', stdout );
- }
-
- if (count)
- putc( '\n', stdout );
- }
-