home *** CD-ROM | disk | FTP | other *** search
/ Gold Fish 3 / goldfish_volume_3.bin / files / text / misc / cvt / source / rules.c < prev    next >
C/C++ Source or Header  |  1994-05-28  |  5KB  |  233 lines

  1. /*                                                               -*- C -*-
  2.  *  RULES.C
  3.  *
  4.  *  (c)Copyright 1991-93 by Tobias Ferber,  All Rights Reserved
  5.  */
  6.  
  7. #include <ctype.h>
  8. #include <stdio.h>
  9. #include <stdarg.h>
  10. #include <stdlib.h>
  11.  
  12. #include "cvt.h"
  13.  
  14.  
  15. /*** / GLOBALS / ***/
  16.  
  17. crule_t **crules;           /* global crule_t * array of size global_numrules */
  18.  
  19. long global_numrules= 0;     /* total #of rules; counted by readcrule() */
  20.  
  21. int global_maxlhs= 0;       /* current maximum length of a lhs in 'crules'.
  22.                              * This value is updated with each call of
  23.                              * addcrule() */
  24.  
  25.  
  26. /*** / NEW / ***/
  27.  
  28. crule_t *new(void)
  29. /* allokiert eine neue crule und initialisiert die members */
  30. { crule_t *rp= (crule_t *)malloc(sizeof(crule_t));
  31.   if(rp)
  32.   { rp->next= NIL(crule_t);
  33.     rp->lhs= rp->rhs= (char *)0L;
  34.     rp->l= rp->r= 0;
  35.     rp->ln= 0;
  36.   }
  37.   return rp;
  38. }
  39.  
  40.  
  41. /*** / DISPOSE / ***/
  42.  
  43. crule_t *dispose(crule_t *rp)
  44. /* gibt eine crule frei und ihren Nachfolger zur"uck */
  45. { crule_t *succ= rp->next;
  46.   if(rp->lhs) { free(rp->lhs); rp->lhs= (char *)0L; rp->l= 0; }
  47.   if(rp->rhs) { free(rp->rhs); rp->rhs= (char *)0L; rp->r= 0; }
  48.   rp->ln= 0;
  49.   free(rp);
  50.   return succ;
  51. }
  52.  
  53.  
  54. /*** / INIT_RULES / ***/
  55.  
  56. int init_rules(void)
  57. /* richtet das 'crules' array ein und initialisiert es auf NIL(crule_t).
  58.  * Es wird hier nicht "uberpr"uft ob die ANSI Grenze von 64k f"ur
  59.  * malloc() "uberschritten wird, was aber auch "au\3erst unwahrscheinlich
  60.  * ist. */
  61. {
  62. #ifdef DEBUG
  63.   if(debuglevel >= 1)
  64.     printf("> init_rules() entered to malloc() %ld bytes of memory\n",
  65.       global_numchars * sizeof(crule_t *));
  66. #endif
  67.  
  68.   crules= (crule_t **)malloc(global_numchars * sizeof(crule_t *));
  69.  
  70.   if(crules)
  71.   { long i;
  72.     for(i=0; i<global_numchars; i++)
  73.       crules[i]= NIL(crule_t);
  74.     return 0;
  75.   }
  76.   else return 1;
  77. }
  78.  
  79.  
  80. /*** / EXIT_RULES / ***/
  81.  
  82. void exit_rules(void)
  83. /* Hier werden alle Eintr"age in 'crules' aufgel"ost und deren Speicher
  84.  * freigegeben.  Au\3erdem wird 'crules' selbst abgebaut. */
  85. {
  86. #ifdef DEBUG
  87.   if(debuglevel >= 1)
  88.     printf("> exit_rules() entered to free() %ld rules for %d chars\n",
  89.       global_numrules, global_numchars);
  90. #endif
  91.  
  92.   if(crules)
  93.   { long i;
  94.     for(i=0; i<global_numchars; i++)
  95.     { crule_t *rp= crules[i];
  96.       while(rp) rp= dispose(rp);
  97.       crules[i]= NIL(crule_t);
  98.     }
  99.     free(crules);
  100.   }
  101.   global_numrules= 0;
  102. }
  103.  
  104.  
  105. /*** / ADDCRULE / ***/
  106.  
  107. int addcrule(crule_t *rp)
  108. /* Hier wird eine crule 'rp' in das globale 'crules' array eingef"ugt.
  109.  * Der erste Buchstabe der lhs von 'rp' bestimmt den index in 'crules'.
  110.  * Wenn dort schon ein Eintrag ist, wird 'rp' so eingesetzt, da\3 jeder
  111.  * Vorg"anger von 'rp' eine l"angere lhs hat und jeder Nachfolger eine
  112.  * k"urzere.  Bei gleicher L"ange wird nach den ASCII Werten in lhs
  113.  * absteigend sortiert, d.h. Vorg"anger haben gr"o\3ere ASCII Werte
  114.  * als die Nachfolger.
  115.  * Der R"uckgabewert ist 0 wenn alles geklappt hat, 1, wenn die gleiche
  116.  * lhs schon vorhanden war und 2, wenn 'rp' oder dessen lhs leer war. */
  117. { if(rp && rp->lhs)
  118.   { int r= (int)((rp->lhs)[0] & 0377);
  119.     crule_t *m= NIL(crule_t), *n= crules[r];
  120.     while(n && n->l > rp->l) { m=n; n=n->next; }
  121.     if(n && n->l == rp->l)
  122.     { char *s= n->lhs, *t= rp->lhs;
  123.       int l= n->l; /* == rp->l */   
  124.       while(l-- && *s==*t) { ++s; ++t; }
  125.       if(l<0) return 1; /* ambiguous! */
  126.       else if(*s>*t) m=n;
  127.     }
  128.     if(m) { rp->next=m->next; m->next=rp; }
  129.     else { rp->next= crules[r]; crules[r]= rp; }
  130.     if(rp->l > global_maxlhs) global_maxlhs= rp->l;
  131.     return 0;
  132.   }
  133.   return 2;
  134. }
  135.  
  136.  
  137. #ifdef DEBUG
  138.  
  139. /*** / MAXLHS / ***/
  140.  
  141. int maxlhs(void)
  142. /* Ermittelt den l"angsten linken Kontext in 'crules' */
  143. { int r, m=0;
  144.   for(r=0; r<global_numchars; r++)
  145.   { crule_t *rp= crules[r];
  146.     while(rp)
  147.     { if(rp->l > m) m= rp->l;
  148.       rp= rp->next;
  149.     }
  150.   }
  151.   return m;
  152. }
  153.  
  154.  
  155. /*** / PRINT_CRULE / ***/
  156.  
  157. void print_crule(crule_t *rp)
  158. {
  159.   if(rp->l && rp->lhs)
  160.   { int i,q;
  161.     for(i=q=0; i<rp->l; i++)
  162.     { int c= (rp->lhs)[i]&0xFF;
  163.       if(isprint(c))
  164.       { if(!q)
  165.         { putchar('\"');
  166.           q=1;
  167.         }
  168.         if(c=='\\' || c=='\"')
  169.           putchar('\\');
  170.         putchar(c);
  171.       }
  172.       else /* !isprint(c) */
  173.       { if(q)
  174.         { printf("\",");
  175.           q=0;
  176.         }
  177.         printf("$%02x",c);
  178.       }
  179.       if(rp->l>i+1 && q==0)
  180.         putchar(',');
  181.     }
  182.     if(q) putchar('\"');
  183.     printf("->");
  184.     if(rp->r && rp->rhs)
  185.     { for(i=q=0; i<rp->r; i++)
  186.       { int c= (rp->rhs)[i]&0xFF;
  187.         if(isprint(c))
  188.         { if(!q)
  189.           { putchar('\"');
  190.             q=1;
  191.           }
  192.           if(c=='\\' || c=='\"')
  193.             putchar('\\');
  194.           putchar(c);
  195.  
  196.         }
  197.         else /* !isprint(c) */
  198.         { if(q)
  199.           { printf("\",");
  200.             q=0;
  201.           }
  202.           printf("$%02x",c);
  203.         }
  204.         if(rp->r>i+1 && q==0)
  205.           putchar(',');
  206.       }
  207.       if(q) putchar('\"');
  208.     }
  209.     printf("; // line %d\n",rp->ln);
  210.   }
  211.   else printf("// empty rule in line %d\n",rp->ln);
  212. }
  213.  
  214.  
  215. /*** / DUMP_CRULES / ***/
  216.  
  217. void dump_crules(void)
  218. /* prints all rules in 'crules' */
  219. { crule_t *rp;
  220.   int r;
  221.   printf("/*** / CONVERSION RULES / ***/\n");
  222.   for(r=0; r<global_numchars; r++)
  223.   { rp= crules[r];
  224.     while(rp)
  225.     { print_crule(rp);
  226.       rp= rp->next;
  227.     }
  228.   }
  229.   printf("// %ld rules; maximum lhs is %d\n",global_numrules, maxlhs());
  230. }
  231.  
  232. #endif /* DEBUG */
  233.