15db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
25db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// A utility for finding substring embeddings in patterns
35db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
45db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang#include <stdio.h>
55db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang#include <string.h>
65db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang#include <stdlib.h>
75db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
85db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang#define MAXPATHS (256*1024)
95db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
105db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
115db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
125db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangstatic void die(
135db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  const char*msg
145db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang) {
155db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  fprintf(stderr,"%s\n",msg);
165db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  exit(1);
175db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
185db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
195db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
205db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// Finds the index of an entry, only used on xxx_key arrays
215db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// Caveat: the table has to be sorted
225db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangstatic int find_in(
235db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *tab[],
245db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int max,
255db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  const char *pat
265db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang) {
275db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int left=0, right=max-1;
285db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  while (left <= right) {
295db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    int mid = ((right-left)/2)+left;
305db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    int v   = strcmp(pat,tab[mid]);
315db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    if (v>0) {
325db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      left = mid + 1;
335db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    } else if (v<0) {
345db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      right = mid -1;
355db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    } else {
365db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      return mid;
375db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    }
385db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
395db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  return -1;
405db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
415db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
425db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
435db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// used by partition (which is used by qsort_arr)
445db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
455db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangstatic void swap2(
465db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *a[],
475db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *b[],
485db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int i,
495db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int j
505db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang) {
515db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  if (i==j) return;
525db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char*v;
535db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  v=a[i]; a[i]=a[j]; a[j]=v;
545db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  v=b[i]; b[i]=b[j]; b[j]=v;
555db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
565db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
575db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
585db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// used by qsort_arr
595db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
605db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangstatic int partition(
615db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *a[],
625db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *b[],
635db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int left,
645db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int right,
655db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int p
665db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang) {
675db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  const char *pivotValue = a[p];
685db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int i;
695db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  swap2(a,b,p,right); // Move pivot to end
705db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  p = left;
715db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  for (i=left; i<right; i++) {
725db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    if (strcmp(a[i],pivotValue)<=0) {
735db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      swap2(a,b,p,i);
745db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      p++;
755db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    }
765db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
775db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  swap2(a,b,right,p); // Move pivot to its final place
785db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  return p;
795db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
805db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
815db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
825db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
835db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
845db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangstatic void qsort_arr(
855db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *a[],
865db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *b[],
875db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int left,
885db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int right
895db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang) {
905db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  while (right > left) {
915db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    int p = left + (right-left)/2; //select a pivot
925db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    p = partition(a,b, left, right, p);
935db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    if ((p-1) - left < right - (p+1)) {
945db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      qsort_arr(a,b, left, p-1);
955db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      left  = p+1;
965db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    } else {
975db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      qsort_arr(a,b, p+1, right);
985db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      right = p-1;
995db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    }
1005db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
1015db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
1025db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
1035db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
1045db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// Removes extra '0' entries from the string
1055db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
1065db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangstatic char* compact(
1075db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *expr
1085db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang) {
1095db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int l=strlen(expr);
1105db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int i,j;
1115db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  for (i=0,j=0; i<l; i++) {
1125db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    if (expr[i]!='0') expr[j++] = expr[i];
1135db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
1145db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  expr[j]=0;
1155db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  return expr;
1165db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
1175db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
1185db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
1195db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// convert 'n1im' to 0n1i0m0 expressed as a string
1205db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
1215db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangstatic void expand(
1225db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *expr,
1235db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  const char *pat,
1245db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int l
1255db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang) {
1265db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int  el = 0;
1275db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char last = '.';
1285db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int  i;
1295db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  for (i=0; i<l; i++) {
1305db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    char c = pat[i];
1315db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    if ( (last<'0' || last>'9')
1325db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      && (c   <'0' || c   >'9')
1335db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      ) {
1345db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      expr[el++] = '0';
1355db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    }
1365db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    expr[el++] = c;
1375db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    last = c;
1385db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
1395db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  if (last<'0' || last>'9') expr[el++] = '0';
1405db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  expr[el]=0;
1415db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
1425db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
1435db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
1445db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// Combine two patterns, i.e. .ad4der + a2d becomes .a2d4der
1455db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// The second pattern needs to be a right side match of the first
1465db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang// (modulo digits)
1475db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangstatic char *combine(
1485db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *expr,
1495db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  const char *subexpr
1505db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang) {
1515db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int l1 = strlen(expr);
1525db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int l2 = strlen(subexpr);
1535db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int off = l1-l2;
1545db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int j;
1555db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  // this works also for utf8 sequences because the substring is identical
1565db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  // to the last substring-length bytes of expr except for the (single byte)
1575db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  // hyphenation encoders
1585db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  for (j=0; j<l2; j++) {
1595db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    if (subexpr[j]>expr[off+j]) {
1605db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      expr[off+j] = subexpr[j];
1615db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    }
1625db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
1635db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  return expr;
1645db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
1655db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
1665db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
1675db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
1685db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang//
1695db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wangint main(int argc, const char* argv[]) {
1705db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  FILE *in, *out;
1715db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *pattab_key[MAXPATHS];
1725db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *pattab_val[MAXPATHS];
1735db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int   patterns = 0;
1745db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *newpattab_key[MAXPATHS];
1755db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char *newpattab_val[MAXPATHS];
1765db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int   newpatterns = 0;
1775db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  char format[132]; // 64+65+newline+zero+spare
1785db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  int p;
1795db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  if (argc!=3) die("Usage: <orig-file> <new-file>\n");
1805db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  if ((in = fopen(argv[1],"r"))==NULL) die("Could not read input");
1815db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  if ((out = fopen(argv[2],"w"))==NULL) die("Could not create output");
1825db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  // read all patterns and split in pure text (_key) & expanded patterns (_val)
1835db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  while(fgets(format,132,in)) {
1845db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    int l = strlen(format);
1855db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    if (format[l-1]=='\n') { l--; format[l]=0; } // Chomp
1865db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    if (format[0]=='%' || format[0]==0) {
1875db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      // skip
1885db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    } else {
1895db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      if (format[l-1]=='%') {
1905db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        l--;
1915db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        format[l] = 0; // remove '%'
1925db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      }
1935db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      int i,j;
1945db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      char *pat = (char*) malloc(l+1);
1955db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      char *org = (char*) malloc(l*2+1);
1965db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      expand(org,format,l);
1975db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      // remove hyphenation encoders (digits) from pat
1985db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      for (i=0,j=0; i<l; i++) {
1995db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        // odd, but utf-8 proof
2005db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        char c = format[i];
2015db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        if (c<'0' || c>'9') pat[j++]=c;
2025db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      }
2035db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      pat[j]=0;
2045db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      p = patterns;
2055db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      pattab_key[patterns]   = pat;
2065db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      pattab_val[patterns++] = org;
2075db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      if (patterns>MAXPATHS) die("to many base patterns");
2085db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    }
2095db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
2105db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  fclose(in);
2115db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  // As we use binairy search, make sure it is sorted
2125db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  qsort_arr(pattab_key,pattab_val,0,patterns-1);
2135db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
2145db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  for (p=0; p<patterns; p++) {
2155db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    char *pat = pattab_key[p];
2165db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    int   patsize = strlen(pat);
2175db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    int   j,l;
2185db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    for (l=1; l<=patsize; l++) {
2195db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      for (j=1; j<=l; j++) {
2205db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        int i = l-j;
2215db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        int  subpat_ndx;
2225db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        char subpat[132];
2235db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        strncpy(subpat,pat+i,j); subpat[j]=0;
2245db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        if ((subpat_ndx = find_in(pattab_key,patterns,subpat))>=0) {
2255db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang          int   newpat_ndx;
2265db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang          char *newpat=malloc(l+1);
2275db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      //printf("%s is embedded in %s\n",pattab_val[subpat_ndx],pattab_val[p]);
2285db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang          strncpy(newpat, pat+0,l); newpat[l]=0;
2295db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang          if ((newpat_ndx = find_in(newpattab_key,newpatterns,newpat))<0) {
2305db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang            char *neworg = malloc(132); // TODO: compute exact length
2315db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang            expand(neworg,newpat,l);
2325db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang            newpattab_key[newpatterns]   = newpat;
2335db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang            newpattab_val[newpatterns++] = combine(neworg,pattab_val[subpat_ndx]);
2345db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang            if (newpatterns>MAXPATHS) die("to many new patterns");
2355db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    //printf("%*.*s|%*.*s[%s] (%s|%s) = %s\n",i,i,pat,j,j,pat+i,pat+i+j,pattab_val[p],pattab_val[subpat_ndx],neworg);
2365db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang          } else {
2375db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang            free(newpat);
2385db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang            newpattab_val[newpat_ndx] = combine(
2395db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang              newpattab_val[newpat_ndx], pattab_val[subpat_ndx] );
2405db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang          }
2415db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang        }
2425db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang      }
2435db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    }
2445db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
2455db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
2465db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  /* for some tiny extra speed, one could forget the free()s
2475db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang   * as the memory is freed anyway on exit().
2485db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang   * However, the gain is minimal and now the code can be cleanly
2495db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang   * incorporated into other code */
2505db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  for (p=0; p<newpatterns; p++) {
2515db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    fprintf(out,"%s\n",compact(newpattab_val[p]));
2525db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    free(newpattab_key[p]);
2535db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    free(newpattab_val[p]);
2545db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
2555db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  fclose(out);
2565db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang
2575db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  for (p=0; p<patterns; p++) {
2585db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    free(pattab_key[p]);
2595db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang    free(pattab_val[p]);
2605db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  }
2615db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang  return 0;
2625db78df27806d2eb07c14f86623a906df914b952Shimeng (Simon) Wang}
263