#include <stdio.h>
#define deBUG 0

main(unsigned int num_arg, char * arg[])
 {unsigned char reply[20], c[256], file_in[40], file_out[40];
  int i, choice;
  FILE *fin = NULL, *fout;
  void elim_punctuation(unsigned char *);
  void elim_finals(unsigned char *); 
  void elim_dagesh(unsigned char *);
  void elim_vowels(unsigned char *);
  void elim_traup(unsigned char *);
  void notarikon(unsigned char *, FILE *, FILE *);
  void substitute(unsigned char *,FILE *,FILE *);
  void pronounce(int, FILE *, FILE *, char *);
  void gematria(FILE *, FILE *);
  void copy_icon(char *, char *);

  if (num_arg < 4)
   {printf("Please make certain that the window is at least 620 pixels wide\n");
    printf("and 200 pixels high.  Hit enter when ready.");
    getchar();}

    if (num_arg < 1) printf("\n\n\nSubstitute v2.1       by Simcha Kuritzky\n\n");
    else printf("\n\n\n%s v2.1       by Simcha Kuritzky\n\n",arg[0]);

  if (num_arg < 4)
   {printf("This program reads in an ASCII file of the Masoretic (Hebrew) Bible,\n");
    printf("and outputs an ASCII file of  the same with certain letters filtered\n");
    printf("out or substituted  (e.g.,  it can eliminate vowels,  dageshes,  and\n");
    printf("traup, and convert finals to medials).   This can be useful for text\n");
    printf("searches.   It can also be used to substitute phonemes,  so that you\n");
    printf("can  hear  the Bible read  aloud.   The Bible Reader program assumes\n");
    printf("these files end with the extention '.sound'.\n\n");
    if ((num_arg > 1) && (arg[1][0] == '?'))
      printf("Expert mode is SUBSTITUTE input_file output_file choice.\n\n");
    printf("Do you wish to continue (y/n)? ");
    scanf(" %s",reply);
    reply[0] = toupper(reply[0]); if (reply[0] == 'N') goto end_section;}

  if (num_arg > 1)
   {strcpy(file_in,arg[1]); fin = fopen(file_in,"r");
    printf("\nInput file: %s\n",file_in);}
  while (fin == NULL)
   {printf("\nWhat is the full path and name of the input file?\n");
    scanf(" %s",file_in);
    if ((fin = fopen(file_in,"r")) == NULL) printf("File not found.\n");}
  strcpy(file_out,file_in);
  strncat(file_out,".new",5);
  if (num_arg > 2) strcpy(file_out,arg[2]);
  else 
   {printf("The output file will be \"%s\"\n",file_out);
    printf("Is this acceptable (Y/N)? \n");
    scanf(" %s",reply);
    reply[0] = toupper(reply[0]);
    if (reply[0] == 'N')
     {printf("What is the full path and name of the output file?\n");
      printf("(end with + to append) ");
      scanf(" %s",file_out);}}
  if (file_out[strlen(file_out)-1] == '+')
   {file_out[strlen(file_out)-1] = '\0'; fout = fopen(file_out,"a");}
  else fout = fopen(file_out,"w");
  for (i = 1; i < 256; i++) c[i] = i;


  choice = 0;  if (num_arg > 3) sscanf(arg[3],"%d",&choice);
  while ((choice < 1) || (choice > 9))
   {printf("\n\n\nWhat should the output file include?\n\n");
    printf("[1]  Consonants and vowels only (filter out traup)\n");
    printf("[2]  Consonants only (no vowels or traup)\n");
    printf("[3]  Israeli Hebrew (no dagesh, vowels, or traup)\n");
    printf("[4]  Standard form consonants only (no finals, dagesh, vowels OR traup)\n");
    printf("[5]  Substitute phonemes using the Sephardi (Israeli) pronunciation\n");
    printf("[6]  Substitute phonemes using the Ashkenazi (European) pronunciation\n");
    printf("[7]  Gematria (add line with numeric values below the Hebrew line\n");
    printf("[8]  Notarikon (add line with initial & final letters at end of each verse)\n");
    printf("[9]  End this program now\n");
    printf("\nWhich do you wish? \n"); scanf("%d",&choice);}

  switch (choice)
   {case 8:  elim_punctuation(c);
    case 4:  elim_finals(c); 
    case 3:  elim_dagesh(c);
    case 2:  elim_vowels(c);
    case 1:  elim_traup(c);
             if (choice == 8) notarikon(c, fin, fout); 
             else substitute(c, fin, fout); break;
    case 5:
    case 6:  if (num_arg > 4) pronounce(choice, fin, fout, arg[4]); 
             else pronounce(choice, fin, fout, ""); break;
    case 7:  gematria(fin, fout); break;}

  end_section:
  fclose(fin);
  fclose(fout);
  copy_icon(file_in,file_out);
  printf("\nFinished.\n");
  exit(20);}

void copy_icon(char *file_in, char *file_out)
 {char icon_in[50], icon_out[50];
  int temp;
  FILE *iin,*iout;
  strcpy(icon_in,file_in); strcat(icon_in,".info");
  if ((iin = fopen(icon_in,"r")) == NULL) 
    printf("Info file not found.  Will not create icon for new file.\n");
  else
   {strcpy(icon_out,file_out); strcat(icon_out,".info");
    if ((iout = fopen(icon_out,"w")) == NULL) 
      printf("Info file not opened.  Will not create icon for new file.\n");
    else
     {while ((temp = fgetc(iin)) != EOF) fputc(temp,iout);
      fclose(iin); fclose(iout);}}
  return;}

void elim_punctuation(unsigned char *c)
 {int i;
  for (i = 0; i <= 38; i++) *(c+i) = 0;
  for (i = 40; i <= 43; i++) *(c+i) = 0;
  for (i = 45; i <= 64; i++) *(c+i) = 0;
  for (i = 92; i <= 96; i++) *(c+i) = 0;
  for (i = 124; i <= 159; i++) *(c+i) = 0;
  for (i = 176; i <= 185; i++) *(c+i) = 0;
  *(c+84) = *(c+116); *(c+71) = 0;
  return;}

void elim_finals(unsigned char *c)
 {*(c+46) = *(c+109);  *(c+59) = *(c+112);  *(c+105) = *(c+98);
  *(c+108) = *(c+102); *(c+111) = *(c+110);
  return;}

void elim_dagesh(unsigned char *c)
 {int i;
  for (i = 65; i <= 90; i++) if (*(c+i) == i) *(c+i) = *(c+i+32);
  *(c+58) = *(c+59);   *(c+60) = *(c+44);   *(c+79) = *(c+117);
  *(c+81) = *(c+97);   *(c+87) = *(c+97);   *(c+113) = *(c+97);
  *(c+119) = *(c+97);  *(c+91) = *(c+108);  *(c+123) = *(c+108);
  return;}

void elim_vowels(unsigned char *c)
 {int i;
  for (i = 161; i <= 175; i++) *(c+i) = 0;
  for (i = 186; i <= 255; i++) *(c+i) = 0;
  *(c+74) = *(c+106);  *(c+91) = *(c+108);  *(c+123) = *(c+108);
  *(c+73) = *(c+105);
  return;}

void elim_traup(unsigned char *c)
 {int i;
  for (i = 161; i <= 175; i++) *(c+i) = 0;
  for (i = 186; i <= 192; i++) *(c+i) = 0;
  for (i = 199; i <= 208; i++) *(c+i) = 0;
  for (i = 219; i <= 224; i++) *(c+i) = 0;
  for (i = 231; i <= 240; i++) *(c+i) = 0;
  for (i = 251; i <= 255; i++) *(c+i) = 0;
  *(c+194) = 0; *(c+213) = 0; *(c+214) = 0; *(c+217) = 0;
  *(c+245) = 0; *(c+246) = 0; *(c+249) = 0;
  return;}

/*This routine is the heart of the program.  Keep reading characters until
  there are no more, and print the equivalent character from the array.*/
void substitute(unsigned char *c,FILE *fin,FILE *fout)
 {int i = 0;
  int a; unsigned char b;
  *(c+226) = 226;
  printf("Currently at line %d\13\n",i);
  while ((a = fgetc(fin)) != EOF)
   {b = *(c+a);
    if (a == 10) printf("Currently at line %d\13\n",++i);
    if (b) fputc(b,fout);}
  return;}

int L2R(unsigned char c)
 {if (c == 96) return 1;
  if ((c >= 129) && (c <= 154)) return 1;
  if ((c >= 176) && (c <= 185)) return 1;
  return 0;}

int ignore(unsigned char c)
 {int L2R(unsigned char);
  if (L2R(c)) return 1;
  if ((c == 226) || (c == 32) || (c == 9) || (c == 10) || (c == 13)) return 1;
  if ((c >= '0') && (c <= '9')) return 1;
  return 0;}

int ending(unsigned char c)
 {if ((c == '=') || (c == 32) || (c == '?') || (c == 10) || (c == 13)) return 1;
  return 0;}

int blank(unsigned char c)
 {if ((c == 32) || (c == '?') || (c == 10) || (c == 13)) return 1;
  return 0;}

void pronounce(int choice, FILE *fin, FILE *fout, char *rep)
 {unsigned char reply[20], ch = ' ', nxt, outc[9], prev = ' ', outtemp[9] = "V", last[9],
    *c[256] = {"","","","","","","","","","", "","","","","","","","","","", 
      "","","","","","","","","","", "","",", ","","","","","","","AASHEHM",
      "","","","","S","","TS",".","","", "","","","","","","","","P","F",
      "T",", ",",",".","?","SHSH","NN","B","GG","K", "K","","YY","NAO3","AA4/C",
      "LL","K","TSTS","MM","OW3", "P","SS","RR","DD","EH3L","UW3","/H","SHSH","SS","TT",
      "ZZ","/C","OW3","","","","","SH","N","V", "G","K","/C","Q","Y",
      "N","/C","L","/C","TS", "M","M","F","S","R","D","","V","/H","SH",
      "S","T","Z","/CAO3","","","","","","", "","","","","","","","","","", 
      "","","","","","","","","","", "","","","","","","","","","", 
      "","","","","","","","","","", "","","","","","","","","","", 
      "","","","","","","","","","", "","","","AO3","","UW3","AA3","EH3","AA","EH3",
      "AY3","","","","","","","","","OW3", "EH","AO","EY3","","","OW3","QX","","IY3","",
      "","","","","","AO3","","UW3","AA3","EH3", "AA","EH3","EY3","","","LY","","","","",
      "","OW3","EH","AO","EY3","","","OW3","QX","", "IY3","","","","",""};
  const unsigned char holem_vov='O', melupn_vov='U', heh='v', aleph = 't';
  const int vowel = 1, consonant = 2;
  int previous = 0, newline = 1, segol = 0, temp;
  long li = 1;
  int ending(unsigned char);
  int ignore(unsigned char c);

  if (*rep > NULL) reply[0] = toupper(rep[0]); 
  else
   {printf("When the Amiga reads aloud,  it leaves a very short pause between\n");
    printf("words.  If you are not fluent in Hebrew,  it is difficult to tell\n");
    printf("where one word ends and the next begins.  However, the Amiga will\n");
    printf("pause if commas are placed after each word.   Do  you want commas\n");
    printf("placed after each word? ");
    scanf(" %s",reply); reply[0] = toupper(reply[0]);}

  if (reply[0] == 'N') {strcpy(c[32]," "); strcpy(c[61]," ");}
  if (choice == 5) 
   {strcpy(c[44],"T"); strcpy(c[79],"AO3"); strcpy(c[92],"AO3"); strcpy(c[73],"NAA3");
    strcpy(c[123],"/CAA3"); strcpy(c[193],"AA3"); strcpy(c[209],"AO3");
    strcpy(c[211],"AA"); strcpy(c[212],"EH3"); strcpy(c[225],"AA3"); strcpy(c[241],"AO3");
    strcpy(c[243],"AA"); strcpy(c[244],"EH3");}

  while ((ignore(ch) > 0) && ((temp = fgetc(fin)) != EOF)) ch = (unsigned char) temp;
  if (temp != EOF) if ((temp = fgetc(fin)) != EOF) nxt = (unsigned char) temp;

  while (temp != EOF)
   {strcpy(outc,c[ch]);
    if ((blank(prev) > 0) && (blank(nxt) > 0)) strcpy(outc,"");
    if ((blank(ch) > 0) && (newline == 1)) strcpy(outc,"");
    {if ((ch == holem_vov) && (previous == vowel)) 
      {strcat(outtemp,outc); strcpy(outc,outtemp); strcpy(outtemp,"V");}
     if ((ch == melupn_vov) && (previous == vowel)) strcpy(outc,"V");
     if ((ch == heh) && (ending(nxt) > 0))
       {strcpy(outc,""); previous = consonant; segol = 0;}
     if ((outc[0] == 'Y') && (segol == 1))
       {strcpy(outc,""); previous = consonant; segol = 0;}
     if (strlen(outc) > 0) 
      {if ((outc[0] > 64) || (outc[0] == 47)) previous = consonant;}
     else if (ch == aleph) previous = consonant;
     if (((ch == holem_vov) || (ch > 160)) && (strlen(outc) > 0)) previous = vowel;
     if (strlen(outc) > 0) segol = 0;
     if ((ch == 197) || (ch == 229)) segol = 1;}
    if (isdigit(ch) > 0)
     {printf("Currently on verse %ld\13\n",++li);
      while ((isdigit(nxt) > 0) && ((temp = fgetc(fin)) != EOF)) 
        nxt = (unsigned char) temp;  
      outc[0] = 10; outc[1] = 0;}

    if (strlen(outc) > 0)
     {if ((outc[strlen(outc)-1] == ' ') || (outc[0] == '.'))
       {if ((last[0] != '.') && (last[strlen(last)-1] != ' ') && (last[0] != 10)) 
         {fprintf(fout,"%s",outc);
          newline = 0; if (outc[0] == 10) newline = 1;}
        else
          if (newline == 0) fputc(' ',fout);}
      else
       {fprintf(fout,"%s",outc); 
        newline = 0; if (outc[0] == 10) newline = 1;}
      strcpy(last,outc);}
    prev = ch; ch = nxt; 
    if (temp != EOF) if ((temp = fgetc(fin)) != EOF)
      nxt = (unsigned char) temp;}
  return;}


void gematria(FILE *fin, FILE *fout) 
 {const char char_len = 14;
  int i,j,sp,
    numeral[256] = {0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,21, 0,0,0,0,400,0,90,0,0,0,
    0,0,0,0,0,0,0,0,80,80, 400,0,0,0,0,300,50,2,3,100, 20,0,10,50,8,30,20,90,40,6, 
    80,300,200,4,31,6,5,300,60,9, 7,20,0,0,0,0,0,300,50,2,
    3,100,20,70,10,50,8,30,20,90, 40,40,80,300,200,4,1,6,5,300,
    60,9,7,20,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0};

  char width[256] = {0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0, 0,0,14,0,0,0,0,0,0,9, 14,14,0,0,14,0,14,9,12,10,
    14,14,13,14,14,14,14,14,14,14, 14,14,9,14,14,14,9,14,9,14, 
    14,0,9,14,14,14,14,14,14,9,    14,14,14,14,14,9,14,14,14,14, 
    9,14,0,0,0,0,0,14,9,14,       9,14,14,14,9,9,14,14,14,14, 
    14,14,14,14,14,14,14,9,14,14,  14,14,9,14,0,0,0,0,0,0, 
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,
    0,0,0,0,0,0};

  int verse = 0, word_val = 0, tlen = 0, num_len = 0, v = 1;
  unsigned char num[200], st[10]="", txt[200], c, l, word[30]="", n[200];
  int L2R(unsigned char), blank(unsigned char);
  printf("Currently on verse 0\13\n");

/*	txt = input line
	st = start up string (either 1 char tab or string of #226)
	num = numeric text string built by program (initialized to st)
	c = current char of txt
	tlen = width of text string (incremented word by word)
	word_val = numeric value of current word
	verse = numeric value of current verse
	n = string equivalent of word_val
	l = current digit of n
	num_lken = width of num
	sp = difference between lengths of text & numeric strings in char_lens
	word = text version of current word which only includes letters
	v = number of verses printed */

  while (fgets(txt,199,fin) != NULL)
   {fprintf(fout,"%s",txt); 
    if (L2R(txt[0]) == 0)
     {if (st[0] == '\0') /* if startup string is empty, initialize it */
       {st[0] = txt[0]; st[1] = '\0'; i = 1; 
        while (txt[i] == 226) strncat(st,&txt[i++],1);
        strncat(st," ",1); strcpy(num,st);}
      for (i = 0; i < strlen(txt); i++)
       {c = txt[i]; 
        if ((c == ' ') || (c == '=') || (c == '?')) /* end of word */
         {tlen += width[c];
          if (strstr(word,"tkeh") != NULL) word_val -= 95; /* Elokim */
          /* ignore single letters in text */
          if ((i > 1) && (blank(txt[i-2]) > 0)) {word_val = 0; strcpy(word,"");}
          verse += word_val; 
          if (word_val > 0) /* reverse word_val and append to num */
           {sprintf(n,"%d",word_val); word_val = 0; strcpy(word,"");
            for (j = strlen(n)-1; j >= 0; j--)
             {l = n[j]; strncat(num,&l,1); 
              num_len += width[l];}} /* add spaces to even up text */
          sp = (tlen - num_len)/char_len;
          if (sp > 0) num_len += sp * char_len;  
          do {strncat(num," ",1); sp--;} while (sp > 0);}
        else /* middle of word */
         {if (isdigit(c) > 0) word_val = 0; /* new verses start with digits */ 
          word_val += numeral[c]; tlen += width[c]; 
          if (numeral[c] > 0) strncat(word,&c,1);}} /* end of input line */
      tlen = 0; num_len = 0;
      if (strchr(txt,'?') != NULL) /* end of verse */
       {sprintf(n," %d",verse); strncat(n,"? ",2);
        for (i = strlen(n)-1; i >= 0; i--) strncat(num,&n[i],1);
        verse = 0; printf("Currently at verse %d\13\n",v++);}
      fprintf(fout,"%s\n",num); strcpy(num,st);}}
  return;}

void notarikon(unsigned char *c, FILE *fin, FILE *fout)
 {int i, v = 1;
  unsigned char st[10]="", txt[200], ch, word[30]="", begin[50]="", end[50]="";
  int L2R(unsigned char), blank(unsigned char), paren = 0, count = 0;
  printf("Currently on verse 0\13\n");

/*	txt = input line
	st = start up string (either 1 char tab or string of #226)
	end = text string of final letters built by program
	begin = text string of initial letters built by program
	ch = current char of txt
	word = text version of current word which only includes letters
	v = number of verses printed */

  while (fgets(txt,199,fin) != NULL)
   {fprintf(fout,"%s",txt); 
    if (L2R(txt[0]) == 0)
     {if (st[0] == '\0') /* if startup string is empty, initialize it */
       {st[0] = txt[0]; st[1] = '\0'; i = 1; 
        while (txt[i] == 226) strncat(st,&txt[i++],1); strncat(st," ",1);}
      for (i = 0; i < strlen(txt); i++)
       {ch = txt[i];
        if ((paren) && (ch == '(')) 
         {paren--; 
          if (!paren)
           {if (count > 99)
             printf("Warning!  %d letters inside of parentheses.\n",count);
            count=0;}}
        if ((!paren) && (ch == ')')) {ch = ' '; paren++;}
        if ((ch == ' ') || (ch == '=') || (ch == '?')) /* end of word */
         {if (strchr(word,'\'') != NULL) /* Hashem */
           {if (strcmp(word,"v'")) strncat(word,"v",1); else strcpy(word,"hv\0");}
          if (strlen(word) == 1) strcpy(word,"");
          if (strlen(word) > 0)
           {strncat(begin,word,1); strncat(end,word+strlen(word)-1,1); strcpy(word,"");}}
        else
          if (!paren) strncat(word,c+ch,1); else count++;}
      if (strchr(txt,'?') != NULL) /* end of verse */
       {printf("Currently at verse %d\13\n",v++);
        if (strlen(begin) > 15) fprintf(fout,"%s%s\n%s%s\n",st,begin,st,end);
        else fprintf(fout,"%s%s %s\n",st,begin,end);
        strcpy(begin,""); strcpy(end,"");}}}
    if (count > 0)
      printf("Warning!  Mismatched parentheses masked %d letters.\n",count);
    return;}

