int ChampParseAtomBlock()

in contrib/champ/champ.c [2867:3574]


int ChampParseAtomBlock(CChamp *I,char **c_ptr,int cur_atom) 
{
  int ok = true;
  ListAtom *at;
  char *c;
  int not_flag = false;
  int num;
  int done=false;
  int atom_seen = false;

  /*  int done;*/

  c=*c_ptr;

  at=I->Atom+cur_atom;

  at->comp_imp_hydro_flag = false;
  
  while(ok&&!done) {
    switch(*c) {
    case ']':
      done=true;
      c++;
      break;
    case 0:
      done=true;
      break;
    case '!':
      c++;
      not_flag=true;
      atom_seen = false;
      break;
    case ',':
      c++;
      atom_seen = false;
      break;
    case ';':
      not_flag=false;
      c++;
      atom_seen = false;
      break;
    case '*': /* nonstandard */
      c = ChampParseBlockAtom(I,c,cur_atom,cH_Any,1,not_flag);
      atom_seen = true;
      break;
    case '?': /* nonstandard */
      c = ChampParseBlockAtom(I,c,cur_atom,cH_NotH,1,not_flag);
      atom_seen = true;
      break;
    case '@':
      num = ChampParseNumeral(c+1);
      if(num>=0) {
        c+=2;
      } else {
        num = 1;
        c++;
        while(*c) {
          if(*c!='@')
            break;
          else {
            num++;
            c++;
          }
        }
      }
      if(num&0x1) /* odd */
        I->Atom[cur_atom].stereo = cH_Anticlock;
      else
        I->Atom[cur_atom].stereo = cH_Clockwise;
      break;
    case 'A': /* note there is no way to address the 'A' symbol ...*/
      switch(*(c+1)) {
      case 'c':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'g':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'l':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'm':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 's':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'u':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        if(not_flag) {
          I->Atom[cur_atom].neg_flag=true;
          I->Atom[cur_atom].not_class|=cH_Aliphatic;      
        } else {
          I->Atom[cur_atom].pos_flag=true;
          I->Atom[cur_atom].class|=cH_Aliphatic;
        }
        c++;
      }
      break;
    case 'a':
      if(not_flag) {
        I->Atom[cur_atom].neg_flag=true;
        I->Atom[cur_atom].not_class|=cH_Aromatic;
      } else {
        I->Atom[cur_atom].class|=cH_Aromatic;
        I->Atom[cur_atom].pos_flag=true;
      }
      c++;    
      break;
    case 'B':
      switch(*(c+1)) {
      case 'a':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'e':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'i':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'r':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Br,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_B,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'C':
      switch(*(c+1)) {
      case 'a':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Ca,2,not_flag);
        atom_seen = true;
        break;
      case 'd':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'e':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'o':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'r':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 's':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'u':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Cu,2,not_flag);
        atom_seen = true;
        break;
      case 'l':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Cl,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_C,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'D':
      switch(*(c+1)) {
        case 'y':
          c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
          atom_seen = true;
          break;
      default:
        num = ChampParseNumeral(c+1);
        if(num>=0) {
          if(not_flag) {
            I->Atom[cur_atom].neg_flag=true;
            I->Atom[cur_atom].not_degree|=num_to_degree[num];
          } else {
            I->Atom[cur_atom].pos_flag=true;
            I->Atom[cur_atom].degree|=num_to_degree[num];
          }
          c+=2;
        } else
          ok=false;
        break;
      }
      break;
    case 'E':
      switch(*(c+1)) {
      case 'r':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'u':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_E,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'F':
      switch(*(c+1)) {
      case 'e':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Fe,2,not_flag);
        atom_seen = true;
        break;
      case 'r':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_F,1,not_flag);
        atom_seen = true;
        break;
      }
      break;      
    case 'G':
      switch(*(c+1)) {
      case 'a':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'd':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'e':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'H': 
      switch(*(c+1)) {
      case 'e':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'f':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'g':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'o':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        if(!atom_seen) {
          c = ChampParseBlockAtom(I,c,cur_atom,cH_H,1,not_flag);
          atom_seen = true;
        } else {
          num = ChampParseNumeral(c+1);
          if(num>=0) {
            c+=2;
          } else {
            num = 1;
            c++;
            while(*c) {
              if(*c!='H')
                break;
              else {
                num++;
                c++;
              }
            }
          }
          I->Atom[cur_atom].imp_hydro = num;
          I->Atom[cur_atom].tot_hydro = num;
          I->Atom[cur_atom].hydro_flag = true; 
          /* turn on hydrogen count matching for this atom */
          
        }
        break;
      }
      break;
    case 'I':
      switch(*(c+1)) {
      case 'n':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'r':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_I,1,not_flag);
        atom_seen = true;
        break;
      }
      break;      
    case 'J':
      c = ChampParseBlockAtom(I,c,cur_atom,cH_J,1,not_flag);
        atom_seen = true;
      break;
    case 'K':
      c = ChampParseBlockAtom(I,c,cur_atom,cH_K,1,not_flag);
        atom_seen = true;
      break;      
    case 'L':
      switch(*(c+1)) {
      case 'a':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'i':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'u':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_L,1,not_flag);
        atom_seen = true;
      }
      break;      
    case 'M':
      switch(*(c+1)) {
      case 'n':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'o':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'g':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Mg,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_M,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'N':
      switch(*(c+1)) {
      case 'a':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Na,2,not_flag);      
        atom_seen = true;
        break;
      case 'b':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      case 'd':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      case 'i':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_N,1,not_flag);
        atom_seen = true;
        break;
      }
      break;      
    case 'O':
      switch(*(c+1)) {
      case 's':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_O,1,not_flag);
        atom_seen = true;
        break;
      }
      break;      
    case 'P':
      switch(*(c+1)) {
      case 'b':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      case 'd':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      case 'o':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      case 'r':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      case 't':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);      
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_P,1,not_flag);
        atom_seen = true;
      }
      break;      
    case 'p': /* Pi system */
      if(not_flag) {
        I->Atom[cur_atom].neg_flag=true;
        I->Atom[cur_atom].not_class|=cH_Pi;
      } else {
        I->Atom[cur_atom].pos_flag=true;
        I->Atom[cur_atom].class|=cH_Pi;
      }
      c++;
      break;      
    case 'R':
      switch(*(c+1)) {
      case 'b':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'e':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'h':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'u':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_R,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'r':
      num = ChampParseNumeral(c+1);
      if(num>=0) {
        if(not_flag) {
          I->Atom[cur_atom].neg_flag=true;
          I->Atom[cur_atom].not_cycle|=num_to_ring[num];
        } else {
          I->Atom[cur_atom].pos_flag=true;
          I->Atom[cur_atom].cycle|=num_to_ring[num];
        }
        c+=2;
      } else {
        if(not_flag) {
          I->Atom[cur_atom].neg_flag=true;
          I->Atom[cur_atom].not_cycle|=cH_Ring3|cH_Ring4|cH_Ring5|cH_Ring6|cH_Ring7|cH_Ring8;
        } else {
          I->Atom[cur_atom].pos_flag=true;
          I->Atom[cur_atom].cycle|=cH_Ring3|cH_Ring4|cH_Ring5|cH_Ring6|cH_Ring7|cH_Ring8;
        }
        c++;
      }
      break;
    case 'Q':
      c = ChampParseBlockAtom(I,c,cur_atom,cH_Q,1,not_flag);
        atom_seen = true;
      break;      
    case 'S':
      switch(*(c+1)) {
      case 'b':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'c':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'e':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Se,2,not_flag);
        atom_seen = true;
        break;
      case 'i':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'm':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'n':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'r':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_S,1,not_flag);
        atom_seen = true;
        break;
      }
      break;      
    case 'T':
      switch(*(c+1)) {
      case 'a':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'b':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'e':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'i':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'h':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'l':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'm':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_T,1,not_flag);
        atom_seen = true;
      }
      break;    
    case 'V':
      switch(*(c+1)) {
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,1,not_flag);
        atom_seen = true;
      }
      break;    
    case 'v':
      num = ChampParseNumeral(c+1);
      if(num>=0) {
        if(not_flag) {
          I->Atom[cur_atom].neg_flag=true;
          I->Atom[cur_atom].not_valence|=num_to_valence[num];
        } else {
          I->Atom[cur_atom].pos_flag=true;
          I->Atom[cur_atom].degree|=num_to_valence[num];
        }
        c+=2;
      } else 
        ok=false;
      break;
    case 'W':
      switch(*(c+1)) {
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'U':
      switch(*(c+1)) {
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'Y':
      switch(*(c+1)) {
      case 'b':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case 'Z':
      switch(*(c+1)) {
      case 'r':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Sym,2,not_flag);
        atom_seen = true;
        break;
      case 'n':
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Zn,2,not_flag);
        atom_seen = true;
        break;
      default:
        c = ChampParseBlockAtom(I,c,cur_atom,cH_Z,1,not_flag);
        atom_seen = true;
        break;
      }
      break;
    case '+':
      num = ChampParseNumeral(c+1);
      if(num>=0) {
        c+=2;
      } else {
        num = 1;
        c++;
        while(*c) {
          if(*c!='+')
            break;
          else {
            num++;
            c++;
          }
        }
      }
      if(not_flag) {
        I->Atom[cur_atom].neg_flag=true;
        switch(num) {
        case 0: I->Atom[cur_atom].not_charge|=cH_Neutral; break;
        case 1: I->Atom[cur_atom].not_charge|=cH_Cation; break;
        case 2: I->Atom[cur_atom].not_charge|=cH_Dication; break;
        case 3: I->Atom[cur_atom].not_charge|=cH_Trication; break;
        case 4: I->Atom[cur_atom].not_charge|=cH_Tetcation; break;
        case 5: I->Atom[cur_atom].not_charge|=cH_Pentcation; break;
          
        }
      } else {
        I->Atom[cur_atom].pos_flag=true;
        switch(num) {
        case 0: I->Atom[cur_atom].charge|=cH_Neutral; break;
        case 1: I->Atom[cur_atom].charge|=cH_Cation; break;
        case 2: I->Atom[cur_atom].charge|=cH_Dication; break;
        case 3: I->Atom[cur_atom].charge|=cH_Trication; break;
        case 4: I->Atom[cur_atom].charge|=cH_Tetcation; break;
        case 5: I->Atom[cur_atom].charge|=cH_Pentcation; break;
        }
      }
      break;
    case '-':
      num = ChampParseNumeral(c+1);
      if(num>=0) {
        c+=2;
      } else {
        num = 1;
        c++;
        while(*c) {
          if(*c!='-')
            break;
          else {
            num++;
            c++;
          }
        }
      }
      if(not_flag) {
        I->Atom[cur_atom].neg_flag=true;
        switch(num) {
        case 0: I->Atom[cur_atom].not_charge|=cH_Neutral; break;
        case 1: I->Atom[cur_atom].not_charge|=cH_Anion; break;
        case 2: I->Atom[cur_atom].not_charge|=cH_Dianion; break;
        case 3: I->Atom[cur_atom].not_charge|=cH_Trianion; break;
        case 4: I->Atom[cur_atom].not_charge|=cH_Tetanion; break;
        case 5: I->Atom[cur_atom].not_charge|=cH_Pentanion; break;
        }
      } else {
        I->Atom[cur_atom].pos_flag=true;
        switch(num) {
        case 0: I->Atom[cur_atom].charge|=cH_Neutral; break;
        case 1: I->Atom[cur_atom].charge|=cH_Anion; break;
        case 2: I->Atom[cur_atom].charge|=cH_Dianion; break;
        case 3: I->Atom[cur_atom].charge|=cH_Trianion; break;
        case 4: I->Atom[cur_atom].charge|=cH_Tetanion; break;
        case 5: I->Atom[cur_atom].charge|=cH_Pentanion; break;
        }
      }
      break;
    default:
      PRINTFB(FB_smiles_parsing,FB_errors)
        " champ: error parsing atom block at '%c' in: '%s'\n",*c,*c_ptr
        ENDFB;
      c++;
      break;
    }
  }
  *c_ptr = c;
  return ok;
}