LCOV - code coverage report
Current view: top level - src - ichiqueu.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 1.9 % 523 10
Test Date: 2026-10-14 12:14:55 Functions: 6.2 % 16 1
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1.8 % 560 10

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <string.h>
       7                 :             : 
       8                 :             : #include "mode.h"
       9                 :             : #include "ichitaut.h"
      10                 :             : 
      11                 :             : #include "bcf_s.h"
      12                 :             : 
      13                 :             : /****************************************************************************/
      14                 :             : 
      15                 :             : #if ( FIND_RING_SYSTEMS == 1 ) /* { */
      16                 :             : 
      17                 :             : /* local prototypes */
      18                 :             : int are_alt_bonds( U_CHAR *bonds, int len );
      19                 :             : int AddBondsPos( inp_ATOM *atom, T_BONDPOS *BondPosTmp, int nNumBondPosTmp, T_BONDPOS *BondPos, int nMaxNumBondPos, int nNumBondPos );
      20                 :             : int AddEndPoints( T_ENDPOINT *EndPointTmp, int nNumNewEndPoint, T_ENDPOINT *EndPoint, int nMaxNumEndPoint, int nNumEndPoint );
      21                 :             : 
      22                 :             : 
      23                 :             : 
      24                 :             : 
      25                 :             : 
      26                 :             : /******************************************
      27                 :             :  *
      28                 :             :  *  Tautomerism in 5- and 6-member rings
      29                 :             :  *
      30                 :             :  ******************************************/
      31                 :             : 
      32                 :             : const int NONE = (AT_RANK) ~0;
      33                 :             : 
      34                 :             : 
      35                 :             : /*
      36                 :             :   1,5 Tautomerism in 6-member alt ring:
      37                 :             : 
      38                 :             :    /=\          /==\
      39                 :             :  HN   C=O  <-> N    C-OH
      40                 :             :    \=/          \\-//
      41                 :             : 
      42                 :             : 
      43                 :             :    1,2 Tautomerism in 5-member ring:
      44                 :             : 
      45                 :             : 
      46                 :             :   HN--X           N==X
      47                 :             :    |   \\         |   \
      48                 :             :    |    Z  <->    |    Z
      49                 :             :    |   /          |   //
      50                 :             :    N==Y          HN--Y
      51                 :             : 
      52                 :             : 
      53                 :             :   1,4 tautomerism in 7-member ring
      54                 :             : 
      55                 :             :       /C==D             //C-D
      56                 :             :    O=B     \        HO-B     \\
      57                 :             :      |      E  <->     |      E
      58                 :             :   HO-A     //        O=A     /
      59                 :             :       \\G-F             \\G-F
      60                 :             : 
      61                 :             : 
      62                 :             :   1,4 tautomerism in 5-member ring
      63                 :             : 
      64                 :             : 
      65                 :             :    O=B--C            O-B==C
      66                 :             :      |   \\            |   \
      67                 :             :      |     D  <->      |     D
      68                 :             :      |   /             |   //
      69                 :             :   HO-A==E           HO=A--E
      70                 :             : 
      71                 :             : */
      72                 :             : typedef int CHECK_DFS_RING( struct tagCANON_GLOBALS *pCG,
      73                 :             :     inp_ATOM *atom,
      74                 :             :     DFS_PATH *DfsPath,
      75                 :             :     int nLenDfsPath,
      76                 :             :     int nStartAtomNeighbor,
      77                 :             :     int nStartAtomNeighbor2,
      78                 :             :     int nStartAtomNeighborNeighbor,
      79                 :             :     T_ENDPOINT *EndPoint,
      80                 :             :     int nMaxNumEndPoint,
      81                 :             :     T_BONDPOS  *BondPos,
      82                 :             :     int nMaxNumBondPos,
      83                 :             :     int *pnNumEndPoint,
      84                 :             :     int *pnNumBondPos,
      85                 :             :     struct BalancedNetworkStructure *pBNS,
      86                 :             :     struct BalancedNetworkData *pBD,
      87                 :             :     int num_atoms );
      88                 :             : 
      89                 :             : typedef int CHECK_CENTERPOINT( inp_ATOM *atom, int iat );
      90                 :             : 
      91                 :             : CHECK_DFS_RING Check7MembTautRing;
      92                 :             : CHECK_DFS_RING Check6MembTautRing;
      93                 :             : CHECK_DFS_RING Check5MembTautRing;
      94                 :             : 
      95                 :             : #if ( TAUT_15_NON_RING == 1 )  /* post v.1 feature */
      96                 :             : /* DFS simple alt path for 1,5 tautomerism, post v.1 feature */
      97                 :             : typedef int CHECK_DFS_PATH( struct tagCANON_GLOBALS *pCG,
      98                 :             :     inp_ATOM *atom,
      99                 :             :     DFS_PATH *DfsPath,
     100                 :             :     int nLenDfsPath,
     101                 :             :     int jNxtNeigh,
     102                 :             :     int nStartAtomNeighbor,
     103                 :             :     int nStartAtomNeighbor2,
     104                 :             :     int nStartAtomNeighborNeighbor,
     105                 :             :     T_ENDPOINT *EndPoint,
     106                 :             :     int nMaxNumEndPoint,
     107                 :             :     T_BONDPOS  *BondPos,
     108                 :             :     int nMaxNumBondPos,
     109                 :             :     int *pnNumEndPoint,
     110                 :             :     int *pnNumBondPos,
     111                 :             :     struct BalancedNetworkStructure *pBNS,
     112                 :             :     struct BalancedNetworkData *pBD,
     113                 :             :     int num_atoms );
     114                 :             : 
     115                 :             : typedef int CHECK_DFS_CENTERPOINT( inp_ATOM *atom, DFS_PATH *DfsPath, int nLenDfsPath, int jNxtNeigh,
     116                 :             :     struct BalancedNetworkStructure *pBNS,
     117                 :             :     struct BalancedNetworkData *pBD, int num_atoms );
     118                 :             : 
     119                 :             : 
     120                 :             : CHECK_DFS_PATH        Check15TautPath;
     121                 :             : CHECK_DFS_CENTERPOINT Check15TautPathCenterpoint;
     122                 :             : 
     123                 :             : int DFS_FindTautAltPath( struct tagCANON_GLOBALS *pCG,
     124                 :             :     inp_ATOM *atom,
     125                 :             :     int nStartAtom,
     126                 :             :     int nStartAtomNeighbor,
     127                 :             :     int nStartAtomNeighbor2,
     128                 :             :     int nStartAtomNeighborNeighbor,
     129                 :             :     int nCycleLen,
     130                 :             :     AT_RANK  *nDfsPathPos,
     131                 :             :     DFS_PATH *DfsPath,
     132                 :             :     CHECK_DFS_PATH *CheckDfsPath,
     133                 :             :     CHECK_DFS_CENTERPOINT *CheckCenterPoint,
     134                 :             :     T_ENDPOINT *EndPoint,
     135                 :             :     int nMaxNumEndPoint,
     136                 :             :     T_BONDPOS  *BondPos,
     137                 :             :     int nMaxNumBondPos,
     138                 :             :     int *pnNumEndPoint,
     139                 :             :     int *pnNumBondPos,
     140                 :             :     struct BalancedNetworkStructure *pBNS,
     141                 :             :     struct BalancedNetworkData *pBD,
     142                 :             :     int num_atoms );
     143                 :             : 
     144                 :             : #define BOND_WRONG 64
     145                 :             : #define IS_ALT_OR_DBLBOND(X) (((X) == BOND_SINGLE || (X) == BOND_DOUBLE)? (X) : \
     146                 :             :                               ((X) == BOND_ALTERN || (X) == BOND_TAUTOM || (X) == BOND_ALT12NS)? BOND_ALTERN : \
     147                 :             :                               BOND_WRONG);
     148                 :             : 
     149                 :             : #endif /* TAUT_15_NON_RING */
     150                 :             : 
     151                 :             : int DFS_FindTautInARing( struct tagCANON_GLOBALS *pCG,
     152                 :             :     inp_ATOM *atom,
     153                 :             :     int nStartAtom,
     154                 :             :     int nStartAtomNeighbor,
     155                 :             :     int nStartAtomNeighbor2,
     156                 :             :     int nStartAtomNeighborNeighbor,
     157                 :             :     int nCycleLen,
     158                 :             :     AT_RANK  *nDfsPathPos,
     159                 :             :     DFS_PATH *DfsPath,
     160                 :             :     CHECK_DFS_RING *CheckDfsRing,
     161                 :             :     CHECK_CENTERPOINT *CheckCenterPoint,
     162                 :             :     T_ENDPOINT *EndPoint,
     163                 :             :     int nMaxNumEndPoint,
     164                 :             :     T_BONDPOS  *BondPos,
     165                 :             :     int nMaxNumBondPos,
     166                 :             :     int *pnNumEndPoint,
     167                 :             :     int *pnNumBondPos,
     168                 :             :     struct BalancedNetworkStructure *pBNS,
     169                 :             :     struct BalancedNetworkData *pBD,
     170                 :             :     int num_atoms );
     171                 :             : 
     172                 :             : #if ( REPLACE_ALT_WITH_TAUT == 1 )
     173                 :             : #define REPLACE_THE_BOND(X) ( (X) == BOND_SINGLE || (X) == BOND_DOUBLE || (X) == BOND_ALTERN || (X) == BOND_ALT12NS )
     174                 :             : #else
     175                 :             : #define REPLACE_THE_BOND(X) ( (X) == BOND_SINGLE || (X) == BOND_DOUBLE )
     176                 :             : #endif
     177                 :             : 
     178                 :             : 
     179                 :             : /****************************************************************************/
     180                 :         172 : int bIsCenterPointStrict( inp_ATOM *atom, int iat )
     181                 :             : {
     182         [ +  + ]:         172 :     if (atom[iat].valence == atom[iat].chem_bonds_valence)
     183                 :             :     {
     184                 :          86 :         int endpoint_valence = get_endpoint_valence( atom[iat].el_number );
     185   [ +  +  -  + ]:          86 :         if (endpoint_valence && ( (endpoint_valence > atom[iat].valence && /* added a check for negative charge or H 3-31-03 */
     186   [ #  #  #  # ]:           0 :             ( atom[iat].num_H || atom[iat].charge == -1 )) ||
     187   [ +  -  -  + ]:           8 :             (!atom[iat].charge && atom[iat].c_point) )) /* djb-rwth: addressing LLVM warnings */
     188                 :             :         {
     189                 :           0 :             return 1; /*  may appear to be tautomeric or chargable
     190                 :             :                           (this increases chem_bonds_valence), should be explored */
     191                 :             :         }
     192                 :          86 :         return 0;
     193                 :             :     }
     194   [ +  -  +  + ]:         172 :     if (atom[iat].valence + 1 == atom[iat].chem_bonds_valence &&
     195                 :          86 :         is_centerpoint_elem_strict( atom[iat].el_number ))
     196                 :             :     {
     197                 :          84 :         return 1;
     198                 :             :     }
     199                 :             : 
     200                 :           2 :     return 0;
     201                 :             : }
     202                 :             : 
     203                 :             : 
     204                 :             : /****************************************************************************/
     205                 :           0 : int nGet14TautIn7MembAltRing( struct tagCANON_GLOBALS *pCG,
     206                 :             :                               inp_ATOM *atom,
     207                 :             :                               int nStartAtom,
     208                 :             :                               int nStartAtomNeighbor,
     209                 :             :                               int nStartAtomNeighborEndpoint,
     210                 :             :                               int nStartAtomNeighborNeighborEndpoint,
     211                 :             :                               AT_RANK  *nDfsPathPos,
     212                 :             :                               DFS_PATH *DfsPath,
     213                 :             :                               int nMaxLenDfsPath,
     214                 :             :                               T_ENDPOINT *EndPoint,
     215                 :             :                               int nMaxNumEndPoint,
     216                 :             :                               T_BONDPOS  *BondPos,
     217                 :             :                               int nMaxNumBondPos,
     218                 :             :                               int *pnNumEndPoint,
     219                 :             :                               int *pnNumBondPos,
     220                 :             :                               struct BalancedNetworkStructure *pBNS,
     221                 :             :                               struct BalancedNetworkData *pBD,
     222                 :             :                               int num_atoms )
     223                 :             : {
     224                 :             :     int nRet;
     225                 :             : 
     226                 :           0 :     *pnNumEndPoint = 0;
     227                 :           0 :     *pnNumBondPos = 0;
     228                 :             : 
     229         [ #  # ]:           0 :     if (nMaxLenDfsPath <= 7)
     230                 :             :     {
     231                 :           0 :         return -1; /*  path is too short */
     232                 :             :     }
     233                 :             : 
     234                 :           0 :     nRet = DFS_FindTautInARing( pCG, atom, nStartAtom, nStartAtomNeighbor,
     235                 :             :                                 nStartAtomNeighborEndpoint,
     236                 :             :                                 nStartAtomNeighborNeighborEndpoint, 7,
     237                 :             :                                 nDfsPathPos, DfsPath, Check7MembTautRing,
     238                 :             :                                 bIsCenterPointStrict, EndPoint, nMaxNumEndPoint,
     239                 :             :                                 BondPos, nMaxNumBondPos, pnNumEndPoint,
     240                 :             :                                 pnNumBondPos, pBNS, pBD, num_atoms );
     241                 :             : 
     242                 :             : 
     243                 :           0 :     return nRet;
     244                 :             : }
     245                 :             : 
     246                 :             : 
     247                 :             : /****************************************************************************/
     248                 :           0 : int nGet14TautIn5MembAltRing( struct tagCANON_GLOBALS *pCG,
     249                 :             :                               inp_ATOM *atom,
     250                 :             :                               int nStartAtom,
     251                 :             :                               int nStartAtomNeighbor,
     252                 :             :                               int nStartAtomNeighborEndpoint,
     253                 :             :                               int nStartAtomNeighborNeighborEndpoint,
     254                 :             :                               AT_RANK  *nDfsPathPos,
     255                 :             :                               DFS_PATH *DfsPath,
     256                 :             :                               int nMaxLenDfsPath,
     257                 :             :                               T_ENDPOINT *EndPoint,
     258                 :             :                               int nMaxNumEndPoint,
     259                 :             :                               T_BONDPOS  *BondPos,
     260                 :             :                               int nMaxNumBondPos,
     261                 :             :                               int *pnNumEndPoint,
     262                 :             :                               int *pnNumBondPos,
     263                 :             :                               struct BalancedNetworkStructure *pBNS,
     264                 :             :                               struct BalancedNetworkData *pBD,
     265                 :             :                               int num_atoms )
     266                 :             : {
     267                 :             :     int nRet;
     268                 :             : 
     269                 :           0 :     *pnNumEndPoint = 0;
     270                 :           0 :     *pnNumBondPos = 0;
     271                 :             : 
     272         [ #  # ]:           0 :     if (nMaxLenDfsPath <= 5)
     273                 :             :     {
     274                 :           0 :         return -1; /*  path is too short */
     275                 :             :     }
     276                 :             : 
     277                 :           0 :     nRet = DFS_FindTautInARing( pCG, atom, nStartAtom, nStartAtomNeighbor,
     278                 :             :         nStartAtomNeighborEndpoint, nStartAtomNeighborNeighborEndpoint, 5,
     279                 :             :         nDfsPathPos, DfsPath, Check7MembTautRing, bIsCenterPointStrict,
     280                 :             :         EndPoint, nMaxNumEndPoint, BondPos, nMaxNumBondPos,
     281                 :             :         pnNumEndPoint, pnNumBondPos, pBNS, pBD, num_atoms );
     282                 :             : 
     283                 :           0 :     return nRet;
     284                 :             : }
     285                 :             : 
     286                 :             : /****************************************************************************/
     287                 :           0 : int nGet12TautIn5MembAltRing( struct tagCANON_GLOBALS *pCG,
     288                 :             :                               inp_ATOM *atom,
     289                 :             :                               int nStartAtom,
     290                 :             :                               int nStartAtomNeighbor,
     291                 :             :                               AT_RANK  *nDfsPathPos,
     292                 :             :                               DFS_PATH *DfsPath,
     293                 :             :                               int nMaxLenDfsPath,
     294                 :             :                               T_ENDPOINT *EndPoint,
     295                 :             :                               int nMaxNumEndPoint,
     296                 :             :                               T_BONDPOS  *BondPos,
     297                 :             :                               int nMaxNumBondPos,
     298                 :             :                               int *pnNumEndPoint,
     299                 :             :                               int *pnNumBondPos,
     300                 :             :                               struct BalancedNetworkStructure *pBNS,
     301                 :             :                               struct BalancedNetworkData *pBD,
     302                 :             :                               int num_atoms )
     303                 :             : {
     304                 :             :     int nRet;
     305                 :             : 
     306                 :           0 :     *pnNumEndPoint = 0;
     307                 :           0 :     *pnNumBondPos = 0;
     308                 :             : 
     309         [ #  # ]:           0 :     if (nMaxLenDfsPath <= 5)
     310                 :             :     {
     311                 :           0 :         return -1; /*  path is too short */
     312                 :             :     }
     313                 :             : 
     314                 :           0 :     nRet = DFS_FindTautInARing( pCG, atom, nStartAtom, nStartAtomNeighbor,
     315                 :             :                                 -1, -1, 5,
     316                 :             :                                 nDfsPathPos, DfsPath, Check5MembTautRing,
     317                 :             :                                 bIsCenterPointStrict, EndPoint, nMaxNumEndPoint,
     318                 :             :                                 BondPos, nMaxNumBondPos, pnNumEndPoint,
     319                 :             :                                 pnNumBondPos, pBNS, pBD, num_atoms );
     320                 :             : 
     321                 :           0 :     return nRet;
     322                 :             : }
     323                 :             : 
     324                 :             : 
     325                 :             : /****************************************************************************/
     326                 :           0 : int nGet15TautIn6MembAltRing( struct tagCANON_GLOBALS *pCG,
     327                 :             :                               inp_ATOM *atom,
     328                 :             :                               int nStartAtom,
     329                 :             :                               AT_RANK  *nDfsPathPos,
     330                 :             :                               DFS_PATH *DfsPath,
     331                 :             :                               int nMaxLenDfsPath,
     332                 :             :                               T_ENDPOINT *EndPoint,
     333                 :             :                               int nMaxNumEndPoint,
     334                 :             :                               T_BONDPOS  *BondPos,
     335                 :             :                               int nMaxNumBondPos,
     336                 :             :                               int *pnNumEndPoint,
     337                 :             :                               int *pnNumBondPos,
     338                 :             :                               struct BalancedNetworkStructure *pBNS,
     339                 :             :                               struct BalancedNetworkData *pBD,
     340                 :             :                               int num_atoms )
     341                 :             : {
     342                 :             :     int nRet;
     343                 :             : 
     344                 :           0 :     *pnNumEndPoint = 0;
     345                 :           0 :     *pnNumBondPos = 0;
     346                 :             : 
     347         [ #  # ]:           0 :     if (nMaxLenDfsPath <= 7)
     348                 :             :     {
     349                 :           0 :         return -1; /*  path is too short */
     350                 :             :     }
     351                 :             : 
     352                 :           0 :     nRet = DFS_FindTautInARing( pCG, atom, nStartAtom,
     353                 :             :                                 -1/*nStartAtomNeighbor*/,
     354                 :             :                                 -1/*nStartAtomNeighbor2*/,
     355                 :             :                                 -1/*nStartAtomNeighborNeighbor*/,
     356                 :             :                                 6 /* nCycleLen*/,
     357                 :             :                                 nDfsPathPos, DfsPath,
     358                 :             :                                 Check6MembTautRing, bIsCenterPointStrict,
     359                 :             :                                 EndPoint, nMaxNumEndPoint,
     360                 :             :                                 BondPos, nMaxNumBondPos,
     361                 :             :                                 pnNumEndPoint, pnNumBondPos,
     362                 :             :                                 pBNS, pBD, num_atoms );
     363                 :             : 
     364                 :           0 :     return nRet;
     365                 :             : }
     366                 :             : 
     367                 :             : 
     368                 :             : #if ( TAUT_15_NON_RING      == 1 ) /***** post v.1 feature *****/
     369                 :             : 
     370                 :             : 
     371                 :             : /****************************************************************************/
     372                 :           0 : int nGet15TautInAltPath( struct tagCANON_GLOBALS *pCG,
     373                 :             :                          inp_ATOM *atom,
     374                 :             :                          int nStartAtom,
     375                 :             :                          AT_RANK  *nDfsPathPos,
     376                 :             :                          DFS_PATH *DfsPath,
     377                 :             :                          int nMaxLenDfsPath,
     378                 :             :                          T_ENDPOINT *EndPoint,
     379                 :             :                          int nMaxNumEndPoint,
     380                 :             :                          T_BONDPOS  *BondPos,
     381                 :             :                          int nMaxNumBondPos,
     382                 :             :                          int *pnNumEndPoint,
     383                 :             :                          int *pnNumBondPos,
     384                 :             :                          struct BalancedNetworkStructure *pBNS,
     385                 :             :                          struct BalancedNetworkData *pBD,
     386                 :             :                          int num_atoms )
     387                 :             : {
     388                 :             :     int nRet;
     389                 :             : 
     390                 :           0 :     *pnNumEndPoint = 0;
     391                 :           0 :     *pnNumBondPos = 0;
     392                 :             : 
     393         [ #  # ]:           0 :     if (nMaxLenDfsPath <= 7)
     394                 :             :     {
     395                 :           0 :         return -1; /*  path is too short */
     396                 :             :     }
     397                 :             : 
     398                 :           0 :     nRet = DFS_FindTautAltPath( pCG, atom, nStartAtom,
     399                 :             :                                 -1/*nStartAtomNeighbor*/,
     400                 :             :                                 -1/*nStartAtomNeighbor2*/,
     401                 :             :                                 -1/*nStartAtomNeighborNeighbor*/,
     402                 :             :                                 4 /* nCycleLen*/,
     403                 :             :                                 nDfsPathPos, DfsPath,
     404                 :             :                                 Check15TautPath, Check15TautPathCenterpoint,
     405                 :             :                                 EndPoint, nMaxNumEndPoint,
     406                 :             :                                 BondPos, nMaxNumBondPos,
     407                 :             :                                 pnNumEndPoint, pnNumBondPos,
     408                 :             :                                 pBNS, pBD, num_atoms );
     409                 :             : 
     410                 :           0 :     return nRet;
     411                 :             : }
     412                 :             : #endif
     413                 :             : 
     414                 :             : 
     415                 :             : /****************************************************************************
     416                 :             :   DFS version
     417                 :             : ****************************************************************************/
     418                 :             : #define MAX_DFS_DEPTH 16
     419                 :             : 
     420                 :             : 
     421                 :             : 
     422                 :             : /********************************************************************************/
     423                 :           0 : int DFS_FindTautInARing( struct tagCANON_GLOBALS *pCG,
     424                 :             :                          inp_ATOM *atom,
     425                 :             :                          int nStartAtom,
     426                 :             :                          int nStartAtomNeighbor,
     427                 :             :                          int nStartAtomNeighbor2,
     428                 :             :                          int nStartAtomNeighborNeighbor,
     429                 :             :                          int nCycleLen,
     430                 :             :                          AT_RANK  *nDfsPathPos,
     431                 :             :                          DFS_PATH *DfsPath,
     432                 :             :                          CHECK_DFS_RING *CheckDfsRing,
     433                 :             :                          CHECK_CENTERPOINT *CheckCenterPoint,
     434                 :             :                          T_ENDPOINT *EndPoint,
     435                 :             :                          int nMaxNumEndPoint,
     436                 :             :                          T_BONDPOS  *BondPos,
     437                 :             :                          int nMaxNumBondPos,
     438                 :             :                          int *pnNumEndPoint,
     439                 :             :                          int *pnNumBondPos,
     440                 :             :                          struct BalancedNetworkStructure *pBNS,
     441                 :             :                          struct BalancedNetworkData *pBD,
     442                 :             :                          int num_atoms )
     443                 :             : {
     444                 :             :     /*  Depth First Search */
     445                 :             :     /*  Ignore all atoms not belonging to the current ring system (=biconnected component) */
     446                 :             :     AT_RANK      nMinLenDfsPath;
     447                 :             :     int          j, cur_at, nxt_at, prv_at;
     448                 :             :     int          nLenDfsPath, nNumFound, ret;
     449                 :             :     /* djb-rwth: removing redundant variables */
     450                 :           0 :     int          nDoNotTouchAtom1 = -1, nDoNotTouchAtom2 = -1;
     451                 :             : 
     452                 :           0 :     nLenDfsPath = 0;
     453                 :           0 :     nNumFound = 0;
     454                 :             : 
     455                 :           0 :     nCycleLen--;
     456                 :             : 
     457                 :           0 :     DfsPath[nLenDfsPath].at_no = cur_at = nStartAtom;
     458                 :           0 :     DfsPath[nLenDfsPath].bond_type = 0;
     459                 :           0 :     DfsPath[nLenDfsPath].bond_pos = -1;
     460                 :           0 :     nDfsPathPos[cur_at] = nLenDfsPath + 1;  /*  mark */
     461                 :             :     /* djb-rwth: removing redundant code */
     462                 :           0 :     nMinLenDfsPath = 0;
     463         [ #  # ]:           0 :     if (nStartAtomNeighbor2 >= 0)
     464                 :             :     {
     465                 :           0 :         nDoNotTouchAtom1 = (int) atom[cur_at].neighbor[nStartAtomNeighbor2];
     466                 :             :     }
     467                 :             : 
     468                 :             :     /*  add the first neighbor to the 2nd tree position if required */
     469         [ #  # ]:           0 :     if (nStartAtomNeighbor >= 0)
     470                 :             :     {
     471                 :           0 :         j = nStartAtomNeighbor;
     472                 :           0 :         prv_at = cur_at;
     473                 :           0 :         cur_at = atom[prv_at].neighbor[j];
     474                 :           0 :         DfsPath[nLenDfsPath].bond_type = ( atom[prv_at].bond_type[j] & ~BOND_MARK_ALL );
     475                 :             : #if ( FIX_BOND23_IN_TAUT == 1 )
     476                 :             :         DfsPath[nLenDfsPath].bond_type = ACTUAL_ORDER( pBNS, prv_at, j, DfsPath[nLenDfsPath].bond_type );
     477                 :             : #endif
     478                 :           0 :         DfsPath[nLenDfsPath].bond_pos = j;
     479                 :             : 
     480                 :           0 :         nLenDfsPath++;
     481                 :             : 
     482                 :           0 :         DfsPath[nLenDfsPath].at_no = cur_at;
     483                 :           0 :         DfsPath[nLenDfsPath].bond_type = 0;
     484                 :           0 :         DfsPath[nLenDfsPath].bond_pos = -1;
     485                 :           0 :         nDfsPathPos[cur_at] = nLenDfsPath + 1;
     486                 :           0 :         nMinLenDfsPath++;
     487         [ #  # ]:           0 :         if (nStartAtomNeighborNeighbor >= 0)
     488                 :             :         {
     489                 :           0 :             nDoNotTouchAtom2 = (int) atom[cur_at].neighbor[nStartAtomNeighborNeighbor];
     490                 :             :         }
     491                 :             :     }
     492                 :             : 
     493                 :             :     /*  MAIN DFS CYCLE: may find one and the same t-group 2 times; saves only one instance */
     494                 :             :     /*  traverse *all* paths starting at atom[nStartAtom]; max. path length = (nCycleLen+1)  */
     495         [ #  # ]:           0 :     while (nLenDfsPath >= nMinLenDfsPath)
     496                 :             :     {
     497                 :           0 :         j = ++DfsPath[nLenDfsPath].bond_pos;
     498         [ #  # ]:           0 :         if (j < atom[cur_at = (int) DfsPath[nLenDfsPath].at_no].valence)
     499                 :             :         {
     500                 :           0 :             DfsPath[nLenDfsPath].bond_type = ( atom[cur_at].bond_type[j] & ~BOND_MARK_ALL );
     501                 :             : #if ( FIX_BOND23_IN_TAUT == 1 )
     502                 :             :             DfsPath[nLenDfsPath].bond_type = ACTUAL_ORDER( pBNS, cur_at, j, DfsPath[nLenDfsPath].bond_type );
     503                 :             : #endif
     504                 :           0 :             nxt_at = (int) atom[cur_at].neighbor[j];
     505   [ #  #  #  # ]:           0 :             if (nxt_at == nDoNotTouchAtom1 ||
     506                 :             :                 nxt_at == nDoNotTouchAtom2)
     507                 :             :             {
     508                 :             :                 ; /*  ignore */
     509                 :             :             }
     510                 :             :             else
     511                 :             :             {
     512         [ #  # ]:           0 :                 if (nDfsPathPos[nxt_at])
     513                 :             :                 {
     514                 :             :                     /*  found a ring closure or a step backwards */
     515   [ #  #  #  # ]:           0 :                     if (1 == nDfsPathPos[nxt_at] && nLenDfsPath == nCycleLen)
     516                 :             :                     {
     517                 :             :                         /*  we have found the cycle; check it */
     518                 :           0 :                         ret = ( *CheckDfsRing )( pCG,
     519                 :             :                             atom,
     520                 :             :                             DfsPath, nLenDfsPath,
     521                 :             :                             nStartAtomNeighbor,
     522                 :             :                             nStartAtomNeighbor2,
     523                 :             :                             nStartAtomNeighborNeighbor,
     524                 :             :                             EndPoint, nMaxNumEndPoint,
     525                 :             :                             BondPos, nMaxNumBondPos,
     526                 :             :                             pnNumEndPoint, pnNumBondPos,
     527                 :             :                             pBNS, pBD, num_atoms );
     528         [ #  # ]:           0 :                         if (ret < 0)
     529                 :             :                         {
     530                 :           0 :                             nNumFound = ret;
     531                 :           0 :                             goto clear_path;
     532                 :             :                         }
     533                 :           0 :                         nNumFound += ret;
     534                 :             :                     }
     535                 :             :                 }
     536                 :             :                 else
     537                 :             :                 {
     538         [ #  # ]:           0 :                     if (!( *CheckCenterPoint )( atom, nxt_at ))
     539                 :             :                     {
     540                 :             :                         ; /*  cannot advance to a non-centerpoint; ignore */
     541                 :             :                     }
     542                 :             :                     else
     543                 :             :                     {
     544         [ #  # ]:           0 :                         if (nLenDfsPath < nCycleLen)
     545                 :             :                         {
     546                 :             :                             /*  advance */
     547                 :           0 :                             nLenDfsPath++;
     548                 :           0 :                             cur_at = nxt_at;
     549                 :           0 :                             DfsPath[nLenDfsPath].at_no = cur_at;
     550                 :           0 :                             DfsPath[nLenDfsPath].bond_type = 0;
     551                 :           0 :                             DfsPath[nLenDfsPath].bond_pos = -1;
     552                 :           0 :                             nDfsPathPos[cur_at] = nLenDfsPath + 1;  /*  mark */
     553                 :             :                         }
     554                 :             :                     }
     555                 :             :                 }
     556                 :             :             }
     557                 :             :         }
     558                 :             :         else
     559                 :             :         {
     560                 :             :             /*  retract */
     561                 :           0 :             nDfsPathPos[(int) DfsPath[nLenDfsPath].at_no] = 0;
     562                 :           0 :             nLenDfsPath--;
     563                 :             :         }
     564                 :             :     }
     565                 :             : 
     566                 :           0 : clear_path:
     567         [ #  # ]:           0 :     while (0 <= nLenDfsPath)
     568                 :             :     {
     569                 :           0 :         nDfsPathPos[(int) DfsPath[nLenDfsPath].at_no] = 0;
     570                 :           0 :         nLenDfsPath--;
     571                 :             :     }
     572                 :             : 
     573                 :           0 :     return nNumFound;
     574                 :             : }
     575                 :             : 
     576                 :             : 
     577                 :             : #if ( TAUT_15_NON_RING      == 1 ) /***** post v.1 feature *****/
     578                 :             : 
     579                 :             : 
     580                 :             : /****************************************************************************/
     581                 :           0 : int DFS_FindTautAltPath( struct tagCANON_GLOBALS *pCG,
     582                 :             :                          inp_ATOM *atom,
     583                 :             :                          int nStartAtom,
     584                 :             :                          int nStartAtomNeighbor,
     585                 :             :                          int nStartAtomNeighbor2,
     586                 :             :                          int nStartAtomNeighborNeighbor,
     587                 :             :                          int nCycleLen,
     588                 :             :                          AT_RANK  *nDfsPathPos,
     589                 :             :                          DFS_PATH *DfsPath,
     590                 :             :                          CHECK_DFS_PATH *CheckDfsPath,
     591                 :             :                          CHECK_DFS_CENTERPOINT *CheckCenterPointPath,
     592                 :             :                          T_ENDPOINT *EndPoint,
     593                 :             :                          int nMaxNumEndPoint,
     594                 :             :                          T_BONDPOS  *BondPos,
     595                 :             :                          int nMaxNumBondPos,
     596                 :             :                          int *pnNumEndPoint,
     597                 :             :                          int *pnNumBondPos,
     598                 :             :                          struct BalancedNetworkStructure *pBNS,
     599                 :             :                          struct BalancedNetworkData *pBD,
     600                 :             :                          int num_atoms )
     601                 :             : {
     602                 :             :     /*  Naive Depth First Search: same atom may be approached along different alt paths */
     603                 :             :     /*  Ignore all atoms not belonging to the current ring system (=biconnected component) */
     604                 :             :     AT_RANK      nMinLenDfsPath;
     605                 :             :     int          j, cur_at, nxt_at, prv_at;
     606                 :             :     int          nLenDfsPath, nNumFound, ret;
     607                 :             :     /* djb-rwth: removing redundant variables */
     608                 :           0 :     int          nDoNotTouchAtom1 = -1, nDoNotTouchAtom2 = -1;
     609                 :             : 
     610                 :           0 :     nLenDfsPath = 0;
     611                 :           0 :     nNumFound = 0;
     612                 :             : 
     613                 :           0 :     nCycleLen--; /* indef of the last atom in the alt path, statring from 0 */
     614                 :             : 
     615                 :           0 :     DfsPath[nLenDfsPath].at_no = cur_at = nStartAtom;
     616                 :           0 :     DfsPath[nLenDfsPath].bond_type = 0;
     617                 :           0 :     DfsPath[nLenDfsPath].bond_pos = -1;  /* initialize index of the bond to the next atom */
     618                 :           0 :     nDfsPathPos[cur_at] = nLenDfsPath + 1;  /*  mark with distance + 1 */
     619                 :             :     /* djb-rwth: removing redundant variables/code */
     620                 :           0 :     nMinLenDfsPath = 0;  /* allow to restart from nStartAtom */
     621         [ #  # ]:           0 :     if (nStartAtomNeighbor2 >= 0)
     622                 :             :     {
     623                 :           0 :         nDoNotTouchAtom1 = (int) atom[cur_at].neighbor[nStartAtomNeighbor2];
     624                 :             :     }
     625                 :             : 
     626                 :             :     /*  add the first neighbor to the 2nd tree position if required */
     627         [ #  # ]:           0 :     if (nStartAtomNeighbor >= 0)
     628                 :             :     {
     629                 :           0 :         j = nStartAtomNeighbor;
     630                 :           0 :         prv_at = cur_at;
     631                 :           0 :         cur_at = atom[prv_at].neighbor[j];
     632                 :           0 :         DfsPath[nLenDfsPath].bond_type = ( atom[prv_at].bond_type[j] & ~BOND_MARK_ALL );
     633                 :             : #if ( FIX_BOND23_IN_TAUT == 1 )
     634                 :             :         DfsPath[nLenDfsPath].bond_type = ACTUAL_ORDER( pBNS, prv_at, j, DfsPath[nLenDfsPath].bond_type );
     635                 :             : #endif
     636                 :           0 :         DfsPath[nLenDfsPath].bond_pos = j; /* fix index of the bond to the next atom */
     637                 :             : 
     638                 :           0 :         nLenDfsPath++;
     639                 :             : 
     640                 :           0 :         DfsPath[nLenDfsPath].at_no = cur_at;
     641                 :           0 :         DfsPath[nLenDfsPath].bond_type = 0;
     642                 :           0 :         DfsPath[nLenDfsPath].bond_pos = -1;
     643                 :           0 :         nDfsPathPos[cur_at] = nLenDfsPath + 1; /* mark with distance + 1 */
     644                 :           0 :         nMinLenDfsPath++;                 /* allow to restart from nStartAtom's neighbor */
     645         [ #  # ]:           0 :         if (nStartAtomNeighborNeighbor >= 0)
     646                 :             :         {
     647                 :           0 :             nDoNotTouchAtom2 = (int) atom[cur_at].neighbor[nStartAtomNeighborNeighbor];
     648                 :             :         }
     649                 :             :     }
     650                 :             : 
     651                 :             :     /*  MAIN DFS CYCLE: may find one and the same t-group 2 times; saves only one instance */
     652                 :             :     /*  traverse *all* paths starting at atom[nStartAtom]; max. path length = (nCycleLen+1)  */
     653         [ #  # ]:           0 :     while (nLenDfsPath >= nMinLenDfsPath)
     654                 :             :     {
     655                 :           0 :         j = ++DfsPath[nLenDfsPath].bond_pos;
     656         [ #  # ]:           0 :         if (j < atom[cur_at = (int) DfsPath[nLenDfsPath].at_no].valence)
     657                 :             :         {
     658                 :           0 :             DfsPath[nLenDfsPath].bond_type = ( atom[cur_at].bond_type[j] & ~BOND_MARK_ALL );
     659                 :             : #if ( FIX_BOND23_IN_TAUT == 1 )
     660                 :             :             DfsPath[nLenDfsPath].bond_type = ACTUAL_ORDER( pBNS, cur_at, j, DfsPath[nLenDfsPath].bond_type );
     661                 :             : #endif
     662                 :           0 :             nxt_at = (int) atom[cur_at].neighbor[j];
     663   [ #  #  #  # ]:           0 :             if (nxt_at == nDoNotTouchAtom1 || /* forbidden */
     664                 :           0 :                 nxt_at == nDoNotTouchAtom2 || /* forbidden */
     665   [ #  #  #  # ]:           0 :                 nDfsPathPos[nxt_at] || /* ring closure */
     666         [ #  # ]:           0 :                 (nLenDfsPath && nxt_at == (int) DfsPath[nLenDfsPath - 1].at_no) /* step backwards */
     667                 :             :                 ) /* djb-rwth: addressing LLVM warning */
     668                 :             :             {
     669                 :             :                 ; /* ignore nxt_at */
     670                 :             :             }
     671                 :             :             else
     672                 :             :             {
     673         [ #  # ]:           0 :                 if (nLenDfsPath == nCycleLen &&
     674                 :             :                        /* 1,5 and at least one of the endpoints is not in a ring */
     675   [ #  #  #  #  :           0 :                     ( atom[nxt_at].nNumAtInRingSystem == 1 || atom[nStartAtom].nNumAtInRingSystem == 1 ) &&
                   #  # ]
     676                 :             :                        /*  we have found the alt path of the requested length; check it */
     677                 :             :                        /* calling Check15TautPath() */
     678                 :           0 :                        ( ret = ( *CheckDfsPath )( pCG,
     679                 :             :                                                   atom,
     680                 :             :                                                   DfsPath, nLenDfsPath,
     681                 :             :                                                   j, nStartAtomNeighbor,
     682                 :             :                                                   nStartAtomNeighbor2,
     683                 :             :                                                   nStartAtomNeighborNeighbor,
     684                 :             :                                                   EndPoint, nMaxNumEndPoint, BondPos, nMaxNumBondPos,
     685                 :             :                                                   pnNumEndPoint, pnNumBondPos,
     686                 :             :                                                   pBNS, pBD, num_atoms ) ))
     687                 :             :                 {
     688         [ #  # ]:           0 :                     if (ret < 0)
     689                 :             :                     {
     690                 :           0 :                         nNumFound = ret;
     691                 :           0 :                         goto clear_path; /* program error */
     692                 :             :                     }
     693                 :           0 :                     nNumFound += ret; /* success */
     694                 :             :                 }
     695                 :             :                 else
     696                 :             :                 {
     697                 :             :                     /* calling Check15TautPathCenterpoint() */
     698         [ #  # ]:           0 :                     if (!( *CheckCenterPointPath )( atom, DfsPath, nLenDfsPath, j,
     699                 :             :                                                     pBNS, pBD, num_atoms ))
     700                 :             :                     {
     701                 :             :                         ; /*  cannot advance to a non-centerpoint; ignore */
     702                 :             :                     }
     703                 :             :                     else
     704                 :             :                     {
     705         [ #  # ]:           0 :                         if (nLenDfsPath < nCycleLen)
     706                 :             :                         {
     707                 :             :                             /*  advance */
     708                 :           0 :                             nLenDfsPath++;
     709                 :           0 :                             cur_at = nxt_at;
     710                 :           0 :                             DfsPath[nLenDfsPath].at_no = cur_at;
     711                 :           0 :                             DfsPath[nLenDfsPath].bond_type = 0;
     712                 :           0 :                             DfsPath[nLenDfsPath].bond_pos = -1;
     713                 :           0 :                             nDfsPathPos[cur_at] = nLenDfsPath + 1;  /*  mark */
     714                 :             :                         }
     715                 :             :                     }
     716                 :             :                 }
     717                 :             :             }
     718                 :             :         }
     719                 :             :         else
     720                 :             :         {
     721                 :             :             /*  retract */
     722                 :           0 :             nDfsPathPos[(int) DfsPath[nLenDfsPath].at_no] = 0;
     723                 :           0 :             nLenDfsPath--;
     724                 :             :         }
     725                 :             :     }
     726                 :             : 
     727                 :           0 : clear_path:
     728         [ #  # ]:           0 :     while (0 <= nLenDfsPath)
     729                 :             :     {
     730                 :           0 :         nDfsPathPos[(int) DfsPath[nLenDfsPath].at_no] = 0;
     731                 :           0 :         nLenDfsPath--;
     732                 :             :     }
     733                 :             : 
     734                 :           0 :     return nNumFound;
     735                 :             : }
     736                 :             : 
     737                 :             : #endif /* TAUT_15_NON_RING */
     738                 :             : 
     739                 :             : 
     740                 :             : /****************************************************************************
     741                 :             :       Check if bonds are alternating
     742                 :             : ****************************************************************************/
     743                 :           0 : int are_alt_bonds( U_CHAR *bonds, int len )
     744                 :             : {
     745                 :             :     U_CHAR next_bond;
     746                 :           0 :     int           i, bAnyBond, bTautBondPresent = BOND_ALTERN;
     747   [ #  #  #  #  :           0 :     if (len < 2 || bonds[0] == BOND_TRIPLE || bonds[0] == BOND_ALT_13)
                   #  # ]
     748                 :             :     {
     749                 :           0 :         return 0;
     750                 :             :     }
     751         [ #  # ]:           0 :     next_bond = bonds[0] == BOND_SINGLE ? BOND_DOUBLE : bonds[0] == BOND_DOUBLE ? BOND_SINGLE : 0; /* djb-rwth: removing redundant code; ignoring LLVM warning: possible presence of global variables */
     752         [ #  # ]:           0 :     if (bonds[0] == BOND_TAUTOM)
     753                 :             :     {
     754                 :           0 :         bTautBondPresent = BOND_TAUTOM;
     755                 :           0 :         next_bond = 0;
     756                 :             :     }
     757                 :             :     else
     758                 :             :     {
     759         [ #  # ]:           0 :         next_bond = bonds[0] == BOND_SINGLE ? BOND_DOUBLE : bonds[0] == BOND_DOUBLE ? BOND_SINGLE : 0;
     760                 :             :     }
     761                 :             : 
     762         [ #  # ]:           0 :     for (i = 1; i < len; i++)
     763                 :             :     {
     764         [ #  # ]:           0 :         if (bonds[i] == BOND_TAUTOM)
     765                 :             :         {
     766                 :           0 :             bTautBondPresent = BOND_TAUTOM;
     767                 :           0 :             bAnyBond = 1;
     768                 :             :         }
     769                 :             :         else
     770                 :             :         {
     771   [ #  #  #  # ]:           0 :             bAnyBond = ( bonds[i] == BOND_ALTERN || bonds[i] == BOND_ALT12NS );
     772                 :             :         }
     773         [ #  # ]:           0 :         if (next_bond)
     774                 :             :         {
     775   [ #  #  #  # ]:           0 :             if (bonds[i] == next_bond || bAnyBond)
     776                 :             :             {
     777         [ #  # ]:           0 :                 next_bond = ( next_bond == BOND_SINGLE ) ? BOND_DOUBLE : BOND_SINGLE;
     778                 :           0 :                 continue;
     779                 :             :             }
     780                 :           0 :             return 0;
     781                 :             :         }
     782                 :             :         else
     783                 :             :         {
     784         [ #  # ]:           0 :             if (bonds[i] == BOND_SINGLE)
     785                 :             :             {
     786                 :           0 :                 next_bond = BOND_DOUBLE;
     787                 :           0 :                 continue;
     788                 :             :             }
     789                 :             :             else
     790                 :             :             {
     791         [ #  # ]:           0 :                 if (bonds[i] == BOND_DOUBLE)
     792                 :             :                 {
     793                 :           0 :                     next_bond = BOND_SINGLE;
     794                 :           0 :                     continue;
     795                 :             :                 }
     796                 :             :                 else
     797                 :             :                 {
     798         [ #  # ]:           0 :                     if (!bAnyBond)
     799                 :             :                     {
     800                 :           0 :                         return 0;
     801                 :             :                     }
     802                 :             :                 }
     803                 :             :             }
     804                 :             :         }
     805                 :             :     }
     806         [ #  # ]:           0 :     return !next_bond ? bTautBondPresent : ( next_bond == BOND_SINGLE )
     807         [ #  # ]:           0 :                             ? BOND_DOUBLE : BOND_SINGLE; /* bond to the end atom */
     808                 :             : }
     809                 :             : 
     810                 :             : /****************************************************************************/
     811                 :           0 : int AddBondsPos( inp_ATOM *atom,
     812                 :             :                  T_BONDPOS *BondPosTmp,
     813                 :             :                  int nNumBondPosTmp,
     814                 :             :                  T_BONDPOS *BondPos,
     815                 :             :                  int nMaxNumBondPos,
     816                 :             :                  int nNumBondPos )
     817                 :             : {
     818                 :             :     int i, j, k, cur_at, nxt_at;
     819                 :             :     /*  add opposite direction bonds to BondPosTmp */
     820         [ #  # ]:           0 :     for (j = 0; j < nNumBondPosTmp; j += 2)
     821                 :             :     {
     822                 :           0 :         cur_at = BondPosTmp[j].nAtomNumber;
     823                 :           0 :         nxt_at = atom[cur_at].neighbor[(int) BondPosTmp[j].neighbor_index];
     824         [ #  # ]:           0 :         for (k = 0; k < atom[nxt_at].valence; k++)
     825                 :             :         {
     826         [ #  # ]:           0 :             if (cur_at == atom[nxt_at].neighbor[k])
     827                 :             :             {
     828                 :           0 :                 BondPosTmp[j + 1].nAtomNumber = nxt_at;
     829                 :           0 :                 BondPosTmp[j + 1].neighbor_index = k;
     830                 :           0 :                 break;
     831                 :             :             }
     832                 :             :         }
     833                 :             :     }
     834                 :             :     /*  add new tautomeric bonds */
     835         [ #  # ]:           0 :     for (j = 0; j < nNumBondPosTmp; j += 2)
     836                 :             :     {
     837         [ #  # ]:           0 :         for (i = 0; i < nNumBondPos; i++)
     838                 :             :         {
     839         [ #  # ]:           0 :             if ((BondPos[i].nAtomNumber == BondPosTmp[j].nAtomNumber &&
     840         [ #  # ]:           0 :                 BondPos[i].neighbor_index == BondPosTmp[j].neighbor_index) ||
     841         [ #  # ]:           0 :                 (BondPos[i].nAtomNumber == BondPosTmp[j + 1].nAtomNumber &&
     842         [ #  # ]:           0 :                 BondPos[i].neighbor_index == BondPosTmp[j + 1].neighbor_index))  /* djb-rwth: addressing LLVM warnings */
     843                 :             :             {
     844                 :             :                 break; /*  bond has already been added */
     845                 :             :             }
     846                 :             :         }
     847         [ #  # ]:           0 :         if (i == nNumBondPos)
     848                 :             :         {
     849         [ #  # ]:           0 :             if (i > nMaxNumBondPos)
     850                 :             :             {
     851                 :           0 :                 return -1; /*  overflow */
     852                 :             :             }
     853                 :           0 :             BondPos[nNumBondPos++] = BondPosTmp[j];
     854                 :             :         }
     855                 :             :     }
     856                 :             : 
     857                 :           0 :     return nNumBondPos;
     858                 :             : }
     859                 :             : 
     860                 :             : 
     861                 :             : /****************************************************************************/
     862                 :           0 : int AddEndPoints( T_ENDPOINT *EndPointTmp,
     863                 :             :                   int nNumNewEndPoint,
     864                 :             :                   T_ENDPOINT *EndPoint,
     865                 :             :                   int nMaxNumEndPoint,
     866                 :             :                   int nNumEndPoint )
     867                 :             : {
     868                 :             :     int i, j;
     869                 :             :     /*  add new endpoints */
     870         [ #  # ]:           0 :     for (j = 0; j < nNumNewEndPoint; j++)
     871                 :             :     {
     872         [ #  # ]:           0 :         for (i = 0; i < nNumEndPoint; i++)
     873                 :             :         {
     874         [ #  # ]:           0 :             if (EndPoint[i].nAtomNumber == EndPointTmp[j].nAtomNumber)
     875                 :             :             {
     876                 :           0 :                 break;
     877                 :             :             }
     878                 :             :         }
     879         [ #  # ]:           0 :         if (i == nNumEndPoint)
     880                 :             :         {
     881         [ #  # ]:           0 :             if (i > nMaxNumEndPoint)
     882                 :             :             {
     883                 :           0 :                 return -1; /*  overflow */
     884                 :             :             }
     885                 :           0 :             EndPoint[nNumEndPoint++] = EndPointTmp[j];
     886                 :             :         }
     887                 :             :     }
     888                 :             : 
     889                 :           0 :     return nNumEndPoint;
     890                 :             : }
     891                 :             : 
     892                 :             : 
     893                 :             : /****************************************************************************/
     894                 :             : /*
     895                 :             : 
     896                 :             :   1,4 tautomerism in 7-member ring
     897                 :             : 
     898                 :             :       /C==D             //C-D          A=DfsPath[0].at_no
     899                 :             :    O=B     \        HO-B     \\        B=DfsPath[1].at_no
     900                 :             :      |      E  <->     |      E        nStartAtomNeighbor2:        from A to HO
     901                 :             :   HO-A     //        O=A     /         nStartAtomNeighborNeighbor: from B to O
     902                 :             :       \\G-F             \\G-F
     903                 :             : 
     904                 :             : 
     905                 :             :   1,4 tautomerism in 5-member ring
     906                 :             : 
     907                 :             : 
     908                 :             :    O=B--C            O-B==C
     909                 :             :      |   \\            |   \
     910                 :             :      |     D  <->      |     D
     911                 :             :      |   /             |   //
     912                 :             :   HO-A==E           HO=A--E
     913                 :             : 
     914                 :             : */
     915                 :             : /****************************************************************************/
     916                 :           0 : int Check7MembTautRing( struct tagCANON_GLOBALS *pCG,
     917                 :             :                         inp_ATOM *atom,
     918                 :             :                         DFS_PATH *DfsPath,
     919                 :             :                         int nLenDfsPath,
     920                 :             :                         int nStartAtomNeighbor,
     921                 :             :                         int nStartAtomNeighbor2,
     922                 :             :                         int nStartAtomNeighborNeighbor,
     923                 :             :                         T_ENDPOINT *EndPoint,
     924                 :             :                         int nMaxNumEndPoint,
     925                 :             :                         T_BONDPOS  *BondPos,
     926                 :             :                         int nMaxNumBondPos,
     927                 :             :                         int *pnNumEndPoint,
     928                 :             :                         int *pnNumBondPos,
     929                 :             :                         struct BalancedNetworkStructure *pBNS,
     930                 :             :                         struct BalancedNetworkData *pBD,
     931                 :             :                         int num_atoms )
     932                 :             : {
     933                 :             : #define PATH_LEN 8
     934                 :             : 
     935                 :             :     int i, j, k, /*m,*/ nNumEndPoint, nNumEndPointTmp, nNumBondPos, nNumBondPosTmp;
     936                 :             :     int endpoint, /*nMobile, nMobile1, nMobile2,*/ o1_at, o2_at;
     937                 :             :     int ret;
     938                 :             :     U_CHAR path_bonds[PATH_LEN + 1], bond_type;
     939                 :             :     T_ENDPOINT EndPointTmp[2];
     940                 :             :     T_BONDPOS  BondPosTmp[2 * PATH_LEN];
     941                 :             :     ENDPOINT_INFO eif1, eif2;
     942                 :           0 :     int nErr = 0;
     943                 :             : 
     944                 :             : 
     945         [ #  # ]:           0 :     if (nLenDfsPath + 2 > PATH_LEN)
     946                 :             :     {
     947                 :           0 :         return -1; /*  too long path */
     948                 :             :     }
     949   [ #  #  #  # ]:           0 :     if (nLenDfsPath != 6 && nLenDfsPath != 4)
     950                 :             :     {
     951                 :           0 :         return -1; /*  wrong call */
     952                 :             :     }
     953                 :             : 
     954                 :           0 :     nNumBondPos = *pnNumBondPos;
     955                 :           0 :     nNumEndPoint = *pnNumEndPoint;
     956                 :           0 :     nNumBondPosTmp = 0;
     957                 :           0 :     nNumEndPointTmp = 0;
     958                 :           0 :     ret = 0;
     959                 :             : 
     960                 :           0 :     o1_at = atom[(int) DfsPath[1].at_no].neighbor[nStartAtomNeighborNeighbor];
     961                 :           0 :     o2_at = atom[(int) DfsPath[0].at_no].neighbor[nStartAtomNeighbor2];
     962                 :             :     /*
     963                 :             :     nMobile1 = (atom[o1_at].charge == -1) + atom[o1_at].num_H;
     964                 :             :     nMobile2 = (atom[o2_at].charge == -1) + atom[o2_at].num_H;
     965                 :             :     */
     966   [ #  #  #  # ]:           0 :     if (!nGetEndpointInfo( atom, o1_at, &eif1 ) ||
     967                 :           0 :         !nGetEndpointInfo( atom, o2_at, &eif2 ))
     968                 :             :     {
     969                 :           0 :         return 0;
     970                 :             :     }
     971                 :             : 
     972                 :             :     /*  save endpoints */
     973         [ #  # ]:           0 :     for (j = 0; j < 2; j++)
     974                 :             :     {
     975         [ #  # ]:           0 :         endpoint = j ? o2_at : o1_at;
     976         [ #  # ]:           0 :         if (!atom[endpoint].endpoint)
     977                 :             :         {
     978                 :           0 :             AddAtom2num( EndPointTmp[nNumEndPointTmp].num, atom, endpoint, 2 ); /* fill out */
     979                 :           0 :             AddAtom2DA( EndPointTmp[nNumEndPointTmp].num_DA, atom, endpoint, 2 );
     980                 :             :             /*
     981                 :             :                    nMobile  = j? nMobile2 : nMobile1;
     982                 :             :                } else {
     983                 :             :                    nMobile  = 0;
     984                 :             :                }
     985                 :             :                if ( nMobile ) {
     986                 :             :                    EndPointTmp[nNumEndPointTmp].num[1] = (atom[endpoint].charge == -1);
     987                 :             :                    EndPointTmp[nNumEndPointTmp].num[0] = nMobile;
     988                 :             :                    for ( m = 0; m < T_NUM_ISOTOPIC; m ++ ) {
     989                 :             :                        EndPointTmp[nNumEndPointTmp].num[T_NUM_NO_ISOTOPIC+m] = atom[endpoint].num_iso_H[NUM_H_ISOTOPES-m-1];
     990                 :             :                    }
     991                 :             :             */
     992                 :             :         }
     993                 :             :         else
     994                 :             :         {
     995                 :           0 :             memset( EndPointTmp + nNumEndPointTmp, 0, sizeof( EndPointTmp[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     996                 :             :         }
     997                 :           0 :         EndPointTmp[nNumEndPointTmp].nAtomNumber = endpoint;
     998                 :           0 :         EndPointTmp[nNumEndPointTmp].nGroupNumber = atom[endpoint].endpoint;
     999                 :           0 :         EndPointTmp[nNumEndPointTmp].nEquNumber = 0;
    1000                 :           0 :         nNumEndPointTmp++;
    1001                 :             :     }
    1002                 :             : 
    1003                 :             :     /*  extract bonds */
    1004                 :           0 :     k = (int) DfsPath[1].at_no;
    1005                 :           0 :     bond_type = ( atom[k].bond_type[nStartAtomNeighborNeighbor] & ~BOND_MARK_ALL );
    1006                 :             : #if ( FIX_BOND23_IN_TAUT == 1 )
    1007                 :             :     bond_type = ACTUAL_ORDER( pBNS, k, nStartAtomNeighborNeighbor, bond_type );
    1008                 :             : #endif
    1009                 :           0 :     path_bonds[0] = bond_type;
    1010   [ #  #  #  #  :           0 :     if (REPLACE_THE_BOND( bond_type ))
             #  #  #  # ]
    1011                 :             :     {
    1012                 :           0 :         BondPosTmp[nNumBondPosTmp].nAtomNumber = k;
    1013                 :           0 :         BondPosTmp[nNumBondPosTmp].neighbor_index = nStartAtomNeighborNeighbor;
    1014                 :           0 :         nNumBondPosTmp += 2;
    1015                 :             :     }
    1016         [ #  # ]:           0 :     for (i = 1; i <= nLenDfsPath; i++)
    1017                 :             :     {
    1018                 :           0 :         bond_type = DfsPath[i].bond_type;
    1019                 :           0 :         path_bonds[i] = bond_type;
    1020   [ #  #  #  #  :           0 :         if (REPLACE_THE_BOND( bond_type ))
             #  #  #  # ]
    1021                 :             :         {
    1022                 :           0 :             BondPosTmp[nNumBondPosTmp].nAtomNumber = DfsPath[i].at_no;
    1023                 :           0 :             BondPosTmp[nNumBondPosTmp].neighbor_index = DfsPath[i].bond_pos;
    1024                 :           0 :             nNumBondPosTmp += 2;
    1025                 :             :         }
    1026                 :             :     }
    1027                 :           0 :     bond_type = ( atom[(int) DfsPath[0].at_no].bond_type[nStartAtomNeighbor2] & ~BOND_MARK_ALL );
    1028                 :             : #if ( FIX_BOND23_IN_TAUT == 1 )
    1029                 :             :     bond_type = ACTUAL_ORDER( pBNS, (int) DfsPath[0].at_no, nStartAtomNeighbor2, bond_type );
    1030                 :             : #endif
    1031                 :           0 :     path_bonds[i++] = bond_type;
    1032   [ #  #  #  #  :           0 :     if (REPLACE_THE_BOND( bond_type ))
             #  #  #  # ]
    1033                 :             :     {
    1034                 :           0 :         BondPosTmp[nNumBondPosTmp].nAtomNumber = DfsPath[0].at_no;
    1035                 :           0 :         BondPosTmp[nNumBondPosTmp].neighbor_index = nStartAtomNeighbor2;
    1036                 :           0 :         nNumBondPosTmp += 2;
    1037                 :             :     }
    1038                 :             : 
    1039         [ #  # ]:           0 :     if (!are_alt_bonds( path_bonds, i ))
    1040                 :             :     {
    1041                 :           0 :         return 0;
    1042                 :             :     }
    1043                 :             : 
    1044                 :             :     /* path_bonds is from at_n1 to at_n2 */
    1045         [ #  # ]:           0 :     if (!( j = are_alt_bonds( path_bonds, i ) ))
    1046                 :             :     {
    1047                 :           0 :         return 0;
    1048                 :             :     }
    1049                 :             :     /* j is a bond type of the last bond to o2_at, the first bond from o1_at is 2-j if j=1 or 2 */
    1050                 :             : 
    1051                 :             :     /* single bond at o2_at: it should have a mobile atom, o1_at should not */
    1052   [ #  #  #  #  :           0 :     if ((j == BOND_SINGLE && ( (!atom[o2_at].endpoint && !eif2.cDonor) || (!atom[o1_at].endpoint && !eif1.cAcceptor) )) ||
          #  #  #  #  #  
                #  #  # ]
    1053                 :             :         /* double bond at o2_at: it should not have a mobile atom, o1_at should */
    1054   [ #  #  #  #  :           0 :         (j == BOND_DOUBLE && ( (!atom[o2_at].endpoint && !eif2.cAcceptor) || (!atom[o1_at].endpoint && !eif1.cDonor) ))) /* djb-rwth: addressing LLVM warnings */
             #  #  #  # ]
    1055                 :             :     {
    1056                 :           0 :         return 0; /* bond pattern does not fit */
    1057                 :             :     }
    1058                 :             : 
    1059                 :           0 :     nNumBondPos = AddBondsPos( atom, BondPosTmp, nNumBondPosTmp, BondPos, nMaxNumBondPos, nNumBondPos );
    1060                 :           0 :     nNumEndPoint = AddEndPoints( EndPointTmp, nNumEndPointTmp, EndPoint, nMaxNumEndPoint, nNumEndPoint );
    1061                 :             : 
    1062   [ #  #  #  # ]:           0 :     if (nNumBondPos >= 0 && nNumEndPoint >= 0)
    1063                 :             :     {
    1064   [ #  #  #  #  :           0 :         if ((ret = ( nNumBondPos > *pnNumBondPos ) || ( nNumEndPoint > *pnNumEndPoint ))) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    1065                 :             :         {
    1066                 :           0 :             *pnNumBondPos = nNumBondPos;
    1067                 :           0 :             *pnNumEndPoint = nNumEndPoint;
    1068                 :             :         }
    1069                 :             :     }
    1070                 :             : 
    1071         [ #  # ]:           0 :     if (ret)
    1072                 :             :     {
    1073                 :             :         /* finally check whether the bonds allow moving the hydrogens */
    1074   [ #  #  #  # ]:           0 :         if (( atom[o1_at].endpoint != atom[o2_at].endpoint || !atom[o1_at].endpoint ))
    1075                 :             :         {
    1076                 :             : 
    1077                 :           0 :             nErr = bExistsAnyAltPath( pCG, pBNS, pBD, atom, num_atoms, o1_at, o2_at, ALT_PATH_MODE_TAUTOM );
    1078                 :             : 
    1079         [ #  # ]:           0 :             if (nErr <= 0)
    1080                 :             :             {
    1081                 :           0 :                 return nErr;
    1082                 :             :             }
    1083                 :             :         }
    1084                 :             :     }
    1085                 :             : 
    1086                 :           0 :     return ret;
    1087                 :             : 
    1088                 :             : 
    1089                 :             : #undef PATH_LEN
    1090                 :             : }
    1091                 :             : 
    1092                 :             : 
    1093                 :             : /****************************************************************************/
    1094                 :             : /*
    1095                 :             :   1,5 Tautomerism in 6-member alt ring:
    1096                 :             : 
    1097                 :             :    /=\          /==\          N = DfsPath[0].at_no
    1098                 :             :  HN   C=O  <-> N    C-OH      C = DfsPath[3].at_no
    1099                 :             :    \=/          \\-//
    1100                 :             : 
    1101                 :             : */
    1102                 :             : /****************************************************************************/
    1103                 :             : 
    1104                 :             : /****************************************************************************
    1105                 :             :   Check if a tautomeric 6-member ring has been found
    1106                 :             : *****************************************************************************/
    1107                 :           0 : int Check6MembTautRing( struct tagCANON_GLOBALS *pCG,
    1108                 :             :                         inp_ATOM *atom,
    1109                 :             :                         DFS_PATH *DfsPath,
    1110                 :             :                         int nLenDfsPath,
    1111                 :             :                         int nStartAtomNeighbor,
    1112                 :             :                         int nStartAtomNeighbor2,
    1113                 :             :                         int nStartAtomNeighborNeighbor,
    1114                 :             :                         T_ENDPOINT *EndPoint,
    1115                 :             :                         int nMaxNumEndPoint,
    1116                 :             :                         T_BONDPOS  *BondPos,
    1117                 :             :                         int nMaxNumBondPos,
    1118                 :             :                         int *pnNumEndPoint,
    1119                 :             :                         int *pnNumBondPos,
    1120                 :             :                         struct BalancedNetworkStructure *pBNS,
    1121                 :             :                         struct BalancedNetworkData *pBD,
    1122                 :             :                         int num_atoms )
    1123                 :             : {
    1124                 :             : #define PATH_LEN 4
    1125                 :             :     int i, j, k, /*m,*/ nNumBondPos, nNumEndPoint, ept, eptn;
    1126                 :           0 :     int nNumEndPointTmp, nNumBondPosTmp, o_at = 0, ret;
    1127                 :             :     /* int num_taut_endpoints, num_H; */
    1128                 :             :     int middle_pos;
    1129                 :             :     int nMobile, endpoint, endpoint_valence, chem_bonds_valence;
    1130                 :             :     int nMobile1, endpoint_valence1;  /*  o_at */
    1131                 :             :     int nMobile2, endpoint_valence2;  /*  n_at */
    1132                 :             :     int nxt_at;
    1133                 :             :     int n_at;
    1134                 :             :     U_CHAR path_bonds[2][PATH_LEN + 1], bond_type;
    1135                 :             :     T_ENDPOINT EndPointTmp[2];
    1136                 :             :     T_BONDPOS  BondPosTmp[4 * PATH_LEN];
    1137                 :             :     ENDPOINT_INFO eif1, eif2;
    1138                 :             : 
    1139   [ #  #  #  #  :           0 :     if (nStartAtomNeighbor >= 0 || nStartAtomNeighbor2 >= 0 || nStartAtomNeighborNeighbor >= 0)
                   #  # ]
    1140                 :             :     {
    1141                 :           0 :         return -1; /*  wrong call */
    1142                 :             :     }
    1143         [ #  # ]:           0 :     if (nLenDfsPath != 5)
    1144                 :             :     {
    1145                 :           0 :         return -1; /*  wrong call */
    1146                 :             :     }
    1147                 :             : 
    1148                 :           0 :     nNumBondPos = *pnNumBondPos;
    1149                 :           0 :     nNumEndPoint = *pnNumEndPoint;
    1150                 :             :     /* djb-rwth: removing redundant code */
    1151                 :           0 :     nNumEndPointTmp = 0;
    1152                 :           0 :     ret = 0;
    1153         [ #  # ]:           0 :     for (ept = 0; ept < 2; ept++) /* djb-rwth: initialisation needed for num array */
    1154         [ #  # ]:           0 :         for (eptn = 0; eptn < T_NUM_NO_ISOTOPIC + T_NUM_ISOTOPIC; eptn++)
    1155                 :           0 :             EndPointTmp[ept].num[eptn] = 0;
    1156                 :             : 
    1157                 :           0 :     n_at = (int) DfsPath[0].at_no;   /*  -N= or -NH- atom */
    1158                 :           0 :     nxt_at = DfsPath[middle_pos = ( nLenDfsPath + 1 ) / 2].at_no;  /*  must have tautomeric neighbor -OH or =O or -NH2 or =NH */
    1159                 :             : 
    1160         [ #  # ]:           0 :     if (atom[nxt_at].valence != 3
    1161                 :             : #if ( TAUT_RINGS_ATTACH_CHAIN == 1 )
    1162         [ #  # ]:           0 :         || !atom[nxt_at].bCutVertex
    1163                 :             : #endif
    1164                 :             :         )
    1165                 :             :     {
    1166                 :           0 :         return 0;
    1167                 :             :     }
    1168                 :             : 
    1169         [ #  # ]:           0 :     for (i = 0; i < atom[nxt_at].valence; i++)
    1170                 :             :     {
    1171                 :           0 :         o_at = atom[nxt_at].neighbor[i];
    1172   [ #  #  #  # ]:           0 :         if (o_at != DfsPath[middle_pos - 1].at_no && o_at != DfsPath[middle_pos + 1].at_no)
    1173                 :             :         {
    1174                 :           0 :             break; /*  >=O or />-OH has been found */
    1175                 :             :         }
    1176                 :             :     }
    1177         [ #  # ]:           0 :     if (i == atom[nxt_at].valence)
    1178                 :             :     {
    1179                 :           0 :         return 0; /*  no neighboring atom >=O or />-OH */
    1180                 :             :     }
    1181                 :           0 :     bond_type = ( atom[nxt_at].bond_type[i] & ~BOND_MARK_ALL );
    1182                 :             : #if ( FIX_BOND23_IN_TAUT == 1 )
    1183                 :             :     bond_type = ACTUAL_ORDER( pBNS, nxt_at, i, bond_type );
    1184                 :             : #endif
    1185   [ #  #  #  # ]:           0 :     if (bond_type != BOND_SINGLE &&
    1186         [ #  # ]:           0 :         bond_type != BOND_DOUBLE &&
    1187         [ #  # ]:           0 :         bond_type != BOND_TAUTOM &&
    1188         [ #  # ]:           0 :         bond_type != BOND_ALT12NS &&
    1189                 :             :         bond_type != BOND_ALTERN)
    1190                 :             :     {
    1191                 :           0 :         return 0;
    1192                 :             :     }
    1193                 :             : 
    1194                 :             :     /*  check whether the two atoms already belong to one tautomeric group */
    1195                 :             : #if ( TAUT_IGNORE_EQL_ENDPOINTS == 1 )
    1196                 :             :     if (atom[n_at].endpoint && atom[n_at].endpoint == atom[o_at].endpoint)
    1197                 :             :     {
    1198                 :             :         return 0;
    1199                 :             :     }
    1200                 :             : #endif
    1201                 :             :     /*  check =O valence; must be 2 for O, S, Se or 3 for N */
    1202         [ #  # ]:           0 :     if (!( endpoint_valence1 = nGetEndpointInfo( atom, o_at, &eif1 ) ))
    1203                 :             :     {
    1204                 :           0 :         return 0; /*  n_at has been checked in MarkTautomerGroups(...) */
    1205                 :             :     }
    1206                 :             :     /*
    1207                 :             :         if ( 2 != endpoint_valence1 )
    1208                 :             :             return 0; // accept only O, S, Se
    1209                 :             :     */
    1210                 :             :     /*  check hydrogens/endpoints */
    1211                 :           0 :     nMobile1 = atom[o_at].num_H + ( atom[o_at].charge == -1 );
    1212   [ #  #  #  #  :           0 :     if (bond_type == BOND_SINGLE && !eif1.cDonor && !atom[o_at].endpoint)
                   #  # ]
    1213                 :             :     {
    1214                 :           0 :         return 0;
    1215                 :             :     }
    1216                 :             :     /* not needed since nGetEndpointInfo returned non-zero
    1217                 :             :     if ( nMobile1 + atom[o_at].chem_bonds_valence != endpoint_valence1 )
    1218                 :             :         return 0;
    1219                 :             :     */
    1220                 :             : 
    1221         [ #  # ]:           0 :     if (!( endpoint_valence2 = nGetEndpointInfo( atom, n_at, &eif2 ) ))
    1222                 :             :     {
    1223                 :           0 :         return 0; /* should not happen here */
    1224                 :             :     }
    1225                 :           0 :     nMobile2 = atom[n_at].num_H + ( atom[n_at].charge == -1 );
    1226                 :             : 
    1227                 :           0 :     nMobile = 0;
    1228                 :             : 
    1229                 :             :     /*  can mobile group move from o_at to n_at? */
    1230   [ #  #  #  # ]:           0 :     nMobile += ( atom[o_at].endpoint || eif1.cDonor ) &&  /*  from o_at */
    1231         [ #  # ]:           0 :         bond_type != BOND_DOUBLE &&
    1232         [ #  # ]:           0 :         ( atom[n_at].endpoint ||                   /*  to n_at */
    1233         [ #  # ]:           0 :             eif2.cNeutralBondsValence > atom[n_at].valence );
    1234                 :             :     /*  can mobile group move from n_at to o_at? */
    1235         [ #  # ]:           0 :     nMobile += ( atom[n_at].endpoint || eif2.cDonor ) && /*  from n_at */
    1236         [ #  # ]:           0 :         ( atom[o_at].endpoint ||          /*  to o_at */
    1237   [ #  #  #  #  :           0 :             eif1.cNeutralBondsValence > atom[o_at].valence ) &&
                   #  # ]
    1238                 :             :         bond_type != BOND_SINGLE;
    1239                 :             : 
    1240                 :             : 
    1241         [ #  # ]:           0 :     if (!nMobile)
    1242                 :             :     {
    1243                 :           0 :         return 0;
    1244                 :             :     }
    1245                 :             : 
    1246                 :             :     /*
    1247                 :             :     num_H = atom[n_at].num_H + atom[o_at].num_H;
    1248                 :             :     num_taut_endpoints = (0!=atom[n_at].endpoint) + (0!=atom[o_at].endpoint); // if O, N already are endpoints
    1249                 :             :     if ( num_H != 1 && num_taut_endpoints != 2 && !(num_H==2 && num_taut_endpoints >= 1) ) {
    1250                 :             :         return 0;
    1251                 :             :     }
    1252                 :             :     */
    1253                 :             :     /*  extract -OH bond */
    1254                 :           0 :     nNumBondPosTmp = 0;
    1255                 :             : 
    1256                 :           0 :     path_bonds[0][0] = path_bonds[1][0] = bond_type;
    1257   [ #  #  #  #  :           0 :     if (REPLACE_THE_BOND( bond_type ))
             #  #  #  # ]
    1258                 :             :     {
    1259                 :           0 :         BondPosTmp[nNumBondPosTmp].nAtomNumber = nxt_at; /*  accumulate bonds to be */
    1260                 :           0 :         BondPosTmp[nNumBondPosTmp].neighbor_index = i;   /*  marked as tautomeric */
    1261                 :           0 :         nNumBondPosTmp += 2; /*  leave room for the same bond in the opposite direction */
    1262                 :             :     }
    1263                 :             : 
    1264                 :             :     /*  extract other bonds */
    1265                 :             :     /* path_bonds[] contents:
    1266                 :             : 
    1267                 :             : 
    1268                 :             :                     O              OH            OH
    1269                 :             :                     ||             |             |
    1270                 :             :                    /  \          //  \          /  \\
    1271                 :             :                   ||   ||  <-->  |   ||  <-->  ||   |
    1272                 :             :                    \  /          \\  /          \  //
    1273                 :             :                     NH             N             N
    1274                 :             : 
    1275                 :             :         path[0]:  O=NH-=-      OH-N...         OH.N...
    1276                 :             :         path[1]   O=NH-=-      OH-N...         OH.N...
    1277                 :             :                  bonds are    all bonds       all bonds
    1278                 :             :                  single and   are either      are either
    1279                 :             :                  double       alt or taut     alt or taut
    1280                 :             :     */
    1281         [ #  # ]:           0 :     for (j = 0; j < middle_pos; j++)
    1282                 :             :     {
    1283         [ #  # ]:           0 :         for (i = 0; i < 2; i++)
    1284                 :             :         {
    1285                 :             :             /* k = i? j : middle_pos-1-j; */
    1286         [ #  # ]:           0 :             k = i ? middle_pos + j : middle_pos - 1 - j;
    1287                 :             :             /*  i=0: from O neighbor i=0: down to N, i=1: up to N */
    1288                 :           0 :             bond_type = DfsPath[k].bond_type;
    1289                 :             : 
    1290                 :           0 :             path_bonds[i][j + 1] = bond_type;
    1291   [ #  #  #  #  :           0 :             if (REPLACE_THE_BOND( bond_type ))
             #  #  #  # ]
    1292                 :             :             {
    1293                 :           0 :                 BondPosTmp[nNumBondPosTmp].nAtomNumber = DfsPath[k].at_no;       /*  accumulate bonds to be */
    1294                 :           0 :                 BondPosTmp[nNumBondPosTmp].neighbor_index = DfsPath[k].bond_pos; /*  marked as tautomeric */
    1295                 :           0 :                 nNumBondPosTmp += 2;   /*  leave room for the same bond in the opposite direction */
    1296                 :             :             }
    1297                 :             :         }
    1298                 :             :     }
    1299                 :             : 
    1300   [ #  #  #  # ]:           0 :     if (!are_alt_bonds( path_bonds[0], middle_pos + 1 ) || !are_alt_bonds( path_bonds[1], middle_pos + 1 ))
    1301                 :             :     {
    1302                 :           0 :         return 0;
    1303                 :             :     }
    1304                 :             : 
    1305                 :             :     /* finally check whether the bonds allow moving the hydrogens */
    1306   [ #  #  #  # ]:           0 :     if (( atom[o_at].endpoint != atom[n_at].endpoint || !atom[o_at].endpoint ))
    1307                 :             :     {
    1308                 :             :         int nErr;
    1309                 :           0 :         nErr = bExistsAnyAltPath( pCG, pBNS, pBD, atom, num_atoms, n_at, o_at, ALT_PATH_MODE_TAUTOM );
    1310         [ #  # ]:           0 :         if (nErr <= 0)
    1311                 :             :         {
    1312                 :           0 :             return nErr;
    1313                 :             :         }
    1314                 :             :     }
    1315                 :             : 
    1316                 :             :     /*  save endpoints */
    1317         [ #  # ]:           0 :     for (j = 0; j < 2; j++)
    1318                 :             :     {
    1319         [ #  # ]:           0 :         endpoint = j ? n_at :      /*  =N-  2 */
    1320                 :             :             o_at;       /*  -OH  1 */
    1321         [ #  # ]:           0 :         if (!atom[endpoint].endpoint)
    1322                 :             :         { /* not a known endpoint */
    1323         [ #  # ]:           0 :             endpoint_valence = j ? endpoint_valence2 : endpoint_valence1;
    1324         [ #  # ]:           0 :             chem_bonds_valence = j ? eif2.cNeutralBondsValence : eif1.cNeutralBondsValence;
    1325                 :             :             /* endpoint_valence = get_endpoint_valence( atom[endpoint].el_number ); */
    1326         [ #  # ]:           0 :             nMobile = j ? nMobile2 : nMobile1;
    1327                 :             :             /* nMobile  = (atom[endpoint].charge == -1) + atom[endpoint].num_H; */
    1328                 :             :             /* if ( nMobile + atom[endpoint].chem_bonds_valence != endpoint_valence ) -- fixed 02-06-2003*/
    1329         [ #  # ]:           0 :             if (nMobile + chem_bonds_valence != endpoint_valence)
    1330                 :           0 :                 return 0; /*  abnormal endpoint valence; ignore. */
    1331                 :           0 :             AddAtom2num( EndPointTmp[nNumEndPointTmp].num, atom, endpoint, 2 ); /* fill out */
    1332                 :           0 :             AddAtom2DA( EndPointTmp[nNumEndPointTmp].num_DA, atom, endpoint, 2 );
    1333                 :             :             /*
    1334                 :             :                         EndPointTmp[nNumEndPointTmp].num[1] = (atom[endpoint].charge == -1);
    1335                 :             :                         EndPointTmp[nNumEndPointTmp].num[0] = nMobile;
    1336                 :             :                         for ( m = 0; m < T_NUM_ISOTOPIC; m ++ ) {
    1337                 :             :                             EndPointTmp[nNumEndPointTmp].num[T_NUM_NO_ISOTOPIC+m] = atom[endpoint].num_iso_H[NUM_H_ISOTOPES-m-1];
    1338                 :             :                         }
    1339                 :             :             */
    1340                 :             :         }
    1341                 :             :         else
    1342                 :             :         { /* already an endpoint */ /* **now it is wrong:** no mobile atom/charge at this endpoint */
    1343                 :           0 :             memset( EndPointTmp + nNumEndPointTmp, 0, sizeof( EndPointTmp[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    1344                 :             :         }
    1345                 :           0 :         EndPointTmp[nNumEndPointTmp].nAtomNumber = endpoint;
    1346                 :           0 :         EndPointTmp[nNumEndPointTmp].nGroupNumber = atom[endpoint].endpoint;
    1347                 :           0 :         EndPointTmp[nNumEndPointTmp].nEquNumber = 0;
    1348                 :             : 
    1349                 :           0 :         nNumEndPointTmp++;
    1350                 :             :     }
    1351                 :             :     /*  add collected tautomeric bonds and endpoints to the input/output data */
    1352                 :           0 :     nNumBondPos = AddBondsPos( atom, BondPosTmp, nNumBondPosTmp, BondPos, nMaxNumBondPos, nNumBondPos );
    1353                 :           0 :     nNumEndPoint = AddEndPoints( EndPointTmp, nNumEndPointTmp, EndPoint, nMaxNumEndPoint, nNumEndPoint );
    1354                 :             : 
    1355   [ #  #  #  # ]:           0 :     if (nNumBondPos >= 0 && nNumEndPoint >= 0)
    1356                 :             :     {
    1357   [ #  #  #  #  :           0 :         if ((ret = ( nNumBondPos > *pnNumBondPos ) || ( nNumEndPoint > *pnNumEndPoint ))) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    1358                 :             :         {
    1359                 :           0 :             *pnNumBondPos = nNumBondPos;
    1360                 :           0 :             *pnNumEndPoint = nNumEndPoint;
    1361                 :             :         }
    1362                 :             :     }
    1363                 :             : 
    1364                 :           0 :     return ret;
    1365                 :             : #undef PATH_LEN
    1366                 :             : }
    1367                 :             : 
    1368                 :             : 
    1369                 :             : #if ( TAUT_15_NON_RING == 1 )  /* post v.1 feature */
    1370                 :             : 
    1371                 :             : /****************************************************************************
    1372                 :             : Check (1,5) taut alt path centerpoint (unfinished) [add path checking]
    1373                 :             : ****************************************************************************/
    1374                 :           0 : int Check15TautPathCenterpoint( inp_ATOM *atom, DFS_PATH *DfsPath, int nLenDfsPath, int jNxtNeigh,
    1375                 :             :     struct BalancedNetworkStructure *pBNS,
    1376                 :             :     struct BalancedNetworkData *pBD, int num_atoms )
    1377                 :             : {
    1378                 :           0 :     int nxt_at = atom[DfsPath[nLenDfsPath].at_no].neighbor[jNxtNeigh];
    1379                 :             :     /* atom[nxt_at].endpoint below allows for keto-enol -CH< or -CH2- endpoints  */
    1380   [ #  #  #  # ]:           0 :     return atom[nxt_at].endpoint || bIsCenterPointStrict( atom, nxt_at );
    1381                 :             : }
    1382                 :             : 
    1383                 :             : /****************************************************************************
    1384                 :             : 
    1385                 :             :   1,5 Tautomerism in general (unfinished) [just a copy from 6-memb case]
    1386                 :             : 
    1387                 :             :   AH--B==C--D==E             C may be carbon exhibiting keto-enol tautomerism
    1388                 :             :   0   1  2  3  4             as well as A or E may be previously detected such a carbon
    1389                 :             :             ^   nxt_at
    1390                 :             :             |
    1391                 :             :             +-- = nLenDfsPath
    1392                 :             : 
    1393                 :             : ****************************************************************************/
    1394                 :             : 
    1395                 :             : 
    1396                 :             : /****************************************************************************
    1397                 :             :   check if 1,5 tautomeric path has been found
    1398                 :             : ****************************************************************************/
    1399                 :           0 : int Check15TautPath( struct tagCANON_GLOBALS *pCG,
    1400                 :             :                      inp_ATOM *atom, DFS_PATH *DfsPath,
    1401                 :             :                      int nLenDfsPath,
    1402                 :             :                      int jNxtNeigh,
    1403                 :             :                      int nStartAtomNeighbor,
    1404                 :             :                      int nStartAtomNeighbor2,
    1405                 :             :                      int nStartAtomNeighborNeighbor,
    1406                 :             :                      T_ENDPOINT *EndPoint,
    1407                 :             :                      int nMaxNumEndPoint,
    1408                 :             :                      T_BONDPOS  *BondPos,
    1409                 :             :                      int nMaxNumBondPos,
    1410                 :             :                      int *pnNumEndPoint,
    1411                 :             :                      int *pnNumBondPos,
    1412                 :             :                      struct BalancedNetworkStructure *pBNS,
    1413                 :             :                      struct BalancedNetworkData *pBD,
    1414                 :             :                      int num_atoms )
    1415                 :             : {
    1416                 :             : #define PATH_LEN 4
    1417                 :             :     int i, j, k, /*m,*/ nNumBondPos, nNumEndPoint, cur_at, prv_at, at1, at2 /*, at3, step_at*/;
    1418                 :             :     int nNumEndPointTmp, nNumBondPosTmp, ret;
    1419                 :             :     /* int num_taut_endpoints, num_H; */
    1420                 :             :     int nMobile, endpoint, endpoint_valence, chem_bonds_valence;
    1421                 :             :     int nMobile1, endpoint_valence1;  /* start atom, at1 */
    1422                 :             :     int nMobile2, endpoint_valence2;  /* end atom,   at2 */
    1423                 :             :     /*int nMobile3, endpoint_valence3=-1;*/  /* middle atom, at3 */
    1424                 :             :     /*int nxt_at;*/
    1425                 :             :     int alt_bonds[2];
    1426                 :             :     U_CHAR /*path_bonds[2][PATH_LEN+1],*/ bond_type;
    1427                 :             :     T_ENDPOINT EndPointTmp[2];
    1428                 :             :     T_BONDPOS  BondPosTmp[4 * PATH_LEN];
    1429                 :             :     ENDPOINT_INFO eif1, eif2/*, eif3*/;
    1430                 :             : 
    1431   [ #  #  #  #  :           0 :     if (nStartAtomNeighbor >= 0 || nStartAtomNeighbor2 >= 0 || nStartAtomNeighborNeighbor >= 0)
                   #  # ]
    1432                 :             :     {
    1433                 :           0 :         return -1; /*  wrong call */
    1434                 :             :     }
    1435         [ #  # ]:           0 :     if (nLenDfsPath != 3)
    1436                 :             :     {
    1437                 :           0 :         return -1; /*  wrong call */
    1438                 :             :     }
    1439                 :             : 
    1440                 :           0 :     nNumBondPos = *pnNumBondPos;
    1441                 :           0 :     nNumEndPoint = *pnNumEndPoint;
    1442                 :             :     /* djb-rwth: removing redundant code */
    1443                 :           0 :     nNumEndPointTmp = 0;
    1444                 :           0 :     ret = 0;
    1445                 :             : 
    1446                 :             :     /*-------add the last atom, nLenDfsPath=4 --*/
    1447                 :           0 :     j = jNxtNeigh;
    1448                 :           0 :     prv_at = DfsPath[nLenDfsPath].at_no;
    1449                 :           0 :     cur_at = atom[prv_at].neighbor[j];
    1450                 :           0 :     DfsPath[nLenDfsPath].bond_type = ( atom[prv_at].bond_type[j] & ~BOND_MARK_ALL );
    1451                 :             : #if ( FIX_BOND23_IN_TAUT == 1 )
    1452                 :             :     DfsPath[nLenDfsPath].bond_type = ACTUAL_ORDER( pBNS, prv_at, j, DfsPath[nLenDfsPath].bond_type );
    1453                 :             : #endif
    1454                 :           0 :     DfsPath[nLenDfsPath].bond_pos = j; /* fix index of the bond to the next atom */
    1455                 :             : 
    1456                 :           0 :     nLenDfsPath++;
    1457                 :             : 
    1458                 :           0 :     DfsPath[nLenDfsPath].at_no = cur_at;
    1459                 :           0 :     DfsPath[nLenDfsPath].bond_type = 0;
    1460                 :           0 :     DfsPath[nLenDfsPath].bond_pos = -1;
    1461                 :             :     /*nDfsPathPos[cur_at]                = nLenDfsPath+1;*/ /* mark with distance + 1 */
    1462                 :             : /*------------------------------------------*/
    1463                 :           0 :     at1 = (int) DfsPath[0].at_no;
    1464                 :           0 :     at2 = (int) DfsPath[nLenDfsPath].at_no;
    1465                 :             :     /*at3 = (int)DfsPath[2].at_no;*/
    1466   [ #  #  #  # ]:           0 :     if (atom[at1].endpoint && atom[at1].endpoint == atom[at2].endpoint)
    1467                 :             :     {
    1468                 :             :         /* start & end already belong to the same taut group */
    1469                 :           0 :         goto exit_function;  /* nothing to do */
    1470                 :             :     }
    1471                 :             : 
    1472                 :             :     /* check bond types along alt path */
    1473                 :           0 :     alt_bonds[0] = alt_bonds[1] = 0;
    1474         [ #  # ]:           0 :     for (i = 0; i < nLenDfsPath; i++)
    1475                 :             :     {
    1476   [ #  #  #  #  :           0 :         alt_bonds[i % 2] |= IS_ALT_OR_DBLBOND( DfsPath[i].bond_type );
          #  #  #  #  #  
                      # ]
    1477                 :             :     }
    1478         [ #  # ]:           0 :     if (( alt_bonds[0] & alt_bonds[1] & ( BOND_SINGLE | BOND_DOUBLE ) ) ||
    1479   [ #  #  #  # ]:           0 :         ( alt_bonds[0] & BOND_WRONG ) || ( alt_bonds[1] & BOND_WRONG ))
    1480                 :             :     {
    1481                 :           0 :         goto exit_function; /* incompatible with alt path or wrong bonds */\
    1482                 :             :     }
    1483                 :             :     /* check possibly tautomeric endpoints at the ends */
    1484                 :           0 :     endpoint_valence1 = nGetEndpointInfo( atom, at1, &eif1 );
    1485                 :           0 :     endpoint_valence2 = nGetEndpointInfo( atom, at2, &eif2 );
    1486                 :             : #ifdef NEVER   /* do not use C-endpoint of keto-enol tautomer to find 1,5 the taut path */
    1487                 :             :     if (!endpoint_valence1 && !atom[at1].endpoint ||
    1488                 :             :         !endpoint_valence2 && !atom[at2].endpoint)
    1489                 :             :         goto exit_function; /* at least one of the end atoms cannot be an endpoint */
    1490                 :             : #endif
    1491   [ #  #  #  # ]:           0 :     if (!endpoint_valence1 || !endpoint_valence2)
    1492                 :           0 :         goto exit_function;  /* require both endpoints be heteroatoms */
    1493                 :             :     /*  check hydrogens/endpoints */
    1494                 :           0 :     nMobile1 = atom[at1].num_H + ( atom[at1].charge == -1 );
    1495         [ #  # ]:           0 :     if (!atom[at1].endpoint)
    1496                 :             :     {
    1497   [ #  #  #  # ]:           0 :         if (( alt_bonds[0] & BOND_SINGLE ) && !eif1.cDonor)
    1498                 :             :         {
    1499                 :           0 :             goto exit_function;
    1500                 :             :         }
    1501   [ #  #  #  # ]:           0 :         if (( alt_bonds[0] & BOND_DOUBLE ) && !eif1.cAcceptor)
    1502                 :             :         {
    1503                 :           0 :             goto exit_function;
    1504                 :             :         }
    1505                 :             :     }
    1506                 :           0 :     nMobile2 = atom[at2].num_H + ( atom[at2].charge == -1 );
    1507         [ #  # ]:           0 :     if (!atom[at2].endpoint)
    1508                 :             :     {
    1509   [ #  #  #  # ]:           0 :         if (( alt_bonds[1] & BOND_SINGLE ) && !eif2.cDonor)
    1510                 :             :         {
    1511                 :           0 :             goto exit_function;
    1512                 :             :         }
    1513   [ #  #  #  # ]:           0 :         if (( alt_bonds[1] & BOND_DOUBLE ) && !eif2.cAcceptor)
    1514                 :             :         {
    1515                 :           0 :             goto exit_function;
    1516                 :             :         }
    1517                 :             :     }
    1518                 :             : 
    1519                 :           0 :     nMobile = 0;
    1520                 :             : 
    1521                 :             :     /*  can mobile group move from at1=o_at to at2=n_at? */
    1522         [ #  # ]:           0 :     nMobile += ( atom[at1].endpoint || eif1.cDonor ) &&  /*  from o_at */
    1523   [ #  #  #  # ]:           0 :         !( alt_bonds[0] & BOND_DOUBLE ) &&
    1524         [ #  # ]:           0 :         ( atom[at2].endpoint ||                   /*  to n_at */
    1525         [ #  # ]:           0 :             eif2.cNeutralBondsValence > atom[at2].valence );
    1526                 :             :     /*  can mobile group move from at2=n_at to at1=o_at? */
    1527         [ #  # ]:           0 :     nMobile += ( atom[at2].endpoint || eif2.cDonor ) && /*  from n_at */
    1528   [ #  #  #  # ]:           0 :         !( alt_bonds[1] & BOND_DOUBLE ) &&
    1529         [ #  # ]:           0 :         ( atom[at1].endpoint ||          /*  to o_at */
    1530         [ #  # ]:           0 :             eif1.cNeutralBondsValence > atom[at1].valence );
    1531                 :             : 
    1532         [ #  # ]:           0 :     if (!nMobile)
    1533                 :             :     {
    1534                 :           0 :         goto exit_function;
    1535                 :             :     }
    1536                 :             : 
    1537                 :             :     /* check whether the bonds allow moving the hydrogens between at1 and at2 */
    1538   [ #  #  #  # ]:           0 :     if (( atom[at1].endpoint != atom[at2].endpoint || !atom[at1].endpoint ))
    1539                 :             :     {
    1540                 :             :         int nErr;
    1541                 :           0 :         nErr = bExistsAnyAltPath( pCG, pBNS, pBD, atom, num_atoms, at1, at2, ALT_PATH_MODE_TAUTOM );
    1542         [ #  # ]:           0 :         if (nErr <= 0)
    1543                 :             :         {
    1544                 :           0 :             ret = nErr;
    1545                 :           0 :             goto exit_function;
    1546                 :             :         }
    1547                 :             :     }
    1548                 :             : 
    1549                 :             :     /* save tautomeric bonds */
    1550                 :           0 :     nNumBondPosTmp = 0;
    1551         [ #  # ]:           0 :     for (k = 0; k < nLenDfsPath; k++)
    1552                 :             :     {
    1553                 :           0 :         bond_type = DfsPath[k].bond_type;
    1554   [ #  #  #  #  :           0 :         if (REPLACE_THE_BOND( bond_type ))
             #  #  #  # ]
    1555                 :             :         {
    1556                 :           0 :             BondPosTmp[nNumBondPosTmp].nAtomNumber = DfsPath[k].at_no;     /*  accumulate bonds to be */
    1557                 :           0 :             BondPosTmp[nNumBondPosTmp].neighbor_index = DfsPath[k].bond_pos;  /*  marked as tautomeric */
    1558                 :           0 :             nNumBondPosTmp += 2; /*  leave room for the same bond in opposite direction */
    1559                 :             :         }
    1560                 :             :     }
    1561                 :             :     /*  save endpoints */
    1562         [ #  # ]:           0 :     for (j = 0; j < 2; j++)
    1563                 :             :     {
    1564         [ #  # ]:           0 :         endpoint = j ? at2 : at1;
    1565         [ #  # ]:           0 :         if (!atom[endpoint].endpoint)
    1566                 :             :         {
    1567                 :             :             /* not a known endpoint */
    1568         [ #  # ]:           0 :             endpoint_valence = j ? endpoint_valence2 : endpoint_valence1;
    1569         [ #  # ]:           0 :             chem_bonds_valence = j ? eif2.cNeutralBondsValence : eif1.cNeutralBondsValence;
    1570                 :             :             /* endpoint_valence = get_endpoint_valence( atom[endpoint].el_number ); */
    1571         [ #  # ]:           0 :             nMobile = j ? nMobile2 : nMobile1;
    1572                 :             :             /* nMobile  = (atom[endpoint].charge == -1) + atom[endpoint].num_H; */
    1573                 :             :             /* if ( nMobile + atom[endpoint].chem_bonds_valence != endpoint_valence ) -- fixed 02-06-2003*/
    1574         [ #  # ]:           0 :             if (nMobile + chem_bonds_valence != endpoint_valence)
    1575                 :             :             {
    1576                 :           0 :                 goto exit_function; /*  abnormal endpoint valence; ignore. */
    1577                 :             :             }
    1578                 :           0 :             AddAtom2num( EndPointTmp[nNumEndPointTmp].num, atom, endpoint, 2 ); /* fill out */
    1579                 :           0 :             AddAtom2DA( EndPointTmp[nNumEndPointTmp].num_DA, atom, endpoint, 2 );
    1580                 :             :         }
    1581                 :             :         else
    1582                 :             :         {
    1583                 :             :             /* already an endpoint */ /* **now it is wrong:** no mobile atom/charge at this endpoint */
    1584                 :           0 :             memset( EndPointTmp + nNumEndPointTmp, 0, sizeof( EndPointTmp[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    1585                 :             :         }
    1586                 :           0 :         EndPointTmp[nNumEndPointTmp].nAtomNumber = endpoint;
    1587                 :           0 :         EndPointTmp[nNumEndPointTmp].nGroupNumber = atom[endpoint].endpoint;
    1588                 :           0 :         EndPointTmp[nNumEndPointTmp].nEquNumber = 0;
    1589                 :             : 
    1590                 :           0 :         nNumEndPointTmp++;
    1591                 :             :     }
    1592                 :             :     /*  add collected tautomeric bonds and endpoints to the input/output data */
    1593                 :           0 :     nNumBondPos = AddBondsPos( atom, BondPosTmp, nNumBondPosTmp, BondPos, nMaxNumBondPos, nNumBondPos );
    1594                 :           0 :     nNumEndPoint = AddEndPoints( EndPointTmp, nNumEndPointTmp, EndPoint, nMaxNumEndPoint, nNumEndPoint );
    1595                 :             : 
    1596   [ #  #  #  # ]:           0 :     if (nNumBondPos >= 0 && nNumEndPoint >= 0)
    1597                 :             :     {
    1598   [ #  #  #  #  :           0 :         if ((ret = ( nNumBondPos > *pnNumBondPos ) || ( nNumEndPoint > *pnNumEndPoint ))) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    1599                 :             :         {
    1600                 :           0 :             *pnNumBondPos = nNumBondPos;
    1601                 :           0 :             *pnNumEndPoint = nNumEndPoint;
    1602                 :             :         }
    1603                 :             :     }
    1604                 :             : 
    1605                 :           0 : exit_function:
    1606                 :             :     /*nDfsPathPos[DfsPath[nLenDfsPath].at_no] = 0;*/
    1607                 :             : 
    1608                 :           0 :     return ret;
    1609                 :             : 
    1610                 :             : #undef PATH_LEN
    1611                 :             : }
    1612                 :             : #endif  /* TAUT_15_NON_RING */
    1613                 :             : 
    1614                 :             : 
    1615                 :             : /****************************************************************************
    1616                 :             : 
    1617                 :             :   1,4 tautomerism in 5-member ring
    1618                 :             : 
    1619                 :             : 
    1620                 :             :    O=N2-C            O-N2=C          N1 = DfsPath[0].at_no
    1621                 :             :      |   \\            |   \         N2 = DfsPath[1].at_no
    1622                 :             :      |     D  <->      |     D
    1623                 :             :      |   /             |   //
    1624                 :             :   HO-N1=E           HO=N1-E
    1625                 :             : 
    1626                 :             : ****************************************************************************/
    1627                 :             : 
    1628                 :             : /****************************************************************************
    1629                 :             :   check if a tautomeric 5-member ring (pyrazole derivatives) has been found
    1630                 :             : ****************************************************************************/
    1631                 :           0 : int Check5MembTautRing( struct tagCANON_GLOBALS *pCG,
    1632                 :             :                         inp_ATOM *atom,
    1633                 :             :                         DFS_PATH *DfsPath,
    1634                 :             :                         int nLenDfsPath,
    1635                 :             :                         int nStartAtomNeighbor,
    1636                 :             :                         int nStartAtomNeighbor2,
    1637                 :             :                         int nStartAtomNeighborNeighbor,
    1638                 :             :                         T_ENDPOINT *EndPoint,
    1639                 :             :                         int nMaxNumEndPoint,
    1640                 :             :                         T_BONDPOS  *BondPos,
    1641                 :             :                         int nMaxNumBondPos,
    1642                 :             :                         int *pnNumEndPoint,
    1643                 :             :                         int *pnNumBondPos,
    1644                 :             :                         struct BalancedNetworkStructure *pBNS,
    1645                 :             :                         struct BalancedNetworkData *pBD,
    1646                 :             :                         int num_atoms )
    1647                 :             : {
    1648                 :             : #define PATH_LEN 4
    1649                 :             :     int i, j, /*m,*/ nMobile, nMobile1, nMobile2, ept, eptn;
    1650                 :             :     int num_taut_endpoints, nNumBondPos, nNumBondPosTmp, nNumEndPoint, nNumEndPointTmp, ret;
    1651                 :             :     int endpoint;
    1652                 :           0 :     int n1_at = (int) DfsPath[0].at_no;
    1653                 :           0 :     int n2_at = (int) DfsPath[1].at_no;
    1654                 :             :     U_CHAR path_bonds[PATH_LEN + 1], bond_type;
    1655                 :             :     T_ENDPOINT EndPointTmp[2];
    1656                 :             :     T_BONDPOS  BondPosTmp[2 * PATH_LEN];
    1657                 :             :     ENDPOINT_INFO eif1, eif2;
    1658                 :             : 
    1659                 :             :     /*  the two root atoms (atom[n1_at] and atom[n2_at]) cannot belong */
    1660                 :             :     /*  to one and the same tautomeric group: it has been verified in MarkTautomerGroups() */
    1661                 :             : 
    1662                 :             :     /*  check hydrogens/endpoints */
    1663         [ #  # ]:           0 :     if (nLenDfsPath != 4)
    1664                 :             :     {
    1665                 :           0 :         return 0; /*  program error */
    1666                 :             :     }
    1667   [ #  #  #  # ]:           0 :     if (nStartAtomNeighbor2 >= 0 || nStartAtomNeighborNeighbor >= 0)
    1668                 :             :     {
    1669                 :           0 :         return 0; /*  program error: wrong call */
    1670                 :             :     }
    1671                 :             : 
    1672                 :           0 :     nNumBondPos = *pnNumBondPos;
    1673                 :           0 :     nNumEndPoint = *pnNumEndPoint;
    1674                 :           0 :     nNumEndPointTmp = 0;
    1675                 :             :     /* djb-rwth: removing redundant code */
    1676                 :           0 :     ret = 0;
    1677         [ #  # ]:           0 :     for (ept = 0; ept < 2; ept++) /* djb-rwth: initialisation needed for num array */
    1678         [ #  # ]:           0 :         for (eptn = 0; eptn < T_NUM_NO_ISOTOPIC + T_NUM_ISOTOPIC; eptn++)
    1679                 :           0 :             EndPointTmp[ept].num[eptn] = 0;
    1680                 :             : 
    1681   [ #  #  #  # ]:           0 :     if (!nGetEndpointInfo( atom, n1_at, &eif1 ) ||
    1682                 :           0 :         !nGetEndpointInfo( atom, n2_at, &eif2 ))
    1683                 :             :     {
    1684                 :           0 :         return 0;
    1685                 :             :     }
    1686                 :             : 
    1687                 :           0 :     nMobile1 = atom[n1_at].num_H + ( atom[n1_at].charge == -1 );
    1688                 :           0 :     nMobile2 = atom[n2_at].num_H + ( atom[n2_at].charge == -1 );
    1689                 :           0 :     nMobile = nMobile1 + nMobile2;
    1690                 :           0 :     num_taut_endpoints = ( 0 != atom[n1_at].endpoint ) + ( 0 != atom[n2_at].endpoint ); /*  if both N atoms already are endpoints */
    1691                 :             :     /*
    1692                 :             :     if ( !(nMobile == 1 || num_taut_endpoints == 2) && !(nMobile>1 && num_taut_endpoints >= 1) ) {
    1693                 :             :         return 0;
    1694                 :             :     }
    1695                 :             :     */
    1696   [ #  #  #  # ]:           0 :     if (num_taut_endpoints == 0 && nMobile != 1)
    1697                 :             :     {
    1698                 :           0 :         return 0;
    1699                 :             :     }
    1700                 :             : 
    1701                 :             :     /* finally check whether the bonds allow moving the hydrogens */
    1702   [ #  #  #  # ]:           0 :     if (( atom[n1_at].endpoint != atom[n2_at].endpoint || !atom[n1_at].endpoint ))
    1703                 :             :     {
    1704                 :             :         int nErr;
    1705                 :           0 :         nErr = bExistsAnyAltPath( pCG, pBNS, pBD, atom, num_atoms, n1_at, n2_at, ALT_PATH_MODE_TAUTOM );
    1706         [ #  # ]:           0 :         if (nErr <= 0)
    1707                 :             :         {
    1708                 :           0 :             return nErr;
    1709                 :             :         }
    1710                 :             :     }
    1711                 :             : 
    1712                 :             :     /*  save endpoints */
    1713         [ #  # ]:           0 :     for (j = 0; j < 2; j++)
    1714                 :             :     {
    1715         [ #  # ]:           0 :         endpoint = j ? n1_at : n2_at;
    1716         [ #  # ]:           0 :         if (!atom[endpoint].endpoint)
    1717                 :             :         {
    1718                 :             :             /* not a known endpoint */
    1719                 :             :             /*
    1720                 :             :                         nMobile  = (atom[endpoint].charge == -1) + atom[endpoint].num_H;
    1721                 :             :                     } else {
    1722                 :             :                         nMobile  = 0;
    1723                 :             :                     }
    1724                 :             :                     if ( nMobile ) {
    1725                 :             :             */
    1726                 :           0 :             AddAtom2num( EndPointTmp[nNumEndPointTmp].num, atom, endpoint, 2 ); /* fill out */
    1727                 :           0 :             AddAtom2DA( EndPointTmp[nNumEndPointTmp].num_DA, atom, endpoint, 2 );
    1728                 :             :             /*
    1729                 :             :             EndPointTmp[nNumEndPointTmp].num[1] = (atom[endpoint].charge == -1);
    1730                 :             :             EndPointTmp[nNumEndPointTmp].num[0] = nMobile;
    1731                 :             :             for ( m = 0; m < T_NUM_ISOTOPIC; m ++ ) {
    1732                 :             :                 EndPointTmp[nNumEndPointTmp].num[T_NUM_NO_ISOTOPIC+m] = atom[endpoint].num_iso_H[NUM_H_ISOTOPES-m-1];
    1733                 :             :             }
    1734                 :             :             */
    1735                 :             :         }
    1736                 :             :         else
    1737                 :             :         {
    1738                 :           0 :             memset( EndPointTmp + nNumEndPointTmp, 0, sizeof( EndPointTmp[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    1739                 :             :         }
    1740                 :           0 :         EndPointTmp[nNumEndPointTmp].nAtomNumber = endpoint;
    1741                 :           0 :         EndPointTmp[nNumEndPointTmp].nGroupNumber = atom[endpoint].endpoint;
    1742                 :           0 :         EndPointTmp[nNumEndPointTmp].nEquNumber = 0;
    1743                 :             : 
    1744                 :           0 :         nNumEndPointTmp++;
    1745                 :             :     }
    1746                 :             : 
    1747                 :             :     /*  extract bonds */
    1748                 :           0 :     nNumBondPosTmp = 0;
    1749         [ #  # ]:           0 :     for (i = 1; i <= nLenDfsPath; i++)
    1750                 :             :     {
    1751                 :           0 :         bond_type = DfsPath[i].bond_type;
    1752                 :           0 :         path_bonds[i - 1] = bond_type;
    1753   [ #  #  #  #  :           0 :         if (REPLACE_THE_BOND( bond_type ))
             #  #  #  # ]
    1754                 :             :         {
    1755                 :           0 :             BondPosTmp[nNumBondPosTmp].nAtomNumber = DfsPath[i].at_no;
    1756                 :           0 :             BondPosTmp[nNumBondPosTmp].neighbor_index = DfsPath[i].bond_pos;
    1757                 :           0 :             nNumBondPosTmp += 2;
    1758                 :             :         }
    1759                 :             :     }
    1760                 :             :     /* path_bonds is from at_n2 to at_n1 */
    1761         [ #  # ]:           0 :     if (!( i = are_alt_bonds( path_bonds, nLenDfsPath ) ))
    1762                 :             :     {
    1763                 :           0 :         return 0;
    1764                 :             :     }
    1765                 :             :     /* i is a bond type of the last bond to at_n1, the first bond from at_n2 is 2-i if i=1 or 2 */
    1766                 :             : 
    1767                 :             :     /* single bond at n1_at: it should have a mobile atom, n2_at should not */
    1768   [ #  #  #  #  :           0 :     if ((i == BOND_SINGLE && ( (!atom[n1_at].endpoint && !eif1.cDonor) || (!atom[n2_at].endpoint && !eif2.cAcceptor) )) ||
          #  #  #  #  #  
                #  #  # ]
    1769                 :             :         /* double bond at n1_at: it should not have a mobile atom, n2_at should */
    1770   [ #  #  #  #  :           0 :         (i == BOND_DOUBLE && ( (!atom[n1_at].endpoint && !eif1.cAcceptor) || (!atom[n2_at].endpoint && !eif2.cDonor) ))) /* djb-rwth: addressing LLVM warnings */
             #  #  #  # ]
    1771                 :             :     {
    1772                 :           0 :         return 0; /* bond pattern does not fit */
    1773                 :             :     }
    1774                 :             : 
    1775                 :           0 :     nNumBondPos = AddBondsPos( atom, BondPosTmp, nNumBondPosTmp, BondPos, nMaxNumBondPos, nNumBondPos );
    1776                 :           0 :     nNumEndPoint = AddEndPoints( EndPointTmp, nNumEndPointTmp, EndPoint, nMaxNumEndPoint, nNumEndPoint );
    1777                 :             : 
    1778   [ #  #  #  # ]:           0 :     if (nNumBondPos >= 0 && nNumEndPoint >= 0)
    1779                 :             :     {
    1780   [ #  #  #  #  :           0 :         if ((ret = ( nNumBondPos > *pnNumBondPos ) || ( nNumEndPoint > *pnNumEndPoint ))) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    1781                 :             :         {
    1782                 :           0 :             *pnNumBondPos = nNumBondPos;
    1783                 :           0 :             *pnNumEndPoint = nNumEndPoint;
    1784                 :             :         }
    1785                 :             :     }
    1786                 :           0 :     return ret;
    1787                 :             : 
    1788                 :             : #undef PATH_LEN
    1789                 :             : }
    1790                 :             : #endif /* } */
        

Generated by: LCOV version 2.0-1