LCOV - code coverage report
Current view: top level - src - ichiqueu.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 1.5 % 523 8
Test Date: 2026-05-04 07:05:02 Functions: 6.2 % 16 1
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.9 % 560 5

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

Generated by: LCOV version 2.0-1