bitset.c

来自「开放源码的编译器open watcom 1.6.0版的源代码」· C语言 代码 · 共 321 行

C
321
字号
/****************************************************************************
*
*                            Open Watcom Project
*
*    Portions Copyright (c) 1983-2002 Sybase, Inc. All Rights Reserved.
*
*  ========================================================================
*
*    This file contains Original Code and/or Modifications of Original
*    Code as defined in and that are subject to the Sybase Open Watcom
*    Public License version 1.0 (the 'License'). You may not use this file
*    except in compliance with the License. BY USING THIS FILE YOU AGREE TO
*    ALL TERMS AND CONDITIONS OF THE LICENSE. A copy of the License is
*    provided with the Original Code and Modifications, and is also
*    available at www.sybase.com/developer/opensource.
*
*    The Original Code and all software distributed under the License are
*    distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
*    EXPRESS OR IMPLIED, AND SYBASE AND ALL CONTRIBUTORS HEREBY DISCLAIM
*    ALL SUCH WARRANTIES, INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF
*    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR
*    NON-INFRINGEMENT. Please see the License for the specific language
*    governing rights and limitations under the License.
*
*  ========================================================================
*
* Description:  Program to generate a set of macros to manipulate a
*               fixed-length (but arbitrarily large) bit set.
*
****************************************************************************/


#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include "walloca.h"

#define _NLONGS( x )    ( ( (x) + 31 ) / 32 )

static void emitHeaderInit( FILE *fp, int size, char *prefix, char *type_name )
//*****************************************************************************
// emit the typedef of the actual bitset into the generated file, as well as
// other misc cruft that belongs at the beginning of the header
{
    int         i;


    fprintf( fp, "#ifndef A_BIT_SET_DEFINED\n" );
    fprintf( fp, "typedef unsigned a_bit_set;\n" );
    fprintf( fp, "#define A_BIT_SET_DEFINED\n" );
    fprintf( fp, "#endif\n\n" );
    fprintf( fp, "#define %s_SIZE %d\n\n", prefix, size );
    fprintf( fp, "typedef struct %s {\n", type_name );
    for( i = 0; i < _NLONGS( size ); i++ ) {
        fprintf( fp, "\ta_bit_set\t_%d;\n", i );
    }
    fprintf( fp, "} %s;\n\n", type_name );
}

static void emitAssign( FILE *fp, int size, char *prefix, char *type_name )
//*************************************************************************
// emit definition of a macro to do assignment of bitsets
{
    int         i;

    fprintf( fp, "#define %sAssign( dst, src ) { \\\n", prefix );
    // fprintf( fp, "\t\t\t%s *srcp = &(src); \\\n\t\t\t%s *dstp = &(dst); \\\n", type_name, type_name );
    for( i = 0; i < _NLONGS( size ); i++ ) {
        fprintf( fp, "\t\t\t(dst)._%d = (src)._%d; \\\n", i, i );
    }
    fprintf( fp, "\t\t}\n\n" );
}

static void emitEmpty( FILE *fp, int size, char *prefix, char *type_name )
//************************************************************************
{
    int         i;

    type_name = type_name;
    fprintf( fp, "#define %sEmpty( set ) ( \\\n", prefix );
    for( i = 0; i < _NLONGS( size ); i++ ) {
        fprintf( fp, "\t\t\t(set)._%d == 0 %s\n", i,
                        ( i == ( _NLONGS( size ) - 1 ) ) ? " )" : "&& \\" );
    }
    fprintf( fp, "\n" );
}

static void emitSet( FILE *fp, int size, char *prefix, char *type_name )
//**********************************************************************
{
    int         i;
    char        c;

    fprintf( fp, "#define %sSet( dst, ", prefix );
    c = 'a';
    for( i = 0; i < _NLONGS( size ); i++ ) {
        fprintf( fp, "%c%s", c++, ( i == ( _NLONGS( size ) - 1 ) ) ? " ) { \\\n" : ", " );
    }
    for( c = 'a', i = 0; i < _NLONGS( size ); i++, c++ ) {
        fprintf( fp, "\t\t\t(dst)._%d = %c; \\\n", i, c );
    }
    fprintf( fp, "\t\t}\n\n" );
    fprintf( fp, "#define %sFirst( set ) %sSet( set, 1", prefix, prefix );
    for( i = 1; i < _NLONGS( size ); i++ ) {
        fprintf( fp, ", 0" );
    }
    fprintf( fp, " )\n\n" );
    fprintf( fp, "#define %sInit( set, val ) %sSet( set, val", prefix, prefix );
    for( i = 1; i < _NLONGS( size ); i++ ) {
        fprintf( fp, ", val" );
    }
    fprintf( fp, " )\n\n" );
}

static void emitIter( FILE *fp, int size, char *prefix, char *type_name )
//***********************************************************************
{
    int         i;

    fprintf( fp, "#define %sIter( routine, set ) { \\\n", prefix );
    for( i = 0; i < _NLONGS( size ); i++ ) {
        fprintf( fp, "\t\t\t(routine)( (set)._%d ); \\\n", i );
    }
    fprintf( fp, "\t\t}\n\n" );
}

static void emitOverlap( FILE *fp, int size, char *prefix, char *type_name )
//**************************************************************************
{
    int         i;

    fprintf( fp, "#define %sOverlap( a, b ) ( \\\n", prefix );
    for( i = 0; i < _NLONGS( size ) - 1; i++ ) {
        fprintf( fp, "\t\t\t( (a)._%d & (b)._%d ) || \\\n", i, i );
    }
    fprintf( fp, "\t\t\t( (a)._%d & (b)._%d ) )\n\n", i, i );
}

static void emitSame( FILE *fp, int size, char *prefix, char *type_name )
//***********************************************************************
{
    int         i;

    fprintf( fp, "#define %sSame( a, b ) ( \\\n", prefix );
    for( i = 0; i < _NLONGS( size ) - 1; i++ ) {
        fprintf( fp, "\t\t\t( (a)._%d == (b)._%d ) && \\\n", i, i );
    }
    fprintf( fp, "\t\t\t( (a)._%d == (b)._%d ) )\n\n", i, i );
}

static void emitIntersect( FILE *fp, int size, char *prefix, char *type_name )
//****************************************************************************
{
    int         i;

    fprintf( fp, "#define %sIntersect( a, b ) { \\\n", prefix );
    for( i = 0; i < _NLONGS( size ); i++ ) {
        fprintf( fp, "\t\t\t(a)._%d &= (b)._%d; \\\n", i, i );
    }
    fprintf( fp, "\t\t}\n\n" );
}

static void emitTurnOff( FILE *fp, int size, char *prefix, char *type_name )
//**************************************************************************
{
    int         i;

    fprintf( fp, "#define %sTurnOff( a, b ) { \\\n", prefix );
    for( i = 0; i < _NLONGS( size ); i++ ) {
        fprintf( fp, "\t\t\t(a)._%d &= ~(b)._%d; \\\n", i, i );
    }
    fprintf( fp, "\t\t}\n\n" );
}

static void emitTurnOn( FILE *fp, int size, char *prefix, char *type_name )
//*************************************************************************
{
    int         i;

    fprintf( fp, "#define %sTurnOn( a, b ) { \\\n", prefix );
    for( i = 0; i < _NLONGS( size ); i++ ) {
        fprintf( fp, "\t\t\t(a)._%d |= (b)._%d; \\\n", i, i );
    }
    fprintf( fp, "\t\t}\n\n" );
}

static void emitScalar( FILE *fp, int size, char *prefix, char *type_name )
//*************************************************************************
{
    fprintf( fp, "#define %sScalar( a ) ( (a)._0 )\n\n", prefix );
}

static void emitStmt( FILE *fp, int indent, char *stmt )
//******************************************************
{
    while( indent >= 2 ) {
        fprintf( fp, "\t" );
        indent -= 2;
    }
    if( indent ) {
        fprintf( fp, "    " );
    }
    fprintf( fp, "%s\n", stmt );
}

static void doSet( FILE *fp, int indent, int size, char *prefix, char *var, int which_long )
//******************************************************************************************
// set the given long in the bitset (_0 == 0) to 1, and all other bits
// to 0
{
    char        *buffer;
    int         i;
    char        *ptr;

    buffer = alloca( strlen( var ) + strlen( prefix ) + _NLONGS( size ) * 3 + 100 );
    sprintf( buffer, "%sSet( *%s, ", prefix, var );
    ptr = buffer + strlen( buffer );
    for( i = 0; i < _NLONGS( size ) - 1; i++ ) {
        sprintf( ptr, "%d, ", ( i == which_long ) ? 1 : 0 );
        ptr += 3;
    }
    sprintf( ptr, "%d );", ( i == which_long ) ? 1 : 0 );
    emitStmt( fp, indent, buffer );
}

static void doShift( FILE *fp, int indent, int size, char *var )
//**************************************************************
{
    int         i;
    char        buffer[ 80 ];

    for( i = 0; i < _NLONGS( size ); i++ ) {
        sprintf( buffer, "(*%s)._%d <<= 1;", var, i );
        emitStmt( fp, indent, buffer );
    }
}

static void checkOtherBits( FILE *fp, int indent, int size, char *prefix, char *var, int which_long ) {
//*****************************************************************************************************

    if( which_long >= _NLONGS( size ) ) {
        doShift( fp, indent, size, var );
    } else {
        char    buffer[ 80 ];

        sprintf( buffer, "if( %s->_%d & 0x80000000 ) {", var, which_long );
        emitStmt( fp, indent, buffer );
        doSet( fp, indent + 1, size, prefix, var, which_long + 1 );
        emitStmt( fp, indent, "} else {" );
        checkOtherBits( fp, indent + 1, size, prefix, var, which_long + 1 );
        emitStmt( fp, indent, "}" );
    }
}

static void emitBitNext( FILE *fp, int size, char *prefix, char *type_name )
//**************************************************************************
{
    int         indent;

    fprintf( fp, "#ifdef %s_DEFINE_BITNEXT\n", prefix );
    fprintf( fp, "static void %sNext( %s *set ) {\n\n", prefix, type_name );
    indent = 1;
    if( size > 32 ) {
        emitStmt( fp, indent, "if( set->_0 & 0x80000000 ) {" );
        doSet( fp, indent + 1, size, prefix, "set", 1 );
        emitStmt( fp, indent, "} else {" );
        if( size > 64 ) {
            checkOtherBits( fp, indent + 1, size, prefix, "set", 1 );
        } else {
            doShift( fp, indent + 1, size, "set" );
        }
        emitStmt( fp, indent, "}" );
    } else {
        doShift( fp, indent, size, "set" );
    }
    fprintf( fp, "}\n" );
    fprintf( fp, "#endif\n\n" );
}

void genBitsetHeader( char *file, int size, char *prefix, char *type_name )
//*************************************************************************
// create a header file named 'file' which contains type and macro definitions
// for dealing with a bitset of length 'size'.
{
    FILE        *fp;

    fp = stdout;
    if( file != NULL ) {
        fp = fopen( file, "wt" );
    }
    if( fp != NULL ) {
        emitHeaderInit( fp, size, prefix, type_name );
        emitAssign( fp, size, prefix, type_name );
        emitEmpty( fp, size, prefix, type_name );
        emitSet( fp, size, prefix, type_name );
        emitIter( fp, size, prefix, type_name );
        emitOverlap( fp, size, prefix, type_name );
        emitSame( fp, size, prefix, type_name );
        emitTurnOff( fp, size, prefix, type_name );
        emitIntersect( fp, size, prefix, type_name );
        emitTurnOn( fp, size, prefix, type_name );
        emitScalar( fp, size, prefix, type_name );
        emitBitNext( fp, size, prefix, type_name );
        fclose( fp );
    } else {
        fprintf( stderr, "Error: unable to create file '%s': %s\n", file, strerror( errno ) );
    }
}

int main( int argc, char *argv[] ) {

    if( argc != 5 ) {
        fprintf( stderr, "usage: %s <size> <prefix> <type_name> <file>\n", argv[ 0 ] );
        exit( EXIT_FAILURE );
    }
    genBitsetHeader( argv[ 4 ], atoi( argv[ 1 ] ), argv[ 2 ], argv[ 3 ] );
    return 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?