home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 3
/
goldfish_volume_3.bin
/
files
/
text
/
misc
/
cvt
/
source
/
rules.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-05-28
|
5KB
|
233 lines
/* -*- C -*-
* RULES.C
*
* (c)Copyright 1991-93 by Tobias Ferber, All Rights Reserved
*/
#include <ctype.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "cvt.h"
/*** / GLOBALS / ***/
crule_t **crules; /* global crule_t * array of size global_numrules */
long global_numrules= 0; /* total #of rules; counted by readcrule() */
int global_maxlhs= 0; /* current maximum length of a lhs in 'crules'.
* This value is updated with each call of
* addcrule() */
/*** / NEW / ***/
crule_t *new(void)
/* allokiert eine neue crule und initialisiert die members */
{ crule_t *rp= (crule_t *)malloc(sizeof(crule_t));
if(rp)
{ rp->next= NIL(crule_t);
rp->lhs= rp->rhs= (char *)0L;
rp->l= rp->r= 0;
rp->ln= 0;
}
return rp;
}
/*** / DISPOSE / ***/
crule_t *dispose(crule_t *rp)
/* gibt eine crule frei und ihren Nachfolger zur"uck */
{ crule_t *succ= rp->next;
if(rp->lhs) { free(rp->lhs); rp->lhs= (char *)0L; rp->l= 0; }
if(rp->rhs) { free(rp->rhs); rp->rhs= (char *)0L; rp->r= 0; }
rp->ln= 0;
free(rp);
return succ;
}
/*** / INIT_RULES / ***/
int init_rules(void)
/* richtet das 'crules' array ein und initialisiert es auf NIL(crule_t).
* Es wird hier nicht "uberpr"uft ob die ANSI Grenze von 64k f"ur
* malloc() "uberschritten wird, was aber auch "au\3erst unwahrscheinlich
* ist. */
{
#ifdef DEBUG
if(debuglevel >= 1)
printf("> init_rules() entered to malloc() %ld bytes of memory\n",
global_numchars * sizeof(crule_t *));
#endif
crules= (crule_t **)malloc(global_numchars * sizeof(crule_t *));
if(crules)
{ long i;
for(i=0; i<global_numchars; i++)
crules[i]= NIL(crule_t);
return 0;
}
else return 1;
}
/*** / EXIT_RULES / ***/
void exit_rules(void)
/* Hier werden alle Eintr"age in 'crules' aufgel"ost und deren Speicher
* freigegeben. Au\3erdem wird 'crules' selbst abgebaut. */
{
#ifdef DEBUG
if(debuglevel >= 1)
printf("> exit_rules() entered to free() %ld rules for %d chars\n",
global_numrules, global_numchars);
#endif
if(crules)
{ long i;
for(i=0; i<global_numchars; i++)
{ crule_t *rp= crules[i];
while(rp) rp= dispose(rp);
crules[i]= NIL(crule_t);
}
free(crules);
}
global_numrules= 0;
}
/*** / ADDCRULE / ***/
int addcrule(crule_t *rp)
/* Hier wird eine crule 'rp' in das globale 'crules' array eingef"ugt.
* Der erste Buchstabe der lhs von 'rp' bestimmt den index in 'crules'.
* Wenn dort schon ein Eintrag ist, wird 'rp' so eingesetzt, da\3 jeder
* Vorg"anger von 'rp' eine l"angere lhs hat und jeder Nachfolger eine
* k"urzere. Bei gleicher L"ange wird nach den ASCII Werten in lhs
* absteigend sortiert, d.h. Vorg"anger haben gr"o\3ere ASCII Werte
* als die Nachfolger.
* Der R"uckgabewert ist 0 wenn alles geklappt hat, 1, wenn die gleiche
* lhs schon vorhanden war und 2, wenn 'rp' oder dessen lhs leer war. */
{ if(rp && rp->lhs)
{ int r= (int)((rp->lhs)[0] & 0377);
crule_t *m= NIL(crule_t), *n= crules[r];
while(n && n->l > rp->l) { m=n; n=n->next; }
if(n && n->l == rp->l)
{ char *s= n->lhs, *t= rp->lhs;
int l= n->l; /* == rp->l */
while(l-- && *s==*t) { ++s; ++t; }
if(l<0) return 1; /* ambiguous! */
else if(*s>*t) m=n;
}
if(m) { rp->next=m->next; m->next=rp; }
else { rp->next= crules[r]; crules[r]= rp; }
if(rp->l > global_maxlhs) global_maxlhs= rp->l;
return 0;
}
return 2;
}
#ifdef DEBUG
/*** / MAXLHS / ***/
int maxlhs(void)
/* Ermittelt den l"angsten linken Kontext in 'crules' */
{ int r, m=0;
for(r=0; r<global_numchars; r++)
{ crule_t *rp= crules[r];
while(rp)
{ if(rp->l > m) m= rp->l;
rp= rp->next;
}
}
return m;
}
/*** / PRINT_CRULE / ***/
void print_crule(crule_t *rp)
{
if(rp->l && rp->lhs)
{ int i,q;
for(i=q=0; i<rp->l; i++)
{ int c= (rp->lhs)[i]&0xFF;
if(isprint(c))
{ if(!q)
{ putchar('\"');
q=1;
}
if(c=='\\' || c=='\"')
putchar('\\');
putchar(c);
}
else /* !isprint(c) */
{ if(q)
{ printf("\",");
q=0;
}
printf("$%02x",c);
}
if(rp->l>i+1 && q==0)
putchar(',');
}
if(q) putchar('\"');
printf("->");
if(rp->r && rp->rhs)
{ for(i=q=0; i<rp->r; i++)
{ int c= (rp->rhs)[i]&0xFF;
if(isprint(c))
{ if(!q)
{ putchar('\"');
q=1;
}
if(c=='\\' || c=='\"')
putchar('\\');
putchar(c);
}
else /* !isprint(c) */
{ if(q)
{ printf("\",");
q=0;
}
printf("$%02x",c);
}
if(rp->r>i+1 && q==0)
putchar(',');
}
if(q) putchar('\"');
}
printf("; // line %d\n",rp->ln);
}
else printf("// empty rule in line %d\n",rp->ln);
}
/*** / DUMP_CRULES / ***/
void dump_crules(void)
/* prints all rules in 'crules' */
{ crule_t *rp;
int r;
printf("/*** / CONVERSION RULES / ***/\n");
for(r=0; r<global_numchars; r++)
{ rp= crules[r];
while(rp)
{ print_crule(rp);
rp= rp->next;
}
}
printf("// %ld rules; maximum lhs is %d\n",global_numrules, maxlhs());
}
#endif /* DEBUG */