void trans(Node *p) { if (!p || tl_errs) return; if (tl_verbose || tl_terse) { fprintf(tl_out, "\t/* Normlzd: "); dump(p); fprintf(tl_out, " */\n"); } if (tl_terse) return; // Buddy might have been initialized by a third-party library. if (!bdd_isrunning()) { bdd_init(100000, 10000); // Disable the default GC handler. bdd_gbc_hook(0); } mk_alternating(p); if (!tl_hoaf || tl_hoaf > 1) { mk_generalized(); if ((!tl_spot_out || tl_spot_out > 2) && (!tl_hoaf || tl_hoaf > 2)) mk_buchi(); } releasenode(1, p); bdd_done(); }
/* ML type: int -> int -> unit */ EXTERNML value mlbdd_bdd_init(value nodes, value cachesize) /* ML */ { /* setup the our error handler */ bdd_error_hook(&mlbdd_errorhandler); bdd_init(Int_val(nodes), Int_val(cachesize)); bdd_error_hook(&mlbdd_errorhandler); /* bdd_gbc_hook(NULL); */ bdd_gbc_hook(mlbdd_gc); return Val_unit; }
/* NAME {* bdd\_init *} SECTION {* kernel *} SHORT {* initializes the BDD package *} PROTO {* int bdd_init(int nodesize, int cachesize) *} DESCR {* This function initiates the bdd package and {\em must} be called before any bdd operations are done. The argument {\tt nodesize} is the initial number of nodes in the nodetable and {\tt cachesize} is the fixed size of the internal caches. Typical values for {\tt nodesize} are 10000 nodes for small test examples and up to 1000000 nodes for large examples. A cache size of 10000 seems to work good even for large examples, but lesser values should do it for smaller examples. The number of cache entries can also be set to depend on the size of the nodetable using a call to {\tt bdd\_setcacheratio}. The initial number of nodes is not critical for any bdd operation as the table will be resized whenever there are to few nodes left after a garbage collection. But it does have some impact on the efficency of the operations. *} RETURN {* If no errors occur then 0 is returned, otherwise a negative error code. *} ALSO {* bdd\_done, bdd\_resize\_hook *} */ int bdd_init(int initnodesize, int cs) { int n, err; if (bddrunning) return bdd_error(BDD_RUNNING); bddnodesize = bdd_prime_gte(initnodesize); if ((bddnodes=(BddNode*)malloc(sizeof(BddNode)*bddnodesize)) == NULL) return bdd_error(BDD_MEMORY); bddresized = 0; for (n=0 ; n<bddnodesize ; n++) { bddnodes[n].refcou = 0; LOW(n) = -1; bddnodes[n].hash = 0; LEVEL(n) = 0; bddnodes[n].next = n+1; } bddnodes[bddnodesize-1].next = 0; bddnodes[0].refcou = bddnodes[1].refcou = MAXREF; LOW(0) = HIGH(0) = 0; LOW(1) = HIGH(1) = 1; if ((err=bdd_operator_init(cs)) < 0) { bdd_done(); return err; } bddfreepos = 2; bddfreenum = bddnodesize-2; bddrunning = 1; bddvarnum = 0; gbcollectnum = 0; gbcclock = 0; cachesize = cs; usednodes_nextreorder = bddnodesize; bddmaxnodeincrease = DEFAULTMAXNODEINC; bdderrorcond = 0; bddcachestats.uniqueAccess = 0; bddcachestats.uniqueChain = 0; bddcachestats.uniqueHit = 0; bddcachestats.uniqueMiss = 0; bddcachestats.opHit = 0; bddcachestats.opMiss = 0; bddcachestats.swapCount = 0; bdd_gbc_hook(bdd_default_gbchandler); bdd_error_hook(bdd_default_errhandler); bdd_resize_hook(NULL); bdd_pairs_init(); bdd_reorder_init(); bdd_fdd_init(); if (setjmp(bddexception) != 0) assert(0); return 0; }
/* NAME {* bdd\_init *} SECTION {* kernel *} SHORT {* initializes the BDD package *} PROTO {* int bdd_init(int nodesize, int cachesize) *} DESCR {* This function initiates the bdd package and {\em must} be called before any bdd operations are done. The argument {\tt nodesize} is the initial number of nodes in the nodetable and {\tt cachesize} is the fixed size of the internal caches. Typical values for {\tt nodesize} are 10000 nodes for small test examples and up to 1000000 nodes for large examples. A cache size of 10000 seems to work good even for large examples, but lesser values should do it for smaller examples. The number of cache entries can also be set to depend on the size of the nodetable using a call to {\tt bdd\_setcacheratio}. The initial number of nodes is not critical for any bdd operation as the table will be resized whenever there are to few nodes left after a garbage collection. But it does have some impact on the efficency of the operations. *} RETURN {* If no errors occur then 0 is returned, otherwise a negative error code. *} ALSO {* bdd\_done, bdd\_resize\_hook *} */ int bdd_init(int initnodesize, int cs) { /* Check to see if tracing is enabled */ char * str; if( (str = getenv("BUDDY_TRACE_FILE")) != NULL) { trace_enable = 1; trace_init(str); } { int n, err; BUDDY_PROLOGUE; ADD_ARG1(T_INT,initnodesize); ADD_ARG1(T_INT,cs); srand48( SRAND48SEED ) ; if (bddrunning) RETURN(bdd_error(BDD_RUNNING)); bddnodesize = bdd_prime_gte(initnodesize); if ((MAX_ALLOC_NODES == 0) || (alloced=(BddNode*)malloc(sizeof(BddNode)*MAX_ALLOC_NODES)) == NULL) { if ((alloced=(BddNode*)malloc(sizeof(BddNode)*bddnodesize)) == NULL) { RETURN(bdd_error(BDD_MEMORY)); } MAX_ALLOC_NODES = bddnodesize; } bddnodes = alloced; bddresized = 0; for (n=0 ; n<bddnodesize ; n++) { INIT_NODE(n); } SETNEXT(bddnodesize-1, 0); SETMAXREF(0); SETMAXREF(1); SETLOW(0,0); SETHIGH(0,0); SETLOW(1,1); SETHIGH(1,1); if ((err=bdd_operator_init(cs)) < 0) { bdd_done(); RETURN(err); } bddfreepos = 2; bddfreenum = bddnodesize-2; bddrunning = 1; bddvarnum = 0; gbcollectnum = 0; gbcclock = 0; cachesize = cs; usednodes_nextreorder = bddnodesize; bddmaxnodeincrease = DEFAULTMAXNODEINC; bddincreasefactor = 2; bdderrorcond = 0; bddcachestats.uniqueAccess = 0; bddcachestats.uniqueChain = 0; bddcachestats.uniqueHit = 0; bddcachestats.uniqueMiss = 0; bddcachestats.opHit = 0; bddcachestats.opMiss = 0; bddcachestats.swapCount = 0; bdd_gbc_hook(bdd_default_gbchandler); bdd_error_hook(bdd_default_errhandler); bdd_resize_hook(NULL); bdd_pairs_init(); bdd_reorder_init(); bdd_fdd_init(); if (setjmp(bddexception) != 0) assert(0); RETURN(0); } }
extern void verbose_gc() { bdd_gbc_hook(bdd_default_gbchandler); }
extern void setuperrorhandler() { bdd_error_hook(errorhandler); bdd_gbc_hook(NULL); }
int main(int argc,char **argv) { char ambiguous_treatment='A'; char linebuff[1024]; char *parseptr; PARSE_STATE ps; uint32_t low_code,high_code; int width,i,j,vi,vj; FILE *unicode_db; BDD x,y,child[8]; BDD *queue; int queue_low,queue_high,queue_max; puts("/*\n" " * GENERATED CODE - DO NOT EDIT!\n" " * Edit mkwcw.c, which generates this, or the input to that\n" " * program, instead. Distributions of IDSgrep will nonetheless\n" " * usually include a ready-made copy of this file because\n" " * compiling and running mkwcw.c requires a library and data\n" " * file that, although free, not everyone is expected to have.\n" " */\n\n" "#include \"_stdint.h\"\n" ); if (argc>1) ambiguous_treatment=argv[1][0]&~32; bdd_init(1000000,15625); bdd_setcacheratio(64); bdd_setvarnum(32); bdd_gbc_hook(NULL); defined_codes=bddfalse; zero_codes=bddfalse; wide_codes=bddfalse; /* yes, unfortunately UnicodeData.txt and EastAsianWidth.txt are just * different enough to need separate parsers, at least if the parsers * are as stupid as I'd like these ones to be */ if (argc>2) { unicode_db=fopen(argv[2],"rt"); while (1) { fgets(linebuff,sizeof(linebuff),unicode_db); if (feof(unicode_db)) break; ps=psLOW; linebuff[sizeof(linebuff)-1]='\0'; low_code=0; width=-1; for (parseptr=linebuff;(*parseptr) && (ps!=psSTOP);parseptr++) switch (ps) { case psLOW: if ((*parseptr>='0') && (*parseptr<='9')) low_code=(low_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) low_code=(low_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) low_code=(low_code<<4)+(*parseptr-'A'+10); else if (*parseptr==';') ps=psSEMI; else if ((*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces and tabs */ } else ps=psSTOP; /* this catches comment lines */ break; case psSEMI: if (*parseptr==';') ps=psWIDTH; break; case psWIDTH: if (((parseptr[0]=='M') && ((parseptr[1]=='e') || (parseptr[1]=='n'))) || ((parseptr[0]=='C') && (parseptr[1]=='f'))) width=0; /* FALL THROUGH */ default: ps=psSTOP; break; } if (width==0) set_range_width(low_code,low_code,0); } fclose(unicode_db); } while (1) { fgets(linebuff,sizeof(linebuff),stdin); if (feof(stdin)) break; ps=psLOW; linebuff[sizeof(linebuff)-1]='\0'; low_code=0; high_code=0; width=-1; for (parseptr=linebuff;(*parseptr) && (ps!=psSTOP);parseptr++) switch (ps) { case psLOW: if ((*parseptr>='0') && (*parseptr<='9')) low_code=(low_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) low_code=(low_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) low_code=(low_code<<4)+(*parseptr-'A'+10); else if (*parseptr=='.') ps=psHIGH; else if (*parseptr==';') { high_code=low_code; ps=psWIDTH; } else if ((*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces and tabs */ } else ps=psSTOP; /* this catches comment lines */ break; case psHIGH: if ((*parseptr>='0') && (*parseptr<='9')) high_code=(high_code<<4)+(*parseptr-'0'); else if ((*parseptr>='a') && (*parseptr<='f')) high_code=(high_code<<4)+(*parseptr-'a'+10); else if ((*parseptr>='A') && (*parseptr<='F')) high_code=(high_code<<4)+(*parseptr-'A'+10); else if ((*parseptr=='.') || (*parseptr==' ') || (*parseptr=='\t')) { /* skip spaces, tabs, and dots */ } else if (*parseptr==';') ps=psWIDTH; else ps=psSTOP; break; case psWIDTH: if (*parseptr=='A') *parseptr=ambiguous_treatment; switch (*parseptr) { case 'F': /* full-width treated as wide */ case 'W': /* wide */ width=2; break; case 'H': /* half-width treated as narrow */ case 'N': /* narrow or neutral */ width=1; break; case '0': /* zero-width - should only appear in user database */ width=0; break; default: /* ignore all others */ break; } /* FALL THROUGH */ default: ps=psSTOP; break; } if (width>=0) set_range_width(low_code,high_code,width); } printf("/* node counts before simplification: %d %d %d */\n", bdd_nodecount(defined_codes), bdd_nodecount(zero_codes), bdd_nodecount(wide_codes)); x=bdd_addref(bdd_simplify(wide_codes,defined_codes)); bdd_delref(wide_codes); wide_codes=x; x=bdd_addref(bdd_apply(defined_codes,wide_codes,bddop_diff)); bdd_delref(defined_codes); defined_codes=x; x=bdd_addref(bdd_simplify(zero_codes,defined_codes)); bdd_delref(zero_codes); zero_codes=x; printf("/* node counts after simplification: %d %d %d */\n\n", bdd_nodecount(defined_codes), bdd_nodecount(zero_codes), bdd_nodecount(wide_codes)); bdd_varblockall(); bdd_intaddvarblock(0,7,0); bdd_intaddvarblock(8,15,0); bdd_intaddvarblock(16,23,0); bdd_intaddvarblock(24,31,0); bdd_intaddvarblock(0,31,1); bdd_reorder_probe(&reordering_size_callback); puts("typedef struct _WIDTH_BBD_ENT {\n" " int16_t child[8];\n" " char byte,shift;\n" "} WIDTH_BDD_ENT;\n\n" "static WIDTH_BDD_ENT width_bdd[]={"); queue=(BDD *)malloc(sizeof(BDD)*1000); queue_max=1000; queue_low=2; queue_high=4; queue[0]=bddfalse; queue[1]=bddtrue; queue[2]=wide_codes; queue[3]=zero_codes; while (queue_low<queue_high) { if (queue_high+8>queue_max) { queue_max/=3; queue_max*=4; queue=(BDD *)realloc(queue,sizeof(BDD)*queue_max); } reorder_focus=queue[queue_low]; bdd_reorder(BDD_REORDER_WIN2ITE); vj=bdd_var(queue[queue_low]); vi=(vj/8)*8; vj=((vj-vi+1)/3)*3-1; if (vj<0) vj=0; x=bdd_addref(bdd_restrict(queue[queue_low],bdd_nithvar(vi+vj))); y=bdd_addref(bdd_restrict(x,bdd_nithvar(vi+vj+1))); child[0]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[1]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); y=bdd_addref(bdd_restrict(x,bdd_ithvar(vi+vj+1))); child[2]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[3]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); bdd_delref(x); x=bdd_addref(bdd_restrict(queue[queue_low],bdd_ithvar(vi+vj))); y=bdd_addref(bdd_restrict(x,bdd_nithvar(vi+vj+1))); child[4]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[5]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); y=bdd_addref(bdd_restrict(x,bdd_ithvar(vi+vj+1))); child[6]=bdd_addref(bdd_restrict(y,bdd_nithvar(vi+vj+2))); child[7]=bdd_addref(bdd_restrict(y,bdd_ithvar(vi+vj+2))); bdd_delref(y); bdd_delref(x); fputs(" {{",stdout); for (i=0;i<8;i++) { queue[queue_high]=child[i]; for (j=0;queue[j]!=child[i];j++); if (j==queue_high) queue_high++; else bdd_delref(child[i]); printf("%d",j-2); if (i<7) putchar(','); } printf("},%d,%d},\n",vi/8,5-vj); queue_low++; } puts("};\n\n" "int idsgrep_utf8cw(char *);\n" "\n" "#define WBS width_bdd[search]\n" "\n" "int idsgrep_utf8cw(char *cp) {\n" " int search;\n" "\n" " for (search=0;search>=0;)\n" " search=WBS.child[(cp[WBS.byte]>>WBS.shift)&7];\n" " if (search==-1)\n" " return 2;\n" " for (search=1;search>=0;)\n" " search=WBS.child[(cp[WBS.byte]>>WBS.shift)&7];\n" " return ((-1)-search);\n" "}\n"); bdd_done(); exit(0); }