/usr.bin/lex/ecs.c

https://bitbucket.org/freebsd/freebsd-head/ · C · 227 lines · 101 code · 46 blank · 80 comment · 35 complexity · 53299ed6472878c14ec1ee56f73754ec MD5 · raw file

  1. /* ecs - equivalence class routines */
  2. /*-
  3. * Copyright (c) 1990 The Regents of the University of California.
  4. * All rights reserved.
  5. *
  6. * This code is derived from software contributed to Berkeley by
  7. * Vern Paxson.
  8. *
  9. * The United States Government has rights in this work pursuant
  10. * to contract no. DE-AC03-76SF00098 between the United States
  11. * Department of Energy and the University of California.
  12. *
  13. * Redistribution and use in source and binary forms are permitted provided
  14. * that: (1) source distributions retain this entire copyright notice and
  15. * comment, and (2) distributions including binaries display the following
  16. * acknowledgement: ``This product includes software developed by the
  17. * University of California, Berkeley and its contributors'' in the
  18. * documentation or other materials provided with the distribution and in
  19. * all advertising materials mentioning features or use of this software.
  20. * Neither the name of the University nor the names of its contributors may
  21. * be used to endorse or promote products derived from this software without
  22. * specific prior written permission.
  23. * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
  24. * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
  25. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
  26. */
  27. /* $Header: /home/daffy/u0/vern/flex/RCS/ecs.c,v 2.9 93/12/07 10:18:20 vern Exp $ */
  28. #include <sys/cdefs.h>
  29. __FBSDID("$FreeBSD$");
  30. #include "flexdef.h"
  31. /* ccl2ecl - convert character classes to set of equivalence classes */
  32. void ccl2ecl()
  33. {
  34. int i, ich, newlen, cclp, ccls, cclmec;
  35. for ( i = 1; i <= lastccl; ++i )
  36. {
  37. /* We loop through each character class, and for each character
  38. * in the class, add the character's equivalence class to the
  39. * new "character" class we are creating. Thus when we are all
  40. * done, character classes will really consist of collections
  41. * of equivalence classes
  42. */
  43. newlen = 0;
  44. cclp = cclmap[i];
  45. for ( ccls = 0; ccls < ccllen[i]; ++ccls )
  46. {
  47. ich = ccltbl[cclp + ccls];
  48. cclmec = ecgroup[ich];
  49. if ( cclmec > 0 )
  50. {
  51. ccltbl[cclp + newlen] = cclmec;
  52. ++newlen;
  53. }
  54. }
  55. ccllen[i] = newlen;
  56. }
  57. }
  58. /* cre8ecs - associate equivalence class numbers with class members
  59. *
  60. * fwd is the forward linked-list of equivalence class members. bck
  61. * is the backward linked-list, and num is the number of class members.
  62. *
  63. * Returned is the number of classes.
  64. */
  65. int cre8ecs( fwd, bck, num )
  66. int fwd[], bck[], num;
  67. {
  68. int i, j, numcl;
  69. numcl = 0;
  70. /* Create equivalence class numbers. From now on, ABS( bck(x) )
  71. * is the equivalence class number for object x. If bck(x)
  72. * is positive, then x is the representative of its equivalence
  73. * class.
  74. */
  75. for ( i = 1; i <= num; ++i )
  76. if ( bck[i] == NIL )
  77. {
  78. bck[i] = ++numcl;
  79. for ( j = fwd[i]; j != NIL; j = fwd[j] )
  80. bck[j] = -numcl;
  81. }
  82. return numcl;
  83. }
  84. /* mkeccl - update equivalence classes based on character class xtions
  85. *
  86. * synopsis
  87. * Char ccls[];
  88. * int lenccl, fwd[llsiz], bck[llsiz], llsiz, NUL_mapping;
  89. * void mkeccl( Char ccls[], int lenccl, int fwd[llsiz], int bck[llsiz],
  90. * int llsiz, int NUL_mapping );
  91. *
  92. * ccls contains the elements of the character class, lenccl is the
  93. * number of elements in the ccl, fwd is the forward link-list of equivalent
  94. * characters, bck is the backward link-list, and llsiz size of the link-list.
  95. *
  96. * NUL_mapping is the value which NUL (0) should be mapped to.
  97. */
  98. void mkeccl( ccls, lenccl, fwd, bck, llsiz, NUL_mapping )
  99. Char ccls[];
  100. int lenccl, fwd[], bck[], llsiz, NUL_mapping;
  101. {
  102. int cclp, oldec, newec;
  103. int cclm, i, j;
  104. static unsigned char cclflags[CSIZE]; /* initialized to all '\0' */
  105. /* Note that it doesn't matter whether or not the character class is
  106. * negated. The same results will be obtained in either case.
  107. */
  108. cclp = 0;
  109. while ( cclp < lenccl )
  110. {
  111. cclm = ccls[cclp];
  112. if ( NUL_mapping && cclm == 0 )
  113. cclm = NUL_mapping;
  114. oldec = bck[cclm];
  115. newec = cclm;
  116. j = cclp + 1;
  117. for ( i = fwd[cclm]; i != NIL && i <= llsiz; i = fwd[i] )
  118. { /* look for the symbol in the character class */
  119. for ( ; j < lenccl; ++j )
  120. {
  121. int ccl_char;
  122. if ( NUL_mapping && ccls[j] == 0 )
  123. ccl_char = NUL_mapping;
  124. else
  125. ccl_char = ccls[j];
  126. if ( ccl_char > i )
  127. break;
  128. if ( ccl_char == i && ! cclflags[j] )
  129. {
  130. /* We found an old companion of cclm
  131. * in the ccl. Link it into the new
  132. * equivalence class and flag it as
  133. * having been processed.
  134. */
  135. bck[i] = newec;
  136. fwd[newec] = i;
  137. newec = i;
  138. /* Set flag so we don't reprocess. */
  139. cclflags[j] = 1;
  140. /* Get next equivalence class member. */
  141. /* continue 2 */
  142. goto next_pt;
  143. }
  144. }
  145. /* Symbol isn't in character class. Put it in the old
  146. * equivalence class.
  147. */
  148. bck[i] = oldec;
  149. if ( oldec != NIL )
  150. fwd[oldec] = i;
  151. oldec = i;
  152. next_pt: ;
  153. }
  154. if ( bck[cclm] != NIL || oldec != bck[cclm] )
  155. {
  156. bck[cclm] = NIL;
  157. fwd[oldec] = NIL;
  158. }
  159. fwd[newec] = NIL;
  160. /* Find next ccl member to process. */
  161. for ( ++cclp; cclflags[cclp] && cclp < lenccl; ++cclp )
  162. {
  163. /* Reset "doesn't need processing" flag. */
  164. cclflags[cclp] = 0;
  165. }
  166. }
  167. }
  168. /* mkechar - create equivalence class for single character */
  169. void mkechar( tch, fwd, bck )
  170. int tch, fwd[], bck[];
  171. {
  172. /* If until now the character has been a proper subset of
  173. * an equivalence class, break it away to create a new ec
  174. */
  175. if ( fwd[tch] != NIL )
  176. bck[fwd[tch]] = bck[tch];
  177. if ( bck[tch] != NIL )
  178. fwd[bck[tch]] = fwd[tch];
  179. fwd[tch] = NIL;
  180. bck[tch] = NIL;
  181. }