LCOV - code coverage report
Current view: top level - src - ichirvr7.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 2.1 % 1173 25
Test Date: 2026-10-14 12:14:55 Functions: 5.9 % 17 1
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 1.0 % 1156 12

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <stdlib.h>
       7                 :             : #include <string.h>
       8                 :             : #include <math.h>
       9                 :             : 
      10                 :             : /* */
      11                 :             : 
      12                 :             : /* #define CHECK_WIN32_VC_HEAP */
      13                 :             : 
      14                 :             : #include "mode.h"
      15                 :             : 
      16                 :             : #if ( READ_INCHI_STRING == 1 )
      17                 :             : 
      18                 :             : #include "ichitime.h"
      19                 :             : 
      20                 :             : /* reverse InChI */
      21                 :             : 
      22                 :             : #include "ichitime.h"
      23                 :             : #include "ichicant.h"
      24                 :             : #include "ichirvrs.h"
      25                 :             : #include "inchicmp.h"
      26                 :             : 
      27                 :             : #include "inchi_gui.h"
      28                 :             : 
      29                 :             : #include "bcf_s.h"
      30                 :             : 
      31                 :             : #if 0
      32                 :             : #ifndef COMPILE_ANSI_ONLY
      33                 :             : #ifndef TARGET_LIB_FOR_WINCHI
      34                 :             : #include "inchi_gui.h"
      35                 :             : #endif
      36                 :             : #endif
      37                 :             : #endif
      38                 :             : 
      39                 :             : 
      40                 :             : #ifdef TARGET_LIB_FOR_WINCHI
      41                 :             : /* dummies */
      42                 :             : /****************************************************************************/
      43                 :             : int DisplayStructure(struct tagCANON_GLOBALS* pCG,
      44                 :             :     inp_ATOM* at,
      45                 :             :     int                     num_at,
      46                 :             :     OAD_Polymer* polymer,
      47                 :             :     int                     num_removed_H,
      48                 :             :     int                     bAdd_DT_to_num_H,
      49                 :             :     int                     nNumRemovedProtons,
      50                 :             :     NUM_H* nNumRemovedProtonsIsotopic,
      51                 :             :     int                     bIsotopic,
      52                 :             :     int                     j /*bTautomeric*/,
      53                 :             :     INChI** cur_INChI,
      54                 :             :     INChI_Aux** cur_INChI_Aux,
      55                 :             :     int                     bAbcNumbers,
      56                 :             :     DRAW_PARMS* dp,
      57                 :             :     INCHI_MODE              nMode,
      58                 :             :     char* szTitle)
      59                 :             : {
      60                 :             :     return 0;
      61                 :             : }
      62                 :             : #endif /* TARGET_LIB_FOR_WINCHI */
      63                 :             : 
      64                 :             : 
      65                 :             : /****************************************************************************/
      66                 :           0 : int InChI2Atom(INCHI_CLOCK* ic,
      67                 :             :     CANON_GLOBALS* pCG,
      68                 :             :     ICHICONST INPUT_PARMS* ip,
      69                 :             :     STRUCT_DATA* sd,
      70                 :             :     const char* szCurHdr,
      71                 :             :     long num_inp,
      72                 :             :     StrFromINChI* pStruct,
      73                 :             :     int iComponent,
      74                 :             :     int iAtNoOffset,
      75                 :             :     int  bI2A_Flag,
      76                 :             :     int bHasSomeFixedH,
      77                 :             :     InpInChI* OneInput)
      78                 :             : {
      79                 :           0 :     int ret = 0;
      80                 :             : 
      81                 :           0 :     int iINChI = (bI2A_Flag & I2A_FLAG_RECMET) ? INCHI_REC : INCHI_BAS;
      82                 :           0 :     int bMobileH = (bI2A_Flag & I2A_FLAG_FIXEDH) ? TAUT_NON : TAUT_YES;
      83                 :             : 
      84                 :             :     INChI* pInChI[TAUT_NUM];
      85                 :             : 
      86                 :             : 
      87                 :             : 
      88                 :           0 :     memset(pInChI, 0, sizeof(pInChI)); /* djb-rwth: memset_s C11/Annex K variant? */
      89                 :             : 
      90                 :             : 
      91                 :             :     /* disconnected or reconnected */
      92                 :             : 
      93         [ #  # ]:           0 :     if (iINChI == INCHI_REC)
      94                 :             :     {
      95         [ #  # ]:           0 :         if (!OneInput->nNumComponents[iINChI][TAUT_YES])
      96                 :             :         {
      97                 :           0 :             iINChI = INCHI_BAS;
      98                 :             :         }
      99                 :             :     }
     100         [ #  # ]:           0 :     if (iComponent >= OneInput->nNumComponents[iINChI][TAUT_YES])
     101                 :             :     {
     102                 :           0 :         return 0; /* component does not exist */
     103                 :             :     }
     104                 :             : 
     105                 :             :     /* mobile or fixed H */
     106                 :           0 :     pStruct->bFixedHExists = 0;
     107         [ #  # ]:           0 :     if (bMobileH == TAUT_NON)
     108                 :             :     {
     109         [ #  # ]:           0 :         if (!OneInput->nNumComponents[iINChI][bMobileH])
     110                 :             :         {
     111                 :             :             /* only one InChI exists (no mobile H) */
     112                 :           0 :             bMobileH = TAUT_YES;
     113                 :             :         }
     114                 :             :     }
     115         [ #  # ]:           0 :     if (iComponent >= OneInput->nNumComponents[iINChI][bMobileH])
     116                 :             :     {
     117                 :           0 :         return 0; /* component does not exist */
     118                 :             :     }
     119                 :             : 
     120                 :             :     /* pointer to the InChI that is going to be reversed */
     121                 :           0 :     pInChI[0] = &OneInput->pInpInChI[iINChI][bMobileH][iComponent];
     122                 :           0 :     pStruct->bMobileH = bMobileH;
     123                 :           0 :     pStruct->iINCHI = iINChI;
     124                 :             : 
     125                 :             :     /* deleted component only in case Mobile-H and compound contains only protons */
     126         [ #  # ]:           0 :     if (pInChI[0]->bDeleted)
     127                 :             :     {
     128                 :           0 :         return 0; /* deleted component, presumably H(+) */
     129                 :             :     }
     130                 :             : 
     131   [ #  #  #  # ]:           0 :     if (bMobileH == TAUT_NON && OneInput->nNumProtons[iINChI][TAUT_YES].pNumProtons)
     132                 :             :     {
     133                 :           0 :         pStruct->nNumRemovedProtonsMobHInChI =
     134                 :           0 :             OneInput->nNumProtons[iINChI][TAUT_YES].pNumProtons[iComponent].nNumRemovedProtons;
     135                 :             :     }
     136                 :             : 
     137   [ #  #  #  # ]:           0 :     if (bMobileH == TAUT_NON ||
     138                 :           0 :         (bMobileH == TAUT_YES &&
     139         [ #  # ]:           0 :             OneInput->pInpInChI[iINChI][TAUT_NON] &&
     140         [ #  # ]:           0 :             OneInput->pInpInChI[iINChI][TAUT_NON][iComponent].nNumberOfAtoms > 0 &&
     141         [ #  # ]:           0 :             !OneInput->pInpInChI[iINChI][TAUT_NON][iComponent].bDeleted) /* djb-rwth: addressing LLVM warning */
     142                 :             :         )
     143                 :             :     {
     144                 :           0 :         pStruct->bFixedHExists = 1;
     145                 :             :     }
     146                 :             : 
     147         [ #  # ]:           0 :     if (bMobileH == TAUT_NON &&
     148         [ #  # ]:           0 :         iComponent < OneInput->nNumComponents[iINChI][TAUT_YES] &&
     149         [ #  # ]:           0 :         OneInput->pInpInChI[iINChI][TAUT_YES] &&
     150         [ #  # ]:           0 :         OneInput->pInpInChI[iINChI][TAUT_YES][iComponent].nNumberOfAtoms > 0 &&
     151         [ #  # ]:           0 :         !OneInput->pInpInChI[iINChI][TAUT_YES][iComponent].bDeleted
     152                 :             :         )
     153                 :             :     {
     154                 :             :         /* pointer to the Mobile-H InChI if we are reversing Fixed-H InChI */
     155                 :           0 :         pInChI[1] = &OneInput->pInpInChI[iINChI][TAUT_YES][iComponent];
     156                 :             :     }
     157                 :             : 
     158                 :           0 :     pStruct->num_inp_actual = OneInput->num_inp;
     159                 :             : 
     160                 :             :     /* Intercept and correct non-polymer Zz to Zy if applicable */
     161         [ #  # ]:           0 :     if (OneInput->polymer)
     162                 :             :     {
     163                 :             :         int a, k, new_num;
     164                 :           0 :         OAD_Polymer* p = OneInput->polymer;
     165                 :           0 :         pStruct->n_pzz = 0;
     166                 :           0 :         pStruct->n_zy = 0;
     167         [ #  # ]:           0 :         for (a = 0; a < pInChI[0]->nNumberOfAtoms; a++)
     168                 :             :         {
     169                 :           0 :             int aglob = iAtNoOffset + a + 1;
     170         [ #  # ]:           0 :             if (pInChI[0]->nAtom[a] == EL_NUMBER_ZZ)
     171                 :             :             {
     172                 :           0 :                 new_num = EL_NUMBER_ZY; /* Zy */
     173         [ #  # ]:           0 :                 for (k = 0; k < p->n; k++)
     174                 :             :                 {
     175   [ #  #  #  # ]:           0 :                     if ((aglob == p->units[k]->cap1) || (aglob == p->units[k]->cap2))
     176                 :             :                     {
     177                 :           0 :                         new_num = EL_NUMBER_ZZ;
     178                 :           0 :                         break;
     179                 :             :                     }
     180                 :             :                 }
     181                 :           0 :                 pInChI[0]->nAtom[a] = new_num;
     182         [ #  # ]:           0 :                 if (new_num == EL_NUMBER_ZY)
     183                 :             :                 {
     184                 :           0 :                     pStruct->n_zy++;
     185                 :             :                 }
     186         [ #  # ]:           0 :                 else if (new_num == EL_NUMBER_ZZ)
     187                 :             :                 {
     188                 :           0 :                     pStruct->n_pzz++;
     189                 :             :                 }
     190                 :             :             }
     191                 :             :         }
     192                 :             :     }
     193                 :             : 
     194                 :           0 :     ret = OneInChI2Atom(ic, pCG, ip, sd, szCurHdr, num_inp, pStruct,
     195                 :             :         iComponent, 0 /* iAtNoOffset*/, bHasSomeFixedH, pInChI);
     196                 :             : 
     197                 :             :     /* djb-rwth: fixing oss-fuzz issue #66758, #30283 */
     198   [ #  #  #  # ]:           0 :     if (pStruct->at && pStruct->at2)
     199                 :             :     {
     200                 :             :         int a;
     201         [ #  # ]:           0 :         for (a = 0; a < pInChI[0]->nNumberOfAtoms; a++)
     202                 :             :         {
     203         [ #  # ]:           0 :             if (pInChI[0]->nAtom[a] == EL_NUMBER_ZY)
     204                 :             :             {
     205                 :           0 :                 pInChI[0]->nAtom[a] = EL_NUMBER_ZZ;
     206                 :           0 :                 pStruct->at[a].el_number = EL_NUMBER_ZZ;
     207                 :           0 :                 strcpy(pStruct->at[a].elname, "Zz");
     208                 :           0 :                 pStruct->at2[a].el_number = EL_NUMBER_ZZ;
     209                 :           0 :                 strcpy(pStruct->at2[a].elname, "Zz");
     210                 :           0 :                 pStruct->n_zy--;
     211                 :           0 :                 pStruct->n_pzz++;
     212                 :             :             }
     213                 :             :         }
     214                 :             :     }
     215                 :             : 
     216                 :           0 :     return ret; /* same interpretation as in ProcessOneStructure ??? */
     217                 :             : }
     218                 :             : 
     219                 :             : 
     220                 :             : /****************************************************************************/
     221                 :           0 : void RemoveFixHInChIIdentical2MobH(InpInChI* pOneInput)
     222                 :             : {
     223                 :             :     int iInchiRec, cur_num_comp, k;
     224                 :             : 
     225                 :             :     /* eliminate Fixed-H InChI that are exactly same as the corresponding Mobile-H structures */
     226         [ #  # ]:           0 :     for (iInchiRec = 0; iInchiRec < INCHI_NUM; iInchiRec++)
     227                 :             :     {
     228                 :           0 :         cur_num_comp = inchi_min(pOneInput->nNumComponents[iInchiRec][TAUT_YES],
     229                 :             :             pOneInput->nNumComponents[iInchiRec][TAUT_NON]);
     230         [ #  # ]:           0 :         for (k = 0; k < cur_num_comp; k++)
     231                 :             :         {
     232         [ #  # ]:           0 :             if (!CompareReversedINChI(pOneInput->pInpInChI[iInchiRec][TAUT_YES] + k,
     233                 :           0 :                 pOneInput->pInpInChI[iInchiRec][TAUT_NON] + k, NULL, NULL))
     234                 :             :             {
     235                 :           0 :                 Free_INChI_Members(pOneInput->pInpInChI[iInchiRec][TAUT_NON] + k);
     236                 :           0 :                 memset(pOneInput->pInpInChI[iInchiRec][TAUT_NON] + k, 0, sizeof(pOneInput->pInpInChI[0][0][0])); /* djb-rwth: memset_s C11/Annex K variant? */
     237                 :             :             }
     238                 :             :         }
     239                 :             :     }
     240                 :           0 : }
     241                 :             : 
     242                 :             : 
     243                 :             : /****************************************************************************
     244                 :             :  mark Disconnected InChI components that are exactly same as Reconnected ones
     245                 :             :  Disconnected will have a negative number of the reconnected component
     246                 :             :  Reconnected will have a positive number of the disconnected component
     247                 :             : ****************************************************************************/
     248                 :           0 : int MarkDisconectedIdenticalToReconnected(InpInChI* pOneInput)
     249                 :             : {
     250                 :           0 :     int k1, k2, num_marked = 0;
     251                 :           0 :     int k1max = inchi_max(pOneInput->nNumComponents[INCHI_BAS][TAUT_YES],
     252                 :             :         pOneInput->nNumComponents[INCHI_BAS][TAUT_NON]);
     253                 :             : 
     254         [ #  # ]:           0 :     for (k1 = 0; k1 < k1max; k1++)
     255                 :             :     {
     256                 :           0 :         int k2max = inchi_max(pOneInput->nNumComponents[INCHI_REC][TAUT_YES],
     257                 :             :             pOneInput->nNumComponents[INCHI_REC][TAUT_NON]);
     258                 :             : 
     259         [ #  # ]:           0 :         for (k2 = 0; k2 < k2max; k2++)
     260                 :             :         {
     261                 :           0 :             int eqM = k1 < pOneInput->nNumComponents[INCHI_BAS][TAUT_YES]
     262                 :           0 :                 &&
     263         [ #  # ]:           0 :                 k2 < pOneInput->nNumComponents[INCHI_REC][TAUT_YES]
     264                 :           0 :                 &&
     265         [ #  # ]:           0 :                 !pOneInput->pInpInChI[INCHI_REC][TAUT_YES][k2].nLink /* already linked */
     266                 :           0 :                 &&
     267         [ #  # ]:           0 :                 !pOneInput->pInpInChI[INCHI_BAS][TAUT_YES][k1].bDeleted
     268                 :           0 :                 &&
     269         [ #  # ]:           0 :                 pOneInput->pInpInChI[INCHI_BAS][TAUT_YES][k1].nNumberOfAtoms
     270                 :           0 :                 &&
     271                 :           0 :                 pOneInput->pInpInChI[INCHI_BAS][TAUT_YES][k1].nNumberOfAtoms ==
     272         [ #  # ]:           0 :                 pOneInput->pInpInChI[INCHI_REC][TAUT_YES][k2].nNumberOfAtoms
     273                 :           0 :                 &&
     274         [ #  # ]:           0 :                 !pOneInput->pInpInChI[INCHI_REC][TAUT_YES][k2].bDeleted
     275   [ #  #  #  # ]:           0 :                 &&
     276                 :           0 :                 !CompareReversedINChI(pOneInput->pInpInChI[INCHI_REC][TAUT_YES] + k2,
     277                 :           0 :                     pOneInput->pInpInChI[INCHI_BAS][TAUT_YES] + k1,
     278                 :             :                     NULL, NULL);
     279                 :             : 
     280                 :           0 :             int isF1 = k1 < pOneInput->nNumComponents[INCHI_BAS][TAUT_NON]
     281                 :           0 :                 &&
     282         [ #  # ]:           0 :                 0 == pOneInput->pInpInChI[INCHI_BAS][TAUT_NON][k1].bDeleted
     283         [ #  # ]:           0 :                 &&
     284         [ #  # ]:           0 :                 0 < pOneInput->pInpInChI[INCHI_BAS][TAUT_NON][k1].nNumberOfAtoms
     285                 :             :                 ;
     286                 :             : 
     287                 :           0 :             int isF2 = k2 < pOneInput->nNumComponents[INCHI_REC][TAUT_NON]
     288                 :           0 :                 &&
     289         [ #  # ]:           0 :                 0 == pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].bDeleted
     290         [ #  # ]:           0 :                 &&
     291         [ #  # ]:           0 :                 0 < pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].nNumberOfAtoms
     292                 :             :                 ;
     293                 :             : 
     294                 :           0 :             int eqF = isF1
     295         [ #  # ]:           0 :                 &&
     296                 :             :                 isF2
     297                 :           0 :                 &&
     298         [ #  # ]:           0 :                 !pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].nLink
     299                 :           0 :                 &&
     300                 :           0 :                 pOneInput->pInpInChI[INCHI_BAS][TAUT_NON][k1].nNumberOfAtoms ==
     301         [ #  # ]:           0 :                 pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].nNumberOfAtoms
     302   [ #  #  #  # ]:           0 :                 &&
     303                 :           0 :                 !CompareReversedINChI(pOneInput->pInpInChI[INCHI_REC][TAUT_NON] + k2,
     304                 :           0 :                     pOneInput->pInpInChI[INCHI_BAS][TAUT_NON] + k1,
     305                 :             :                     NULL, NULL)
     306                 :             :                 ;
     307                 :             : 
     308   [ #  #  #  #  :           0 :             if (eqM && ((!isF1 && !isF2) || eqF)) /* djb-rwth: addressing LLVM warning */
             #  #  #  # ]
     309                 :             :             {
     310                 :           0 :                 pOneInput->pInpInChI[INCHI_BAS][TAUT_YES][k1].nLink = -(k2 + 1);
     311                 :           0 :                 pOneInput->pInpInChI[INCHI_REC][TAUT_YES][k2].nLink = (k1 + 1);
     312         [ #  # ]:           0 :                 if (eqF)
     313                 :             :                 {
     314                 :           0 :                     pOneInput->pInpInChI[INCHI_BAS][TAUT_NON][k1].nLink = -(k2 + 1);
     315                 :           0 :                     pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].nLink = (k1 + 1);
     316                 :             :                 }
     317                 :           0 :                 num_marked++;
     318                 :           0 :                 break;
     319                 :             :                 /* equal InChI has been deleted from the disconnected layer, get next k1 */
     320                 :             :             }
     321                 :             :         }
     322                 :             :     }
     323                 :             : 
     324                 :           0 :     return num_marked;
     325                 :             : }
     326                 :             : 
     327                 :             : 
     328                 :             : /****************************************************************************/
     329                 :           0 : void SetUpSrm(SRM* pSrm)
     330                 :             : {
     331                 :             :     /* structure restore parms !!!!! */
     332                 :           0 :     memset(pSrm, 0, sizeof(pSrm[0])); /* djb-rwth: memset_s C11/Annex K variant? */
     333                 :           0 :     pSrm->bFixStereoBonds = FIX_STEREO_BOND_ORDER;
     334                 :           0 :     pSrm->nMetal2EndpointMinBondOrder = 1;
     335                 :           0 :     pSrm->nMetal2EndpointInitEdgeFlow = 0;
     336                 :             : 
     337                 :             :     if (METAL_FREE_CHARGE_VAL == 1)
     338                 :             :     {
     339                 :           0 :         pSrm->bMetalAddFlower = 1;
     340                 :             :         /* the next 3 parameters: */
     341                 :             :         /* 0, 0, 0 => all bonds 0, no init radical on metal */
     342                 :             :         /* 0, 0, 1 => all bonds 0,    init radical on metal */
     343                 :             :         /* 0, 1, 0 => wrong */
     344                 :             :         /* 0, 1, 1 => all bonds 1, no init radical on metal */
     345                 :             :         /* 1, 0, 1 => min bond order 1, all bonds to metal have order 1 */
     346                 :             :         /* 1, 1, 0 => wrong */
     347                 :             :         /* 1, 1, 1 => wrong */
     348                 :           0 :         pSrm->nMetalMinBondOrder = 0;
     349                 :           0 :         pSrm->nMetalInitEdgeFlow = 1;
     350                 :           0 :         pSrm->nMetalInitBondOrder = 1;
     351                 :           0 :         pSrm->bStereoRemovesMetalFlag = pSrm->bFixStereoBonds;
     352                 :           0 :         pSrm->nMetalFlowerParam_D = 16;
     353                 :           0 :         pSrm->nMetalMaxCharge_D = 16;
     354                 :             :     }
     355                 :             :     else
     356                 :             :     {
     357                 :             :         pSrm->bMetalAddFlower = 0;
     358                 :             :         pSrm->nMetalMinBondOrder = 1;
     359                 :             :         pSrm->nMetalInitEdgeFlow = 0;
     360                 :             :         pSrm->nMetalInitBondOrder = 1;
     361                 :             :         pSrm->bStereoRemovesMetalFlag = pSrm->bFixStereoBonds;
     362                 :             :         pSrm->nMetalFlowerParam_D = 16;
     363                 :             :         pSrm->nMetalMaxCharge_D = 0;
     364                 :             :     }
     365                 :           0 :     pSrm->nMetal2EndpointInitBondOrder = pSrm->nMetal2EndpointMinBondOrder
     366                 :           0 :         + pSrm->nMetal2EndpointInitEdgeFlow;
     367                 :           0 : }
     368                 :             : 
     369                 :             : 
     370                 :             : /****************************************************************************/
     371                 :           0 : int MergeStructureComponents(ICHICONST INPUT_PARMS* ip,
     372                 :             :     STRUCT_DATA* sd,
     373                 :             :     long num_inp,
     374                 :             :     char* szCurHdr,
     375                 :             :     ICHICONST SRM* pSrm,
     376                 :             :     int bReqNonTaut,
     377                 :             :     StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
     378                 :             :     InpInChI* pOneInput)
     379                 :             : {
     380                 :             :     int iInchiRec, iMobileH, iAlternH, num_components, tot_just_atoms, tot_atoms, cur_nA, cur_nH; /* djb-rwth: removing redundant variables */
     381                 :             :     int k, i, j, ret, iCurAtomOffs, iNxtAtomOffs, iCurDelHOffs, iNxtDelHOffs, len, len2, iShiftH, icomp;
     382                 :           0 :     int* nAtomOffs = NULL, * nDelHOffs = NULL;
     383                 :             :     StrFromINChI* pStruct1;
     384                 :           0 :     inp_ATOM* at = NULL, * a;
     385                 :             : 
     386                 :           0 :     ret = 0;
     387                 :           0 :     pOneInput->num_atoms = 0;
     388                 :             :     /* select highest detail level */
     389         [ #  # ]:           0 :     if ((num_components = pOneInput->nNumComponents[INCHI_REC][TAUT_NON])) /* djb-rwth: addressing LLVM warning */
     390                 :             :     {
     391                 :           0 :         iInchiRec = INCHI_REC;
     392                 :           0 :         iMobileH = TAUT_NON;
     393                 :             :     }
     394                 :             :     else
     395                 :             :     {
     396         [ #  # ]:           0 :         if ((num_components = pOneInput->nNumComponents[INCHI_REC][TAUT_YES])) /* djb-rwth: addressing LLVM warning */
     397                 :             :         {
     398                 :           0 :             iInchiRec = INCHI_REC;
     399                 :           0 :             iMobileH = TAUT_YES;
     400                 :             :         }
     401                 :             :         else
     402                 :             :         {
     403         [ #  # ]:           0 :             if ((num_components = pOneInput->nNumComponents[INCHI_BAS][TAUT_NON])) /* djb-rwth: addressing LLVM warning */
     404                 :             :             {
     405                 :           0 :                 iInchiRec = INCHI_BAS;
     406                 :           0 :                 iMobileH = TAUT_NON;
     407                 :             :             }
     408                 :             :             else
     409                 :             :             {
     410         [ #  # ]:           0 :                 if ((num_components = pOneInput->nNumComponents[INCHI_BAS][TAUT_YES])) /* djb-rwth: addressing LLVM warning */
     411                 :             :                 {
     412                 :           0 :                     iInchiRec = INCHI_BAS;
     413                 :           0 :                     iMobileH = TAUT_YES;
     414                 :             :                 }
     415                 :             :                 else
     416                 :             :                 {
     417                 :           0 :                     return 0; /* no components available */
     418                 :             :                 }
     419                 :             :             }
     420                 :             :         }
     421                 :             :     }
     422                 :             : 
     423                 :           0 :     nAtomOffs = (int*)inchi_malloc(((long long)num_components + 1) * sizeof(nAtomOffs[0])); /* djb-rwth: cast operator added */
     424                 :           0 :     nDelHOffs = (int*)inchi_malloc(((long long)num_components + 1) * sizeof(nDelHOffs[0])); /* djb-rwth: cast operator added */
     425   [ #  #  #  # ]:           0 :     if (!nAtomOffs || !nDelHOffs)
     426                 :             :     {
     427                 :           0 :         ret = RI_ERR_ALLOC;
     428                 :           0 :         goto exit_function;
     429                 :             :     }
     430                 :             :     /* count number of atoms and removed H */
     431                 :             :     /* djb-rwth: removing redundant code */
     432   [ #  #  #  # ]:           0 :     iAlternH = (iMobileH == TAUT_NON && pOneInput->nNumComponents[iInchiRec][TAUT_YES]) ? TAUT_YES : -1;
     433                 :           0 :     nAtomOffs[0] = nDelHOffs[0] = 0;
     434         [ #  # ]:           0 :     for (k = 0; k < num_components; k++)
     435                 :             :     {
     436         [ #  # ]:           0 :         pStruct1 = pStruct[iInchiRec][iMobileH][k].num_atoms ? pStruct[iInchiRec][iMobileH] + k :
     437                 :           0 :             iAlternH >= 0 &&
     438   [ #  #  #  # ]:           0 :             pStruct[iInchiRec][iAlternH][k].num_atoms ? pStruct[iInchiRec][iAlternH] + k : NULL;
     439   [ #  #  #  #  :           0 :         if (!pStruct1 || !pStruct1->at2 || !pStruct1->num_atoms || pStruct1->bDeleted)
             #  #  #  # ]
     440                 :             :         {
     441                 :           0 :             cur_nA = cur_nH = 0;
     442                 :             :         }
     443                 :             :         else
     444                 :             :         {
     445                 :           0 :             cur_nA = pStruct1->num_atoms;
     446                 :           0 :             cur_nH = pStruct1->num_deleted_H;
     447                 :             :         }
     448                 :           0 :         nAtomOffs[k + 1] = nAtomOffs[k] + cur_nA;
     449                 :           0 :         nDelHOffs[k + 1] = nDelHOffs[k] + cur_nH;
     450                 :             :     }
     451                 :           0 :     tot_just_atoms = nAtomOffs[num_components];
     452                 :             :     /* shift all H to the end */
     453         [ #  # ]:           0 :     for (k = 0; k <= num_components; k++)
     454                 :             :     {
     455                 :           0 :         nDelHOffs[k] += tot_just_atoms;
     456                 :             :     }
     457                 :           0 :     tot_atoms = nDelHOffs[num_components];
     458                 :             : 
     459                 :             :     /* merge atoms together: 1. Allocate */
     460                 :           0 :     at = (inp_ATOM*)inchi_malloc(((long long)tot_atoms + 1) * sizeof(at[0])); /* djb-rwth: cast operator added */
     461         [ #  # ]:           0 :     if (NULL == at)
     462                 :             :     {
     463                 :           0 :         ret = RI_ERR_ALLOC;
     464                 :           0 :         goto exit_function;
     465                 :             :     }
     466         [ #  # ]:           0 :     if (!tot_atoms)
     467                 :             :     {
     468                 :           0 :         ret = 0;
     469                 :           0 :         goto exit_function; /* empty structure */
     470                 :             :     }
     471                 :             :     /* merge atoms together: 2. Copy */
     472         [ #  # ]:           0 :     for (k = 0; k < num_components; k++)
     473                 :             :     {
     474         [ #  # ]:           0 :         pStruct1 = pStruct[iInchiRec][iMobileH][k].num_atoms ? pStruct[iInchiRec][iMobileH] + k :
     475                 :           0 :             iAlternH >= 0 &&
     476   [ #  #  #  # ]:           0 :             pStruct[iInchiRec][iAlternH][k].num_atoms ? pStruct[iInchiRec][iAlternH] + k : NULL;
     477   [ #  #  #  # ]:           0 :         if ((len = nAtomOffs[k + 1] - nAtomOffs[k]) && pStruct1) /* djb-rwth: addressing LLVM warning; fixing coverity ID #499555 */ 
     478                 :             :         {
     479                 :           0 :             memcpy(at + nAtomOffs[k], pStruct1->at2, len * sizeof(at[0]));
     480         [ #  # ]:           0 :             if ((len2 = nDelHOffs[k + 1] - nDelHOffs[k])) /* djb-rwth: addressing LLVM warning */
     481                 :             :             {
     482                 :           0 :                 memcpy(at + nDelHOffs[k], pStruct1->at2 + len, len2 * sizeof(at[0]));
     483                 :             :             }
     484                 :             :         }
     485                 :             :     }
     486                 :             :     /* merge atoms together: 3. Update atom numbers */
     487                 :           0 :     icomp = 0;
     488         [ #  # ]:           0 :     for (k = 0; k < num_components; k++)
     489                 :             :     {
     490                 :           0 :         iCurAtomOffs = nAtomOffs[k];
     491                 :           0 :         iNxtAtomOffs = nAtomOffs[k + 1];
     492                 :           0 :         iCurDelHOffs = nDelHOffs[k];
     493                 :           0 :         iNxtDelHOffs = nDelHOffs[k + 1];
     494                 :           0 :         len = nAtomOffs[k + 1] - nAtomOffs[k]; /* number of atoms in a component excluding explicit H */
     495                 :           0 :         iShiftH = iCurDelHOffs - len;
     496         [ #  # ]:           0 :         if (!len)
     497                 :             :         {
     498                 :           0 :             continue;
     499                 :             :         }
     500                 :           0 :         icomp++; /* current component number */
     501                 :             :         /* update atoms */
     502         [ #  # ]:           0 :         for (i = iCurAtomOffs; i < iNxtAtomOffs; i++)
     503                 :             :         {
     504                 :             : 
     505                 :           0 :             a = at + i;
     506                 :             : 
     507                 :           0 :             a->endpoint = 0;
     508                 :           0 :             a->bAmbiguousStereo = 0;
     509                 :           0 :             a->at_type = 0;
     510                 :           0 :             a->bCutVertex = 0;
     511                 :           0 :             a->bUsed0DParity = 0;
     512                 :           0 :             a->cFlags = 0;
     513                 :           0 :             a->nBlockSystem = 0;
     514                 :           0 :             a->nNumAtInRingSystem = 0;
     515                 :           0 :             a->nRingSystem = 0;
     516                 :             :             /* djb-rwth: addressing coverity ID #499524 -- initialisation with at */
     517                 :             : 
     518         [ #  # ]:           0 :             for (j = 0; j < a->valence; j++)
     519                 :             :             {
     520         [ #  # ]:           0 :                 if (a->neighbor[j] < len)
     521                 :             :                 {
     522                 :           0 :                     a->neighbor[j] += iCurAtomOffs; /* atom */
     523                 :             :                 }
     524                 :             :                 else
     525                 :             :                 {
     526                 :           0 :                     a->neighbor[j] += iShiftH;      /* explicit H */
     527                 :             :                 }
     528                 :             :             }
     529                 :           0 :             a->orig_at_number += iCurAtomOffs;
     530                 :           0 :             a->component = icomp;
     531         [ #  # ]:           0 :             if (a->p_parity)
     532                 :             :             {
     533         [ #  # ]:           0 :                 for (j = 0; j < MAX_NUM_STEREO_ATOM_NEIGH; j++)
     534                 :             :                 {
     535         [ #  # ]:           0 :                     if (a->p_orig_at_num[j] <= len)
     536                 :             :                     {
     537                 :             :                         /* originally, orig_at_num = atom_index+1, therefore <= instead of < */
     538                 :           0 :                         a->p_orig_at_num[j] += iCurAtomOffs;
     539                 :             :                     }
     540                 :             :                     else
     541                 :             :                     {
     542                 :           0 :                         a->p_orig_at_num[j] += iShiftH;
     543                 :             :                     }
     544                 :             :                 }
     545                 :             :             }
     546   [ #  #  #  # ]:           0 :             for (j = 0; j < MAX_NUM_STEREO_BONDS && a->sb_parity[j]; j++)
     547                 :             :             {
     548         [ #  # ]:           0 :                 if (a->sn_orig_at_num[j] <= len)
     549                 :             :                 {
     550                 :             :                     /* originally, orig_at_num = atom_index+1, therefore <= instead of < */
     551                 :           0 :                     a->sn_orig_at_num[j] += iCurAtomOffs;
     552                 :             :                 }
     553                 :             :                 else
     554                 :             :                 {
     555                 :           0 :                     a->sn_orig_at_num[j] += iShiftH;
     556                 :             :                 }
     557                 :             :             }
     558                 :             :         }
     559                 :             :         /* update fixed-H */
     560         [ #  # ]:           0 :         for (i = iCurDelHOffs; i < iNxtDelHOffs; i++)
     561                 :             :         {
     562                 :           0 :             a = at + i;
     563                 :           0 :             a->neighbor[0] += iCurAtomOffs;
     564                 :           0 :             a->orig_at_number += iShiftH;
     565                 :             :         }
     566                 :             :     }
     567                 :             :     /* save the results */
     568                 :           0 :     pOneInput->atom = at;
     569                 :           0 :     pOneInput->num_atoms = tot_atoms;
     570                 :           0 :     at = NULL;
     571                 :             : 
     572                 :           0 : exit_function:
     573   [ #  #  #  # ]:           0 :     if (at)        inchi_free(at);  /* in case of failure */
     574   [ #  #  #  # ]:           0 :     if (nAtomOffs) inchi_free(nAtomOffs);
     575   [ #  #  #  # ]:           0 :     if (nDelHOffs) inchi_free(nDelHOffs);
     576                 :           0 :     return ret;
     577                 :             : }
     578                 :             : 
     579                 :             : 
     580                 :             : #ifndef COMPILE_ANSI_ONLY
     581                 :             : 
     582                 :             : 
     583                 :             : static PER_DRAW_PARMS pdp;
     584                 :             : 
     585                 :             : 
     586                 :             : /****************************************************************************/
     587                 :             : int DisplayAllRestoredComponents(struct tagCANON_GLOBALS* pCG,
     588                 :             :     inp_ATOM* at,
     589                 :             :     int num_at,
     590                 :             :     const char* szCurHdr)
     591                 :             : {
     592                 :             :     int    ret; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     593                 :             :     char     szTitle[512];
     594                 :             :     DRAW_PARMS dp;
     595                 :             :     TBL_DRAW_PARMS tdp;
     596                 :             :     if (num_at <= 0)
     597                 :             :     {
     598                 :             :         return 0;
     599                 :             :     }
     600                 :             :     memset(&dp, 0, sizeof(dp)); /* djb-rwth: memset_s C11/Annex K variant? */
     601                 :             :     memset(&tdp, 0, sizeof(tdp)); /* djb-rwth: memset_s C11/Annex K variant? */
     602                 :             :     /*memset( &pdp, 0, sizeof(pdp) );*/
     603                 :             :     dp.sdp.tdp = &tdp;
     604                 :             :     dp.pdp = &pdp;
     605                 :             :     dp.sdp.nFontSize = -9;
     606                 :             :     sprintf(szTitle, "All Components of Restored %s Structure", szCurHdr ? szCurHdr : "(No structure name)");
     607                 :             :     ret = DisplayStructure(pCG, at, num_at,
     608                 :             :         NULL, /* OAD_Polymer *polymer, */
     609                 :             :         0 /* nNumDeletedH*/, 0 /*bAdd_DT_to_num_H*/,
     610                 :             :         0 /*nNumRemovedProtons*/, NULL /*NUM_H *nNumRemovedProtonsIsotopic*/,
     611                 :             :         1 /*int bIsotopic*/, 0 /*bTautomeric*/,
     612                 :             :         NULL /* pINChI */, NULL /* INChI_Aux **cur_INChI_Aux*/,
     613                 :             :         0 /*bAbcNumbers*/, &dp, 0 /*INCHI_MODE nMode*/, szTitle); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     614                 :             : 
     615                 :             :     return 0;
     616                 :             : }
     617                 :             : 
     618                 :             : 
     619                 :             : /****************************************************************************/
     620                 :             : int DisplayOneRestoredComponent(struct tagCANON_GLOBALS* pCG,
     621                 :             :     StrFromINChI* pStruct,
     622                 :             :     inp_ATOM* at,
     623                 :             :     int iComponent,
     624                 :             :     int nNumComponents,
     625                 :             :     int bMobileH,
     626                 :             :     const char* szCurHdr)
     627                 :             : {
     628                 :             :     int    ret, k; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     629                 :             :     int    num_at = pStruct->num_atoms;
     630                 :             :     XYZ_COORD* pxyz = pStruct->pXYZ;
     631                 :             :     char     szTitle[512];
     632                 :             :     DRAW_PARMS dp;
     633                 :             :     TBL_DRAW_PARMS tdp;
     634                 :             :     int         iInchiRec = pStruct->iInchiRec;
     635                 :             :     int         iMobileH = pStruct->iMobileH;
     636                 :             :     INChI** pInChI = NULL;
     637                 :             :     INChI_Aux** pAux = NULL;
     638                 :             :     int         nNumRemovedProtons = pAux ? pAux[iMobileH]->nNumRemovedProtons : 0;
     639                 :             :     NUM_H* nNumRemovedProtonsIsotopic = pAux ? pAux[iMobileH]->nNumRemovedIsotopicH : NULL;
     640                 :             : 
     641                 :             : 
     642                 :             :     if (num_at <= 0 || !pxyz)
     643                 :             :     {
     644                 :             :         return 0;
     645                 :             :     }
     646                 :             :     if (iInchiRec && !pStruct->RevInChI.pINChI_Aux[iInchiRec][0])
     647                 :             :     {
     648                 :             :         iInchiRec = 0;
     649                 :             :     }
     650                 :             :     k = iMobileH;
     651                 :             :     if (!bRevInchiComponentExists(pStruct, iInchiRec, k, 0))
     652                 :             :     {
     653                 :             :         k = ALT_TAUT(k);
     654                 :             :     }
     655                 :             :     pInChI = pStruct->RevInChI.pINChI[iInchiRec][0];
     656                 :             :     pAux = pStruct->RevInChI.pINChI_Aux[iInchiRec][0];
     657                 :             : 
     658                 :             : 
     659                 :             :     memset(&dp, 0, sizeof(dp)); /* djb-rwth: memset_s C11/Annex K variant? */
     660                 :             :     memset(&tdp, 0, sizeof(tdp)); /* djb-rwth: memset_s C11/Annex K variant? */
     661                 :             :     /*memset( &pdp, 0, sizeof(pdp) );*/
     662                 :             :     dp.sdp.tdp = &tdp;
     663                 :             :     dp.pdp = &pdp;
     664                 :             :     dp.sdp.nFontSize = -9;
     665                 :             :     sprintf(szTitle, "Restored %s Component %d of %d %c%c",
     666                 :             :         szCurHdr ? szCurHdr : "(No structure name)", iComponent + 1, nNumComponents,
     667                 :             :         pStruct->iInchiRec ? 'R' : 'D', pStruct->iMobileH ? 'M' : 'F');
     668                 :             :     ret = DisplayStructure(pCG, at, num_at,
     669                 :             :         NULL, /* OAD_Polymer *polymer, */
     670                 :             :         0 /* nNumDeletedH*/, 0 /*bAdd_DT_to_num_H*/,
     671                 :             :         nNumRemovedProtons, /*NULL*/ nNumRemovedProtonsIsotopic,
     672                 :             :         1 /*int bIsotopic*/, k,
     673                 :             :         pInChI, pAux,
     674                 :             :         0 /*bAbcNumbers*/, &dp, 0 /*INCHI_MODE nMode*/, szTitle); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     675                 :             : 
     676                 :             :     return 0;
     677                 :             : }
     678                 :             : 
     679                 :             : 
     680                 :             : /****************************************************************************/
     681                 :             : int DisplayRestoredComponent(struct tagCANON_GLOBALS* pCG,
     682                 :             :     StrFromINChI* pStruct,
     683                 :             :     int iComponent,
     684                 :             :     int iAtNoOffset,
     685                 :             :     INChI* pInChI,
     686                 :             :     const char* szCurHdr)
     687                 :             : {
     688                 :             :     int    i, ret; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     689                 :             :     int    num_at = pStruct->num_atoms;
     690                 :             :     int    num_deleted_H = pStruct->num_deleted_H;
     691                 :             :     inp_ATOM* atom = pStruct->at2;
     692                 :             :     XYZ_COORD* pxyz = pStruct->pXYZ;
     693                 :             :     inp_ATOM* at = NULL;
     694                 :             :     char     szTitle[512];
     695                 :             :     DRAW_PARMS dp;
     696                 :             :     TBL_DRAW_PARMS tdp;
     697                 :             :     if (!atom || num_at <= 0 || !pxyz)
     698                 :             :     {
     699                 :             :         return 0;
     700                 :             :     }
     701                 :             :     at = (inp_ATOM*)inchi_calloc((long long)num_at + (long long)num_deleted_H, sizeof(at[0])); /* djb-rwth: cast operator added */
     702                 :             :     if (!at)
     703                 :             :     {
     704                 :             :         return RI_ERR_ALLOC;
     705                 :             :     }
     706                 :             :     memcpy(at, atom, ((long long)num_at + (long long)num_deleted_H) * sizeof(at[0])); /* djb-rwth: cast operator added */
     707                 :             :     for (i = 0; i < num_at; i++)
     708                 :             :     {
     709                 :             :         at[i].x = pxyz[i].xyz[0];
     710                 :             :         at[i].y = pxyz[i].xyz[1];
     711                 :             :         at[i].z = pxyz[i].xyz[2];
     712                 :             :     }
     713                 :             :     memset(&dp, 0, sizeof(dp)); /* djb-rwth: memset_s C11/Annex K variant? */
     714                 :             :     memset(&tdp, 0, sizeof(tdp)); /* djb-rwth: memset_s C11/Annex K variant? */
     715                 :             :     /*memset( &pdp, 0, sizeof(pdp) );*/
     716                 :             :     dp.sdp.tdp = &tdp;
     717                 :             :     dp.pdp = &pdp;
     718                 :             :     dp.sdp.nFontSize = -9;
     719                 :             :     sprintf(szTitle, "DBG Restored %s Component %d %c%c", szCurHdr ? szCurHdr : "(No structure name)", iComponent + 1, pStruct->iInchiRec ? 'R' : 'D', pStruct->iMobileH ? 'M' : 'F');
     720                 :             : 
     721                 :             :     ret = DisplayStructure(pCG, at, num_at,
     722                 :             :         NULL, /* OAD_Polymer *polymer, */
     723                 :             :         0 /* nNumDeletedH*/, 0 /*bAdd_DT_to_num_H*/,
     724                 :             :         0 /*nNumRemovedProtons*/, NULL /*NUM_H *nNumRemovedProtonsIsotopic*/,
     725                 :             :         1 /*int bIsotopic*/, 0 /*bTautomeric*/,
     726                 :             :         &pInChI, NULL /* INChI_Aux **cur_INChI_Aux*/,
     727                 :             :         0 /*bAbcNumbers*/, &dp, 0 /*INCHI_MODE nMode*/, szTitle); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     728                 :             : 
     729                 :             :     inchi_free(at);
     730                 :             : 
     731                 :             :     return 0;
     732                 :             : }
     733                 :             : 
     734                 :             : 
     735                 :             : /****************************************************************************/
     736                 :             : int DisplayStructureComponents(struct tagCANON_GLOBALS* pCG,
     737                 :             :     ICHICONST INPUT_PARMS* ip,
     738                 :             :     STRUCT_DATA* sd,
     739                 :             :     long num_inp,
     740                 :             :     char* szCurHdr,
     741                 :             :     ICHICONST SRM* pSrm,
     742                 :             :     int bReqNonTaut,
     743                 :             :     StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
     744                 :             :     InpInChI* pOneInput)
     745                 :             : {
     746                 :             :     int iInchiRec, iMobileH,
     747                 :             :         iCurMobH = -1,
     748                 :             :         iAlternH, num_components, tot_just_atoms, tot_atoms, cur_nA, cur_nH; /* djb-rwth: removing redundant variables */
     749                 :             :     int k, i, j, ret, iCurAtomOffs, iNxtAtomOffs, len, len2; /* djb-rwth: removing redundant variables; removing redundant variables/code */
     750                 :             :     int* nAtomOffs = NULL, * nDelHOffs = NULL, iNewCoord = 0, nNewCoord = 0; /* djb-rwth: removing redundant variables */
     751                 :             :     double x_max = -1.0e16, x_min = 1.0e16, y_max = -1.0e16, y_min = 1.0e16, delta = 0.0;
     752                 :             :     StrFromINChI* pStruct1;
     753                 :             :     inp_ATOM* at = NULL, * a;
     754                 :             : 
     755                 :             :     if (!ip->bDisplayCompositeResults && !ip->bDisplay)
     756                 :             :     {
     757                 :             :         return 0;
     758                 :             :     }
     759                 :             : 
     760                 :             :     ret = 0;
     761                 :             :     pOneInput->num_atoms = 0;
     762                 :             :     /* select highest detail level */
     763                 :             :     if ((num_components = pOneInput->nNumComponents[INCHI_REC][TAUT_NON])) /* djb-rwth: addressing LLVM warning */
     764                 :             :     {
     765                 :             :         iInchiRec = INCHI_REC;
     766                 :             :         iMobileH = TAUT_NON;
     767                 :             :     }
     768                 :             :     else
     769                 :             :     {
     770                 :             :         if ((num_components = pOneInput->nNumComponents[INCHI_REC][TAUT_YES])) /* djb-rwth: addressing LLVM warning */
     771                 :             :         {
     772                 :             :             iInchiRec = INCHI_REC;
     773                 :             :             iMobileH = TAUT_YES;
     774                 :             :         }
     775                 :             :         else
     776                 :             :         {
     777                 :             :             if ((num_components = pOneInput->nNumComponents[INCHI_BAS][TAUT_NON])) /* djb-rwth: addressing LLVM warning */
     778                 :             :             {
     779                 :             :                 iInchiRec = INCHI_BAS;
     780                 :             :                 iMobileH = TAUT_NON;
     781                 :             :             }
     782                 :             :             else
     783                 :             :             {
     784                 :             :                 if ((num_components = pOneInput->nNumComponents[INCHI_BAS][TAUT_YES])) /* djb-rwth: addressing LLVM warning */
     785                 :             :                 {
     786                 :             :                     iInchiRec = INCHI_BAS;
     787                 :             :                     iMobileH = TAUT_YES;
     788                 :             :                 }
     789                 :             :                 else
     790                 :             :                 {
     791                 :             :                     return 0; /* no components available */
     792                 :             :                 }
     793                 :             :             }
     794                 :             :         }
     795                 :             :     }
     796                 :             : 
     797                 :             :     for (k = 0; k < num_components; k++)
     798                 :             :     {
     799                 :             :         if (pStruct[iInchiRec][iMobileH][k].bDeleted)
     800                 :             :         {
     801                 :             :             break;
     802                 :             :         }
     803                 :             :     }
     804                 :             :     num_components = k;
     805                 :             : 
     806                 :             :     nAtomOffs = (int*)inchi_malloc(((long long)num_components + 1) * sizeof(nAtomOffs[0])); /* djb-rwth: cast operator added */
     807                 :             :     nDelHOffs = (int*)inchi_malloc(((long long)num_components + 1) * sizeof(nDelHOffs[0])); /* djb-rwth: cast operator added */
     808                 :             :     if (!nAtomOffs || !nDelHOffs)
     809                 :             :     {
     810                 :             :         ret = RI_ERR_ALLOC;
     811                 :             :         goto exit_function;
     812                 :             :     }
     813                 :             : 
     814                 :             :     /* count number of atoms and removed H */
     815                 :             :     /* djb-rwth: removing redundant code */
     816                 :             :     iAlternH = (iMobileH == TAUT_NON && pOneInput->nNumComponents[iInchiRec][TAUT_YES]) ? TAUT_YES : -1;
     817                 :             :     nAtomOffs[0] = nDelHOffs[0] = 0;
     818                 :             : 
     819                 :             :     for (k = 0; k < num_components; k++)
     820                 :             :     {
     821                 :             :         pStruct1 = pStruct[iInchiRec][iMobileH][k].num_atoms ? pStruct[iInchiRec][iMobileH] + k :
     822                 :             :             iAlternH >= 0 &&
     823                 :             :             pStruct[iInchiRec][iAlternH][k].num_atoms ? pStruct[iInchiRec][iAlternH] + k : NULL;
     824                 :             :         if (!pStruct1 || !pStruct1->at2 || !pStruct1->num_atoms)
     825                 :             :         {
     826                 :             :             cur_nA = cur_nH = 0;
     827                 :             :         }
     828                 :             :         else
     829                 :             :         {
     830                 :             :             cur_nA = pStruct1->num_atoms;
     831                 :             :             cur_nH = pStruct1->num_deleted_H;
     832                 :             :             if (cur_nA && !pStruct1->pXYZ)
     833                 :             :             {
     834                 :             :                 if (!k)
     835                 :             :                 {
     836                 :             :                     ret = 0; /* no coordinates available */
     837                 :             :                     goto exit_function;
     838                 :             :                 }
     839                 :             :                 /* djb-rwth: removing redundant code */
     840                 :             :             }
     841                 :             :         }
     842                 :             :         nAtomOffs[k + 1] = nAtomOffs[k] + cur_nA;
     843                 :             :         nDelHOffs[k + 1] = nDelHOffs[k] + cur_nH;
     844                 :             :     }
     845                 :             :     tot_just_atoms = nAtomOffs[num_components];
     846                 :             : 
     847                 :             :     /* shift all H to the end */
     848                 :             :     for (k = 0; k <= num_components; k++)
     849                 :             :     {
     850                 :             :         nDelHOffs[k] += tot_just_atoms;
     851                 :             :     }
     852                 :             :     tot_atoms = nDelHOffs[num_components];
     853                 :             : 
     854                 :             :     /* merge atoms together: 1. Allocate */
     855                 :             :     if (NULL == (at = (inp_ATOM*)inchi_malloc(((long long)tot_atoms + 1) * sizeof(at[0])))) /* djb-rwth: cast operator added */
     856                 :             :     {
     857                 :             :         ret = RI_ERR_ALLOC;
     858                 :             :         goto exit_function;
     859                 :             :     }
     860                 :             :     if (!tot_atoms)
     861                 :             :     {
     862                 :             :         ret = 0;
     863                 :             :         goto exit_function; /* empty structure */
     864                 :             :     }
     865                 :             : 
     866                 :             :     /* merge atoms together: 2. Copy */
     867                 :             :     for (k = 0; k < num_components; k++)
     868                 :             :     {
     869                 :             :         pStruct1 = pStruct[iInchiRec][iMobileH][k].num_atoms ? pStruct[iInchiRec][iCurMobH = iMobileH] + k :
     870                 :             :             iAlternH >= 0 &&
     871                 :             :             pStruct[iInchiRec][iAlternH][k].num_atoms ? pStruct[iInchiRec][iCurMobH = iAlternH] + k : NULL;
     872                 :             :         if ((len = nAtomOffs[k + 1] - nAtomOffs[k]) && pStruct1) /* djb-rwth: addressing LLVM warning */
     873                 :             :         {
     874                 :             :             XYZ_COORD* pxyz = pStruct1->pXYZ;
     875                 :             :             len2 = nDelHOffs[k + 1] - nDelHOffs[k]; /* do not separate H from the atom: we will not need them */
     876                 :             :             iCurAtomOffs = nAtomOffs[k];
     877                 :             :             a = at + iCurAtomOffs;
     878                 :             :             memcpy(a, pStruct1->at2, ((long long)len + (long long)len2) * sizeof(at[0])); /* djb-rwth: cast operator added */
     879                 :             :             DisconnectedConnectedH(a, len, len2);
     880                 :             :             if (pxyz)
     881                 :             :             {
     882                 :             :                 for (i = 0; i < len; i++)
     883                 :             :                 {
     884                 :             :                     a[i].x = pxyz[i].xyz[0];
     885                 :             :                     x_max = inchi_max(x_max, pxyz[i].xyz[0]);
     886                 :             :                     x_min = inchi_min(x_min, pxyz[i].xyz[0]);
     887                 :             :                     a[i].y = pxyz[i].xyz[1];
     888                 :             :                     y_max = inchi_max(y_max, pxyz[i].xyz[1]);
     889                 :             :                     y_min = inchi_min(y_min, pxyz[i].xyz[1]);
     890                 :             :                     a[i].z = pxyz[i].xyz[2];
     891                 :             :                     nNewCoord++;
     892                 :             :                 }
     893                 :             :             }
     894                 :             :             else
     895                 :             :             {
     896                 :             :                 if (!iNewCoord)
     897                 :             :                 {
     898                 :             :                     if (!nNewCoord)
     899                 :             :                     {
     900                 :             :                         ret = 0;
     901                 :             :                         goto exit_function; /* empty structure */
     902                 :             :                     }
     903                 :             :                     delta = inchi_max(x_max - x_min, y_max - y_min);
     904                 :             :                     if (delta == 0.0)
     905                 :             :                     {
     906                 :             :                         delta = 0.5 * (x_max + x_min);
     907                 :             :                         if (delta == 0.0)
     908                 :             :                             delta = 1.0;
     909                 :             :                     }
     910                 :             :                     else
     911                 :             :                     {
     912                 :             :                         delta /= sqrt((double)((long long)nNewCoord + 1)); /* djb-rwth: cast operator added */
     913                 :             :                     }
     914                 :             :                 }
     915                 :             :                 for (i = 0; i < len; i++)
     916                 :             :                 {
     917                 :             :                     a[i].x = x_max + delta;
     918                 :             :                     a[i].y = y_max - iNewCoord * delta;
     919                 :             :                     a[i].z = 0.0;
     920                 :             :                     iNewCoord++;
     921                 :             :                 }
     922                 :             :                 if ((pStruct1->pXYZ = (XYZ_COORD*)inchi_calloc(len, sizeof(pStruct1->pXYZ[0])))) /* djb-rwth: addressing LLVM warning */
     923                 :             :                 {
     924                 :             : 
     925                 :             :                     for (i = 0; i < len; i++)
     926                 :             :                     {
     927                 :             :                         pStruct1->pXYZ[i].xyz[0] = a[i].x;
     928                 :             :                         pStruct1->pXYZ[i].xyz[1] = a[i].y;
     929                 :             :                         pStruct1->pXYZ[i].xyz[2] = 0.0;
     930                 :             :                     }
     931                 :             :                 }
     932                 :             :             }
     933                 :             :             if (ip->bDisplay || (ip->bDisplayCompositeResults && 1 == num_components)) /* djb-rwth: addressing LLVM warning */
     934                 :             :             {
     935                 :             :                 DisplayOneRestoredComponent(pCG, pStruct1, a, k, num_components, iCurMobH, szCurHdr);
     936                 :             :             }
     937                 :             :             if (!pxyz && pStruct1->pXYZ)
     938                 :             :             {
     939                 :             :                 inchi_free(pStruct1->pXYZ);
     940                 :             :                 pStruct1->pXYZ = NULL;
     941                 :             :             }
     942                 :             :         }
     943                 :             :     }
     944                 :             : 
     945                 :             :     /* merge atoms together: 3. Update atom numbers */
     946                 :             :     /* djb-rwth: removing redundant code */
     947                 :             :     if (ip->bDisplayCompositeResults && num_components > 1)
     948                 :             :     {
     949                 :             :         for (k = 0; k < num_components; k++)
     950                 :             :         {
     951                 :             :             /* display each restored component if requested */
     952                 :             :             iCurAtomOffs = nAtomOffs[k];
     953                 :             :             iNxtAtomOffs = nAtomOffs[k + 1];
     954                 :             :             /* djb-rwth: removing redundant code */
     955                 :             :             /* djb-rwth: removing redundant code */
     956                 :             :             len = nAtomOffs[k + 1] - nAtomOffs[k]; /* number of atoms in a component excluding explicit H */
     957                 :             :             /* djb-rwth: removing redundant code */
     958                 :             :             if (!len)
     959                 :             :             {
     960                 :             :                 continue;
     961                 :             :             }
     962                 :             :             /* djb-rwth: removing redundant code */
     963                 :             :             /* update atoms */
     964                 :             :             for (i = iCurAtomOffs; i < iNxtAtomOffs; i++)
     965                 :             :             {
     966                 :             :                 a = at + i;
     967                 :             :                 for (j = 0; j < a->valence; j++)
     968                 :             :                 {
     969                 :             :                     if (a->neighbor[j] < len)
     970                 :             :                     {
     971                 :             :                         a->neighbor[j] += iCurAtomOffs; /* atom */
     972                 :             :                     }
     973                 :             :                     else
     974                 :             :                     {
     975                 :             :                         ret = RI_ERR_PROGR;  /* explicit H */
     976                 :             :                         goto exit_function;
     977                 :             :                     }
     978                 :             :                 }
     979                 :             :                 a->orig_at_number += iCurAtomOffs;
     980                 :             :             }
     981                 :             :         }
     982                 :             :         tot_atoms = nAtomOffs[num_components];
     983                 :             :         DisplayAllRestoredComponents(pCG, at, tot_atoms, szCurHdr);
     984                 :             :     }
     985                 :             : 
     986                 :             : exit_function:
     987                 :             : 
     988                 :             :     if (at)
     989                 :             :     {
     990                 :             :         inchi_free(at);  /* in case of failure */
     991                 :             :     }
     992                 :             :     if (nAtomOffs)
     993                 :             :     {
     994                 :             :         inchi_free(nAtomOffs);
     995                 :             :     }
     996                 :             :     if (nDelHOffs)
     997                 :             :     {
     998                 :             :         inchi_free(nDelHOffs);
     999                 :             :     }
    1000                 :             : 
    1001                 :             :     return ret;
    1002                 :             : }
    1003                 :             : #endif
    1004                 :             : 
    1005                 :             : 
    1006                 :             : /****************************************************************************/
    1007                 :           0 : int AllInchiToStructure(INCHI_CLOCK* ic,
    1008                 :             :     CANON_GLOBALS* pCG,
    1009                 :             :     ICHICONST INPUT_PARMS* ip_inp,
    1010                 :             :     STRUCT_DATA* sd_inp,
    1011                 :             :     long num_inp,
    1012                 :             :     char* szCurHdr,
    1013                 :             :     ICHICONST SRM* pSrm,
    1014                 :             :     int bHasSomeFixedH,
    1015                 :             :     StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
    1016                 :             :     InpInChI* pOneInput)
    1017                 :             : {
    1018                 :             :     int iInchiRec, iMobileH, cur_num_comp, bCurI2A_Flag, k, ret, num_err;
    1019                 :             :     int iAtNoOffset;
    1020                 :             :     INPUT_PARMS* ip, ip_loc;
    1021                 :             :     STRUCT_DATA* sd, sd_loc;
    1022                 :           0 :     long          ulProcessingTime = 0;
    1023                 :             :     inchiTime     ulTStart;
    1024                 :             : 
    1025                 :           0 :     InchiTimeGet(&ulTStart);
    1026                 :           0 :     ip = &ip_loc;
    1027                 :           0 :     *ip = *ip_inp;
    1028                 :           0 :     sd = &sd_loc;
    1029                 :           0 :     memset(sd, 0, sizeof(*sd)); /* djb-rwth: memset_s C11/Annex K variant? */
    1030                 :           0 :     sd->ulStructTime = sd_inp->ulStructTime;
    1031                 :           0 :     ret = 0;
    1032                 :           0 :     num_err = 0;
    1033         [ #  # ]:           0 :     for (iInchiRec = 0; iInchiRec < INCHI_NUM; iInchiRec++)
    1034                 :             :     {
    1035                 :             :         /* Disconnected/Connected */
    1036         [ #  # ]:           0 :         for (iMobileH = 0; iMobileH < TAUT_NUM; iMobileH++)
    1037                 :             :         {
    1038                 :             :             /* Mobile/Fixed H */
    1039                 :           0 :             cur_num_comp = pOneInput->nNumComponents[iInchiRec][iMobileH];
    1040         [ #  # ]:           0 :             if (!cur_num_comp)
    1041                 :             :             {
    1042                 :           0 :                 continue;
    1043                 :             :             }
    1044                 :             :             /* allocate memory for all existing components */
    1045                 :           0 :             pStruct[iInchiRec][iMobileH] = (StrFromINChI*)inchi_calloc(cur_num_comp, sizeof(pStruct[0][0][0]));
    1046         [ #  # ]:           0 :             if (!pStruct[iInchiRec][iMobileH])
    1047                 :             :             {
    1048                 :           0 :                 ret = RI_ERR_ALLOC;
    1049                 :           0 :                 goto exit_error;
    1050                 :             :             }
    1051                 :             :             /* set conversion mode */
    1052         [ #  # ]:           0 :             bCurI2A_Flag = (iMobileH ? 0 : I2A_FLAG_FIXEDH) | (iInchiRec ? I2A_FLAG_RECMET : 0);
    1053         [ #  # ]:           0 :             if (iMobileH)
    1054                 :             :             {
    1055                 :           0 :                 ip->nMode &= ~REQ_MODE_BASIC;
    1056                 :             :             }
    1057                 :             :             else
    1058                 :             :             {
    1059                 :           0 :                 ip->nMode |= REQ_MODE_BASIC;
    1060                 :             :             }
    1061                 :             :             /* InChI --> structure conversion for all components except duplicated */
    1062                 :           0 :             iAtNoOffset = 0;
    1063         [ #  # ]:           0 :             for (k = 0; k < cur_num_comp; k++)
    1064                 :             :             {
    1065                 :             :                 /* components */
    1066   [ #  #  #  # ]:           0 :                 if ((!iMobileH && !pOneInput->pInpInChI[iInchiRec][iMobileH][k].nNumberOfAtoms) ||
    1067         [ #  # ]:           0 :                     pOneInput->pInpInChI[iInchiRec][iMobileH][k].bDeleted ||
    1068         [ #  # ]:           0 :                     pOneInput->pInpInChI[iInchiRec][iMobileH][k].nLink < 0) /* djb-rwth: addressing LLVM warning */
    1069                 :             :                 {
    1070                 :           0 :                     pStruct[iInchiRec][iMobileH][k].nLink = pOneInput->pInpInChI[iInchiRec][iMobileH][k].nLink;
    1071                 :           0 :                     pStruct[iInchiRec][iMobileH][k].bDeleted = pOneInput->pInpInChI[iInchiRec][iMobileH][k].bDeleted;
    1072                 :           0 :                     continue; /* do not create a structure out of an unavailable
    1073                 :             :                                  Fixed-H InChI or out of the one present in Reconnected layer */
    1074                 :             : 
    1075                 :             : #ifdef NEVER  /* a wrong attempt to process deleted components here */
    1076                 :             :                     if (pStruct[iInchiRec][iMobileH][k].nLink = pOneInput->pInpInChI[iInchiRec][iMobileH][k].nLink)
    1077                 :             :                     {
    1078                 :             :                         continue; /* do not create a structure out of an unavailable
    1079                 :             :                                      Fixed-H InChI or out of the one present in Reconnected layer */
    1080                 :             :                     }
    1081                 :             :                     else
    1082                 :             :                         if (iMobileH && pOneInput->pInpInChI[iInchiRec][iMobileH][k].nNumberOfAtoms &&
    1083                 :             :                             pOneInput->pInpInChI[iInchiRec][iMobileH][k].bDeleted &&
    1084                 :             :                             pOneInput->pInpInChI[iInchiRec][iMobileH][0].bDeleted)
    1085                 :             :                         {
    1086                 :             :                             /* all components are protons */
    1087                 :             :                             ;
    1088                 :             :                         }
    1089                 :             :                         else
    1090                 :             :                         {
    1091                 :             :                             continue;
    1092                 :             :                         }
    1093                 :             : #endif
    1094                 :             : 
    1095                 :             :                 }
    1096   [ #  #  #  #  :           0 :                 if (bHasSomeFixedH && iMobileH && k < pOneInput->nNumComponents[iInchiRec][TAUT_NON] &&
                   #  # ]
    1097         [ #  # ]:           0 :                     pOneInput->pInpInChI[iInchiRec][TAUT_NON][k].nNumberOfAtoms)
    1098                 :             :                 {
    1099                 :           0 :                     continue; /* do not process Mobile-H if Fixed-H is requested and exists */
    1100                 :             :                 }
    1101                 :           0 :                 pStruct[iInchiRec][iMobileH][k].pSrm = pSrm;
    1102                 :           0 :                 pStruct[iInchiRec][iMobileH][k].iInchiRec = iInchiRec;
    1103                 :           0 :                 pStruct[iInchiRec][iMobileH][k].iMobileH = iMobileH;
    1104                 :             : 
    1105                 :             :                 /****************************************************/
    1106                 :             :                 /*                                                  */
    1107                 :             :                 /* Convert InChI of one component into a Structure  */
    1108                 :             :                 /*                                                  */
    1109                 :             :                 /****************************************************/
    1110                 :             : 
    1111                 :           0 :                 ret = InChI2Atom(ic, pCG, ip, sd, szCurHdr, num_inp, pStruct[iInchiRec][iMobileH] + k, k,
    1112                 :             :                     iAtNoOffset /* 0*/, bCurI2A_Flag, bHasSomeFixedH, pOneInput);
    1113                 :           0 :                 pStruct[iInchiRec][iMobileH][k].nLink = pOneInput->pInpInChI[iInchiRec][iMobileH][k].nLink;
    1114         [ #  # ]:           0 :                 if (ret < 0)
    1115                 :             :                 {
    1116                 :             : #if ( bRELEASE_VERSION != 1 )
    1117                 :             : #ifndef TARGET_API_LIB
    1118                 :             :                     /* !!! Conversion Error -- Ignore for now !!! */
    1119                 :             :                     fprintf(stdout, "%ld %s Conversion failed: %d, %c%c comp %d\n",
    1120                 :             :                         num_inp, szCurHdr ? szCurHdr : "Struct", ret, iInchiRec ? 'R' : 'D', iMobileH ? 'M' : 'F', k + 1);
    1121                 :             : #endif
    1122                 :             : #endif
    1123         [ #  # ]:           0 :                     if (ret == CT_USER_QUIT_ERR)
    1124                 :             :                     {
    1125                 :           0 :                         goto exit_error;
    1126                 :             :                     }
    1127                 :           0 :                     pStruct[iInchiRec][iMobileH][k].nError = ret;
    1128                 :           0 :                     ret = 0; /* force to ignore the errors for now !!!! */
    1129                 :           0 :                     num_err++;
    1130                 :             :                 }
    1131                 :           0 :                 iAtNoOffset += pOneInput->pInpInChI[iInchiRec][iMobileH][k].nNumberOfAtoms;
    1132                 :             :             } /* k-th component */
    1133                 :             :         }
    1134                 :             :     }
    1135                 :             : 
    1136                 :           0 : exit_error:
    1137                 :           0 :     ulProcessingTime += InchiTimeElapsed(ic, &ulTStart);
    1138                 :           0 :     sd->ulStructTime += ulProcessingTime;
    1139                 :             : 
    1140         [ #  # ]:           0 :     return ret < 0 ? ret : num_err;
    1141                 :             : }
    1142                 :             : 
    1143                 :             : 
    1144                 :             : /****************************************************************************/
    1145                 :           0 : int AddProtonAndIsoHBalanceToMobHStruct(INCHI_CLOCK* ic,
    1146                 :             :     CANON_GLOBALS* pCG,
    1147                 :             :     ICHICONST INPUT_PARMS* ip,
    1148                 :             :     STRUCT_DATA* sd,
    1149                 :             :     long num_inp,
    1150                 :             :     int bHasSomeFixedH,
    1151                 :             :     char* szCurHdr,
    1152                 :             :     StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
    1153                 :             :     InpInChI* pOneInput)
    1154                 :             : {
    1155                 :             :     COMPONENT_REM_PROTONS nToBeRemovedByNormFromRevrs[INCHI_NUM];
    1156                 :             :     int                   nRemovedByNormFromRevrs[INCHI_NUM];
    1157                 :             :     int                   nRemovedByRevrs[INCHI_NUM];
    1158                 :             : 
    1159                 :           0 :     int   nDeltaFromDisconnected = 0, nRemovedProtonsByNormFromRevrs, nRemovedProtonsByRevrs; /* djb-rwth: removing redundant variables */
    1160                 :             :     NUM_H nIsoDeltaFromDisconnected[NUM_H_ISOTOPES];
    1161                 :           0 :     int iInchiRec, i, k, k1, ret = 0;
    1162                 :             :     int  nChargeInChI, nChargeRevrs;
    1163                 :             : 
    1164         [ #  # ]:           0 :     if (bHasSomeFixedH)
    1165                 :             :     {
    1166                 :           0 :         return 0; /* 2005-03-01 */
    1167                 :             :     }
    1168                 :             : 
    1169                 :             :     /* num protons removed by InChI Normalization from the original structure */
    1170         [ #  # ]:           0 :     for (i = 0; i < INCHI_NUM; i++)
    1171                 :             :     {
    1172                 :           0 :         nToBeRemovedByNormFromRevrs[i].nNumRemovedProtons = pOneInput->nNumProtons[i][TAUT_YES].nNumRemovedProtons;
    1173         [ #  # ]:           0 :         for (k = 0; k < NUM_H_ISOTOPES; k++)
    1174                 :             :         {
    1175                 :           0 :             nToBeRemovedByNormFromRevrs[i].nNumRemovedIsotopicH[k] = pOneInput->nNumProtons[i][TAUT_YES].nNumRemovedIsotopicH[k];
    1176                 :             :         }
    1177                 :             :     }
    1178                 :             :     /* accumulate here num. protons removed by the normalization from the reversed structure */
    1179                 :           0 :     nRemovedByNormFromRevrs[INCHI_BAS] =
    1180                 :           0 :         nRemovedByNormFromRevrs[INCHI_REC] = 0;
    1181                 :           0 :     nRemovedByRevrs[INCHI_REC] =
    1182                 :           0 :         nRemovedByRevrs[INCHI_BAS] = 0;
    1183                 :             :     /* protons added/removed by InChI Normalization to/from Restored Structure might have been added by StructureRestore */
    1184                 :             : 
    1185         [ #  # ]:           0 :     for (iInchiRec = 0; iInchiRec < INCHI_NUM; iInchiRec++)
    1186                 :             :     {
    1187         [ #  # ]:           0 :         for (k = 0; k < pOneInput->nNumComponents[iInchiRec][TAUT_YES]; k++)
    1188                 :             :         {
    1189         [ #  # ]:           0 :             if (!bInpInchiComponentExists(pOneInput, iInchiRec, TAUT_YES, k))
    1190                 :             :             {
    1191                 :           0 :                 continue;
    1192                 :             :             }
    1193                 :           0 :             nRemovedProtonsByNormFromRevrs = 0; /* Num protons removed from the Restored Structure by InChI Normalization */
    1194                 :           0 :             nRemovedProtonsByRevrs = 0; /* Num protons removed by the Reconstruction from the Restored Structure */
    1195   [ #  #  #  #  :           0 :             if (iInchiRec == INCHI_REC || (iInchiRec == INCHI_BAS && (pStruct[iInchiRec][TAUT_YES][k].nLink) >= 0)) /* djb-rwth: addressing LLVM warning; removing redundant code */
                   #  # ]
    1196                 :           0 :             {
    1197                 :             : 
    1198                 :           0 :                 REV_INCHI* pRevInChI = &pStruct[iInchiRec][TAUT_YES][k].RevInChI;
    1199                 :           0 :                 INChI_Aux** pINChI_Aux2 = pRevInChI->pINChI_Aux[iInchiRec][0]; /* component 0*/
    1200                 :           0 :                 INChI** pINChI_Revr = pRevInChI->pINChI[iInchiRec][0];
    1201                 :           0 :                 INChI* pINChI_Orig = pOneInput->pInpInChI[iInchiRec][TAUT_YES] + k;
    1202         [ #  # ]:           0 :                 nChargeRevrs = pINChI_Revr ? pINChI_Revr[TAUT_YES]->nTotalCharge : NO_VALUE_INT;
    1203                 :           0 :                 nChargeInChI = pINChI_Orig->nTotalCharge;
    1204         [ #  # ]:           0 :                 if (pINChI_Aux2)
    1205                 :             :                 {
    1206                 :           0 :                     nRemovedProtonsByNormFromRevrs = pINChI_Aux2[TAUT_YES]->nNumRemovedProtons;
    1207                 :             :                 }
    1208                 :           0 :                 nRemovedProtonsByRevrs = pStruct[iInchiRec][TAUT_YES][k].nNumRemovedProtonsByRevrs;
    1209                 :           0 :                 pStruct[iInchiRec][TAUT_YES][k].nChargeRevrs = nChargeRevrs;
    1210                 :           0 :                 pStruct[iInchiRec][TAUT_YES][k].nChargeInChI = nChargeInChI;
    1211                 :             :             }
    1212                 :             :             else
    1213                 :             :             {
    1214         [ #  # ]:           0 :                 if (0 <= (k1 = -(1 + pStruct[iInchiRec][TAUT_YES][k].nLink)))
    1215                 :             :                 {
    1216                 :           0 :                     REV_INCHI* pRevInChI = &pStruct[INCHI_REC][TAUT_YES][k1].RevInChI;
    1217                 :           0 :                     INChI_Aux** pINChI_Aux2 = pRevInChI->pINChI_Aux[INCHI_BAS][0]; /* component 0 */
    1218                 :           0 :                     INChI** pINChI_Revr = pRevInChI->pINChI[INCHI_BAS][0];
    1219                 :           0 :                     INChI* pINChI_Orig = pOneInput->pInpInChI[INCHI_REC][TAUT_YES] + k1;
    1220         [ #  # ]:           0 :                     nChargeRevrs = pINChI_Revr ? pINChI_Revr[TAUT_YES]->nTotalCharge : NO_VALUE_INT;
    1221                 :           0 :                     nChargeInChI = pINChI_Orig->nTotalCharge;
    1222         [ #  # ]:           0 :                     if (pINChI_Aux2)
    1223                 :             :                     {
    1224                 :           0 :                         nRemovedProtonsByNormFromRevrs = pINChI_Aux2[TAUT_YES]->nNumRemovedProtons;
    1225                 :             :                     }
    1226                 :             :                     /* this component cannot be disconnected because it is same as in reconnected layer */
    1227                 :           0 :                     nRemovedProtonsByRevrs = pStruct[INCHI_REC][TAUT_YES][k1].nNumRemovedProtonsByRevrs;
    1228                 :           0 :                     pStruct[iInchiRec][TAUT_YES][k1].nChargeRevrs = nChargeRevrs;
    1229                 :           0 :                     pStruct[iInchiRec][TAUT_YES][k1].nChargeInChI = nChargeInChI;
    1230                 :             :                 }
    1231                 :             :             }
    1232                 :             :             /* how many protons (to be removed by InChI Normalization) to add =
    1233                 :             :             (proton balance in InChI} -
    1234                 :             :             {number of protons known to be removed by InChI Normalization from Reconstructed structure} */
    1235                 :           0 :             nToBeRemovedByNormFromRevrs[iInchiRec].nNumRemovedProtons -= nRemovedProtonsByNormFromRevrs;
    1236                 :           0 :             nRemovedByNormFromRevrs[iInchiRec] += nRemovedProtonsByNormFromRevrs;
    1237                 :           0 :             nRemovedByRevrs[iInchiRec] += nRemovedProtonsByRevrs;
    1238                 :           0 :             pStruct[iInchiRec][TAUT_YES][k].nRemovedProtonsByNormFromRevrs = nRemovedProtonsByNormFromRevrs;
    1239                 :             :         }
    1240                 :             :     }
    1241                 :             : 
    1242                 :             :     /* Since fixed-H layer is missing we need to add proton balance to the components */
    1243                 :           0 :     memset(nIsoDeltaFromDisconnected, 0, sizeof(nIsoDeltaFromDisconnected)); /* djb-rwth: memset_s C11/Annex K variant? */
    1244         [ #  # ]:           0 :     for (iInchiRec = INCHI_REC; INCHI_BAS <= iInchiRec; iInchiRec--)
    1245                 :             :     {
    1246                 :             :         /*
    1247                 :             :         if ( !pOneInput->nNumComponents[iInchiRec][TAUT_NON] &&
    1248                 :             :               pOneInput->nNumComponents[iInchiRec][TAUT_YES] ) {
    1249                 :             :         */
    1250   [ #  #  #  # ]:           0 :         int bHasRecMobH = (iInchiRec == INCHI_BAS && pOneInput->nNumComponents[INCHI_REC][TAUT_YES]);
    1251                 :             :         /* bHasRecMobH means all components that could not be disconnected are in reconnected part */
    1252         [ #  # ]:           0 :         if (iInchiRec == INCHI_BAS)
    1253                 :             :         {
    1254                 :             :             /* second pass: common structures have been changed */
    1255                 :           0 :             nToBeRemovedByNormFromRevrs[INCHI_BAS].nNumRemovedProtons += nDeltaFromDisconnected;
    1256                 :             :         }
    1257                 :             :         /* after proton removal InChI is recalculated */
    1258                 :             : 
    1259   [ #  #  #  #  :           0 :         ret = AddRemProtonsInRestrStruct(ic, pCG, ip, sd, num_inp, bHasSomeFixedH, pStruct[iInchiRec][TAUT_YES],
                   #  # ]
    1260                 :             :             pOneInput->nNumComponents[iInchiRec][TAUT_YES],
    1261                 :           0 :             bHasRecMobH ? pStruct[INCHI_REC][TAUT_YES] : NULL,
    1262                 :             :             bHasRecMobH ? pOneInput->nNumComponents[INCHI_REC][TAUT_YES] : 0,
    1263                 :             :             &nToBeRemovedByNormFromRevrs[iInchiRec].nNumRemovedProtons,
    1264                 :             :             (iInchiRec == INCHI_REC) ? &nDeltaFromDisconnected : NULL);
    1265         [ #  # ]:           0 :         if (ret < 0)
    1266                 :             :         {
    1267                 :           0 :             goto exit_function;
    1268                 :             :         }
    1269                 :             :         /* djb-rwth: removing redundant code */
    1270                 :             :        /*
    1271                 :             :        }
    1272                 :             :        */
    1273                 :             :     }
    1274                 :             : 
    1275                 :             :     /* if fixed-H layer is missing then we need to add isotopic exchangeable proton balance to the components */
    1276         [ #  # ]:           0 :     for (iInchiRec = INCHI_REC; INCHI_BAS <= iInchiRec; iInchiRec--)
    1277                 :             :     {
    1278                 :             :         /*
    1279                 :             :         if ( !pOneInput->nNumComponents[iInchiRec][TAUT_NON] &&
    1280                 :             :               pOneInput->nNumComponents[iInchiRec][TAUT_YES] ) {
    1281                 :             :         */
    1282   [ #  #  #  # ]:           0 :         int bHasRecMobH = (iInchiRec == INCHI_BAS && pOneInput->nNumComponents[INCHI_REC][TAUT_YES]);
    1283                 :             :         /* bHasRecMobH means all components that could not be disconnected are in reconnected part */
    1284         [ #  # ]:           0 :         if (iInchiRec == INCHI_BAS)
    1285                 :             :         {
    1286                 :             :             /* second pass: common structures have been changed */
    1287         [ #  # ]:           0 :             for (k = 0; k < NUM_H_ISOTOPES; k++)
    1288                 :             :             {
    1289                 :           0 :                 nToBeRemovedByNormFromRevrs[INCHI_BAS].nNumRemovedIsotopicH[k] += nIsoDeltaFromDisconnected[k];
    1290                 :             :             }
    1291                 :             :         }
    1292                 :             : 
    1293                 :             :         /* after proton removal InChI is recalculated */
    1294   [ #  #  #  # ]:           0 :         ret = AddRemIsoProtonsInRestrStruct(ic, pCG, ip, sd, num_inp, bHasSomeFixedH, pStruct[iInchiRec][TAUT_YES],
    1295                 :             :             pOneInput->nNumComponents[iInchiRec][TAUT_YES],
    1296                 :           0 :             bHasRecMobH ? pStruct[INCHI_REC][TAUT_YES] : NULL,
    1297                 :             :             bHasRecMobH ? pOneInput->nNumComponents[INCHI_REC][TAUT_YES] : 0,
    1298         [ #  # ]:           0 :             nToBeRemovedByNormFromRevrs[iInchiRec].nNumRemovedIsotopicH,
    1299                 :             :             (iInchiRec == INCHI_REC) ? nIsoDeltaFromDisconnected : NULL);
    1300                 :             : 
    1301         [ #  # ]:           0 :         if (ret < 0)
    1302                 :             :         {
    1303                 :           0 :             goto exit_function;
    1304                 :             :         }
    1305                 :             :         /* djb-rwth: removing redundant code */
    1306                 :             :         /*
    1307                 :             :         }
    1308                 :             :         */
    1309                 :             :     }
    1310                 :             : 
    1311                 :           0 : exit_function:
    1312                 :             : 
    1313                 :           0 :     return ret;
    1314                 :             : }
    1315                 :             : 
    1316                 :             : 
    1317                 :             : /****************************************************************************/
    1318                 :           0 : void FreeStrFromINChI(StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
    1319                 :             :     int nNumComponents[INCHI_NUM][TAUT_NUM])
    1320                 :             : {
    1321                 :             :     int iInchiRec, iMobileH, cur_num_comp, k, j;
    1322                 :             :     StrFromINChI* pStruct1;
    1323         [ #  # ]:           0 :     for (iInchiRec = 0; iInchiRec < INCHI_NUM; iInchiRec++)
    1324                 :             :     {
    1325         [ #  # ]:           0 :         for (iMobileH = 0; iMobileH < TAUT_NUM; iMobileH++)
    1326                 :             :         {
    1327                 :           0 :             cur_num_comp = nNumComponents[iInchiRec][iMobileH];
    1328   [ #  #  #  # ]:           0 :             if (!cur_num_comp || !(pStruct1 = pStruct[iInchiRec][iMobileH]))
    1329                 :             :             {
    1330                 :           0 :                 continue;
    1331                 :             :             }
    1332         [ #  # ]:           0 :             for (k = 0; k < cur_num_comp; k++)
    1333                 :             :             {
    1334         [ #  # ]:           0 :                 if (pStruct1[k].at)
    1335                 :             :                 {
    1336         [ #  # ]:           0 :                     inchi_free(pStruct1[k].at);
    1337                 :             :                 }
    1338         [ #  # ]:           0 :                 if (pStruct1[k].at2)
    1339                 :             :                 {
    1340         [ #  # ]:           0 :                     inchi_free(pStruct1[k].at2);
    1341                 :             :                 }
    1342         [ #  # ]:           0 :                 if (pStruct1[k].st)
    1343                 :             :                 {
    1344         [ #  # ]:           0 :                     inchi_free(pStruct1[k].st);
    1345                 :             :                 }
    1346         [ #  # ]:           0 :                 if (pStruct1[k].pVA)
    1347                 :             :                 {
    1348         [ #  # ]:           0 :                     inchi_free(pStruct1[k].pVA);
    1349                 :             :                 }
    1350                 :             :                 /*
    1351                 :             :                 if ( pStruct1[k].ti.t_group ) {
    1352                 :             :                     inchi_free( pStruct1[k].ti.t_group );
    1353                 :             :                 }
    1354                 :             :                 */
    1355         [ #  # ]:           0 :                 if (pStruct1[k].One_ti.t_group) {
    1356         [ #  # ]:           0 :                     inchi_free(pStruct1[k].One_ti.t_group); /* ricrogz: fixing memory leak */
    1357                 :             :                 }
    1358         [ #  # ]:           0 :                 if (pStruct1[k].pXYZ)
    1359                 :             :                 {
    1360         [ #  # ]:           0 :                     inchi_free(pStruct1[k].pXYZ); /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
    1361                 :             :                 }
    1362                 :             :                 /*==== begin ====*/
    1363                 :           0 :                 free_t_group_info(&pStruct1[k].ti);
    1364         [ #  # ]:           0 :                 if (pStruct1[k].endpoint)
    1365                 :             :                 {
    1366         [ #  # ]:           0 :                     inchi_free(pStruct1[k].endpoint); /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
    1367                 :             :                 }
    1368         [ #  # ]:           0 :                 if (pStruct1[k].fixed_H)
    1369                 :             :                 {
    1370         [ #  # ]:           0 :                     inchi_free(pStruct1[k].fixed_H); /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
    1371                 :             :                 }
    1372         [ #  # ]:           0 :                 for (j = 0; j < TAUT_NUM; j++)
    1373                 :             :                 {
    1374         [ #  # ]:           0 :                     if (pStruct1[k].nAtno2Canon[j])
    1375         [ #  # ]:           0 :                         inchi_free(pStruct1[k].nAtno2Canon[j]);
    1376         [ #  # ]:           0 :                     if (pStruct1[k].nCanon2Atno[j])
    1377         [ #  # ]:           0 :                         inchi_free(pStruct1[k].nCanon2Atno[j]);
    1378                 :             :                 }
    1379                 :             :                 /*===== end ======*/
    1380                 :             :                 /*  free INChI memory */
    1381                 :           0 :                 FreeAllINChIArrays(pStruct1[k].RevInChI.pINChI,
    1382                 :           0 :                     pStruct1[k].RevInChI.pINChI_Aux,
    1383                 :           0 :                     pStruct1[k].RevInChI.num_components);
    1384                 :             : #ifdef NEVER
    1385                 :             :                 /* don't do that: these are just pointers to OneInput structure members */
    1386                 :             :                 Free_INChI(&pStruct1[k].pINChI);
    1387                 :             :                 Free_INChI_Aux(&pStruct1[k].pINChI_Aux);
    1388                 :             :                 if (pStruct1[k].inp_norm_data)
    1389                 :             :                 {
    1390                 :             :                     FreeInpAtomData(pStruct1[k].inp_norm_data);
    1391                 :             :                     inchi_free(pStruct1[k].inp_norm_data);
    1392                 :             :                 }
    1393                 :             : #endif
    1394                 :             :             }
    1395         [ #  # ]:           0 :             inchi_free(pStruct[iInchiRec][iMobileH]);
    1396                 :           0 :             pStruct[iInchiRec][iMobileH] = NULL;
    1397                 :             :         }
    1398                 :             :     }
    1399                 :           0 : }
    1400                 :             : 
    1401                 :             : 
    1402                 :             : /****************************************************************************/
    1403                 :           4 : void FreeInpInChI(InpInChI* pOneInput)
    1404                 :             : {
    1405                 :             :     int iINChI, k, j;
    1406         [ +  + ]:          12 :     for (iINChI = 0; iINChI < INCHI_NUM; iINChI++)
    1407                 :             :     {
    1408         [ +  + ]:          24 :         for (j = 0; j < TAUT_NUM; j++)
    1409                 :             :         {
    1410         [ +  + ]:          16 :             if (pOneInput->pInpInChI[iINChI][j])
    1411                 :             :             {
    1412         [ +  + ]:           4 :                 for (k = 0; k < pOneInput->nNumComponents[iINChI][j]; k++)
    1413                 :             :                 {
    1414                 :             : #if (FIX_OSS_FUZZ_25734_28139 == 1)
    1415                 :           2 :                     U_CHAR* k_nAtom = (&pOneInput->pInpInChI[iINChI][j][k])->nAtom;
    1416                 :           2 :                     AT_NUMB* k_nConnTable = (&pOneInput->pInpInChI[iINChI][j][k])->nConnTable;
    1417                 :           2 :                     AT_NUMB* k_nTautomer = (&pOneInput->pInpInChI[iINChI][j][k])->nTautomer;
    1418                 :           2 :                     S_CHAR* k_nNum_H = (&pOneInput->pInpInChI[iINChI][j][k])->nNum_H;
    1419                 :           2 :                     S_CHAR* k_nNum_H_fixed = (&pOneInput->pInpInChI[iINChI][j][k])->nNum_H_fixed;
    1420                 :           2 :                     char* k_szHillFormula = (&pOneInput->pInpInChI[iINChI][j][k])->szHillFormula;
    1421                 :           2 :                     AT_NUMB* k_nPossibleLocationsOfIsotopicH = (&pOneInput->pInpInChI[iINChI][j][k])->nPossibleLocationsOfIsotopicH;
    1422                 :           2 :                     INChI_IsotopicAtom* k_IsotopicAtom = (&pOneInput->pInpInChI[iINChI][j][k])->IsotopicAtom;
    1423                 :           2 :                     INChI_IsotopicTGroup* k_IsotopicTGroup = (&pOneInput->pInpInChI[iINChI][j][k])->IsotopicTGroup;
    1424                 :           2 :                     INChI_Stereo* k_Stereo = (&pOneInput->pInpInChI[iINChI][j][k])->Stereo;
    1425                 :           2 :                     INChI_Stereo* k_StereoIsotopic = (&pOneInput->pInpInChI[iINChI][j][k])->StereoIsotopic;
    1426                 :             : 
    1427                 :             : #endif
    1428                 :             : 
    1429                 :           2 :                     Free_INChI_Members(&pOneInput->pInpInChI[iINChI][j][k]);
    1430                 :             : 
    1431                 :             : #if (FIX_OSS_FUZZ_25734_28139 == 1)
    1432                 :             :                     {
    1433                 :             :                         /* prevent erroneous repeated freeing in copied pInpInChIp[][][kk] */
    1434                 :             :                         int kk;
    1435         [ -  + ]:           2 :                         for (kk = k + 1; kk < pOneInput->nNumComponents[iINChI][j]; kk++)
    1436                 :             :                         {
    1437         [ #  # ]:           0 :                             if (k_nAtom == (&pOneInput->pInpInChI[iINChI][j][kk])->nAtom)
    1438                 :             :                             {
    1439                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->nAtom = NULL;
    1440                 :             :                             }
    1441         [ #  # ]:           0 :                             if (k_nConnTable == (&pOneInput->pInpInChI[iINChI][j][kk])->nConnTable)
    1442                 :             :                             {
    1443                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->nConnTable = NULL;
    1444                 :             :                             }
    1445         [ #  # ]:           0 :                             if (k_nTautomer == (&pOneInput->pInpInChI[iINChI][j][kk])->nTautomer)
    1446                 :             :                             {
    1447                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->nTautomer = NULL;
    1448                 :             :                             }
    1449         [ #  # ]:           0 :                             if (k_nNum_H == (&pOneInput->pInpInChI[iINChI][j][kk])->nNum_H)
    1450                 :             :                             {
    1451                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->nNum_H = NULL;
    1452                 :             :                             }
    1453         [ #  # ]:           0 :                             if (k_nNum_H_fixed == (&pOneInput->pInpInChI[iINChI][j][kk])->nNum_H_fixed)
    1454                 :             :                             {
    1455                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->nNum_H_fixed = NULL;
    1456                 :             :                             }
    1457         [ #  # ]:           0 :                             if (k_szHillFormula == (&pOneInput->pInpInChI[iINChI][j][kk])->szHillFormula)
    1458                 :             :                             {
    1459                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->szHillFormula = NULL;
    1460                 :             :                             }
    1461         [ #  # ]:           0 :                             if (k_nPossibleLocationsOfIsotopicH == (&pOneInput->pInpInChI[iINChI][j][kk])->nPossibleLocationsOfIsotopicH)
    1462                 :             :                             {
    1463                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->nPossibleLocationsOfIsotopicH = NULL;
    1464                 :             :                             }
    1465                 :             : 
    1466         [ #  # ]:           0 :                             if (k_IsotopicAtom == (&pOneInput->pInpInChI[iINChI][j][kk])->IsotopicAtom)
    1467                 :             :                             {
    1468                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->IsotopicAtom = NULL;
    1469                 :             :                             }
    1470                 :             : 
    1471         [ #  # ]:           0 :                             if (k_IsotopicTGroup == (&pOneInput->pInpInChI[iINChI][j][kk])->IsotopicTGroup)
    1472                 :             :                             {
    1473                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->IsotopicTGroup = NULL;
    1474                 :             :                             }
    1475                 :             : 
    1476         [ #  # ]:           0 :                             if (k_Stereo == (&pOneInput->pInpInChI[iINChI][j][kk])->Stereo)
    1477                 :             :                             {
    1478                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->Stereo = NULL;
    1479                 :             :                             }
    1480                 :             : 
    1481         [ #  # ]:           0 :                             if (k_StereoIsotopic == (&pOneInput->pInpInChI[iINChI][j][kk])->StereoIsotopic)
    1482                 :             :                             {
    1483                 :           0 :                                 (&pOneInput->pInpInChI[iINChI][j][kk])->StereoIsotopic = NULL;
    1484                 :             :                             }
    1485                 :             : 
    1486                 :             :                         }
    1487                 :             :                     }
    1488                 :             : #endif                    
    1489                 :             : 
    1490                 :             :                 }
    1491         [ +  - ]:           2 :                 inchi_free(pOneInput->pInpInChI[iINChI][j]);
    1492                 :           2 :                 pOneInput->pInpInChI[iINChI][j] = NULL;
    1493                 :             :             }
    1494         [ -  + ]:          16 :             if (pOneInput->nNumProtons[iINChI][j].pNumProtons)
    1495                 :             :             {
    1496         [ #  # ]:           0 :                 inchi_free(pOneInput->nNumProtons[iINChI][j].pNumProtons);
    1497                 :           0 :                 pOneInput->nNumProtons[iINChI][j].pNumProtons = NULL;
    1498                 :             :             }
    1499                 :             :         }
    1500                 :             :     }
    1501         [ -  + ]:           4 :     if (pOneInput->atom)
    1502                 :             :     {
    1503         [ #  # ]:           0 :         inchi_free(pOneInput->atom);
    1504                 :             :     }
    1505                 :             : 
    1506                 :           4 :     FreeExtOrigAtData(pOneInput->polymer, pOneInput->v3000);
    1507                 :             : 
    1508                 :           4 :     memset(pOneInput, 0, sizeof(*pOneInput)); /* djb-rwth: memset_s C11/Annex K variant? */
    1509                 :           4 : }
    1510                 :             : 
    1511                 :             : 
    1512                 :             : /****************************************************************************/
    1513                 :           0 : int CompareAllOrigInchiToRevInChI(StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
    1514                 :             :     InpInChI* pOneInput,
    1515                 :             :     int bReqNonTaut,
    1516                 :             :     long num_inp,
    1517                 :             :     char* szCurHdr)
    1518                 :             : {
    1519                 :           0 :     int i, iInchiRec, iMobileH, iMobileHpStruct, num_components, iComponent, ret = 0; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1520                 :             :     COMPONENT_REM_PROTONS nCurRemovedProtons, nNumRemovedProtons;
    1521                 :             :     INChI* pInChI[TAUT_NUM];
    1522                 :             :     INCHI_MODE  CompareInchiFlags[TAUT_NUM];
    1523                 :           0 :     memset(pOneInput->CompareInchiFlags[0], 0, sizeof(pOneInput->CompareInchiFlags[0])); /* djb-rwth: memset_s C11/Annex K variant? */
    1524                 :           0 :     memset(&nNumRemovedProtons, 0, sizeof(nNumRemovedProtons)); /* djb-rwth: memset_s C11/Annex K variant? */
    1525                 :             : 
    1526                 :             :     /* do we have reconnected InChI ?*/
    1527                 :           0 :     iInchiRec = INCHI_REC;
    1528                 :           0 :     iMobileH = TAUT_NON;
    1529   [ #  #  #  # ]:           0 :     if (!pOneInput->nNumComponents[iInchiRec][TAUT_YES] && !pOneInput->nNumComponents[iInchiRec][TAUT_NON])
    1530                 :             :     {
    1531                 :           0 :         iInchiRec = INCHI_BAS;
    1532                 :             :     }
    1533                 :             :     /* do we have Mobile or Fixed-H ? */
    1534   [ #  #  #  # ]:           0 :     if (!pOneInput->nNumComponents[iInchiRec][TAUT_NON] || !bReqNonTaut)
    1535                 :             :     {
    1536                 :           0 :         iMobileH = TAUT_YES;  /* index for pOneInput */
    1537                 :             :     }
    1538                 :             :     /* if a restored structure has Fixed-H InChI then its mobile-H restored InChI is in Fixed-H pStruct */
    1539                 :           0 :     num_components = pOneInput->nNumComponents[iInchiRec][iMobileH];
    1540         [ #  # ]:           0 :     for (iComponent = 0; iComponent < num_components; iComponent++)
    1541                 :             :     {
    1542                 :           0 :         int bMobileH = iMobileH;
    1543                 :           0 :         pInChI[0] = pInChI[1] = NULL;
    1544         [ #  # ]:           0 :         if (pOneInput->pInpInChI[iInchiRec][bMobileH][iComponent].nNumberOfAtoms &&
    1545         [ #  # ]:           0 :             !pOneInput->pInpInChI[iInchiRec][bMobileH][iComponent].bDeleted)
    1546                 :             :         {
    1547                 :             :             /* the requested InChI layer exists */
    1548                 :           0 :             pInChI[0] = &pOneInput->pInpInChI[iInchiRec][bMobileH][iComponent];
    1549         [ #  # ]:           0 :             if (bMobileH == TAUT_NON)
    1550                 :             :             {
    1551                 :           0 :                 pInChI[1] = &pOneInput->pInpInChI[iInchiRec][TAUT_YES][iComponent];
    1552                 :             :             }
    1553                 :             :         }
    1554                 :             :         else
    1555                 :             :         {
    1556         [ #  # ]:           0 :             if (bMobileH == TAUT_NON &&
    1557         [ #  # ]:           0 :                 pOneInput->pInpInChI[iInchiRec][TAUT_YES][iComponent].nNumberOfAtoms &&
    1558         [ #  # ]:           0 :                 !pOneInput->pInpInChI[iInchiRec][TAUT_YES][iComponent].bDeleted)
    1559                 :             :             {
    1560                 :             :                 /* the requested Fixed-H InChI layer does not exist; however, the Mobile-H does exist */
    1561                 :           0 :                 bMobileH = TAUT_YES; /* only Mobile-H is available */
    1562                 :           0 :                 pInChI[0] = &pOneInput->pInpInChI[iInchiRec][bMobileH][iComponent];
    1563                 :             :             }
    1564                 :             :         }
    1565                 :           0 :         memset(CompareInchiFlags, 0, sizeof(CompareInchiFlags)); /* djb-rwth: memset_s C11/Annex K variant? */
    1566                 :           0 :         memset(&nCurRemovedProtons, 0, sizeof(nCurRemovedProtons)); /* djb-rwth: memset_s C11/Annex K variant? */
    1567                 :           0 :         iMobileHpStruct =
    1568                 :             : #if ( bRELEASE_VERSION == 0 )
    1569                 :             : #ifndef TARGET_API_LIB
    1570                 :             :             /* legacy: reproduce old output */
    1571                 :             :             OldPrintCompareOneOrigInchiToRevInChI(pStruct[iInchiRec][bMobileH] + iComponent, pInChI, bMobileH,
    1572                 :             :                 iComponent, num_inp, szCurHdr);
    1573                 :             : #endif
    1574                 :             : #endif
    1575                 :             :         /* one component comparison result bits */
    1576                 :           0 :         ret = CompareOneOrigInchiToRevInChI(pStruct[iInchiRec][bMobileH] + iComponent, pInChI, bMobileH, iComponent,
    1577                 :             :             num_inp, szCurHdr, &nCurRemovedProtons, CompareInchiFlags);
    1578         [ #  # ]:           0 :         if (ret >= 0)
    1579                 :             :         {
    1580                 :             :             /* no errors encountered -> accumulate removed protons from individual Mobile-H layers of components */
    1581                 :           0 :             nNumRemovedProtons.nNumRemovedProtons += nCurRemovedProtons.nNumRemovedProtons;
    1582         [ #  # ]:           0 :             for (i = 0; i < NUM_H_ISOTOPES; i++)
    1583                 :             :             {
    1584                 :           0 :                 nNumRemovedProtons.nNumRemovedIsotopicH[i] += nCurRemovedProtons.nNumRemovedIsotopicH[i];
    1585                 :             :             }
    1586                 :             :             /* accumulate compare bits */
    1587         [ #  # ]:           0 :             for (i = 0; i < TAUT_NUM; i++)
    1588                 :             :             {
    1589                 :           0 :                 pOneInput->CompareInchiFlags[0][i] |= CompareInchiFlags[i];
    1590                 :             :             }
    1591                 :             :         }
    1592                 :             :         else
    1593                 :             :         {
    1594                 :           0 :             goto exit_function;
    1595                 :             :         }
    1596                 :             :     }
    1597         [ #  # ]:           0 :     if (iMobileH == TAUT_YES)
    1598                 :             :     {
    1599         [ #  # ]:           0 :         if (pOneInput->nNumProtons[iInchiRec][iMobileH].pNumProtons)
    1600                 :             :         {
    1601                 :           0 :             ret = RI_ERR_PROGR; /* in Mobile-H case proton balances are split between compoments */
    1602                 :             :         }
    1603                 :             :         else
    1604                 :             :         {
    1605                 :             :             /*   num removed protons in orig. InChI      num removed protons in restored InChi */
    1606         [ #  # ]:           0 :             if (nNumRemovedProtons.nNumRemovedProtons != pOneInput->nNumProtons[iInchiRec][iMobileH].nNumRemovedProtons)
    1607                 :             :             {
    1608                 :             :                 /* restored structure InChI has less or more removed protons */
    1609                 :           0 :                 pOneInput->CompareInchiFlags[0][TAUT_YES] |= INCHIDIFF_MOBH_PROTONS;
    1610                 :             : #if ( bRELEASE_VERSION == 0 )
    1611                 :             :                 /* debug output only */
    1612                 :             :                 {
    1613                 :             :                     int num_H_AddedByRevrs = pOneInput->nNumProtons[iInchiRec][iMobileH].nNumRemovedProtons
    1614                 :             :                         - nNumRemovedProtons.nNumRemovedProtons;
    1615                 :             :                     fprintf(stdout, "COMPARE_INCHI: %ld: %s %cM: Proton balance (Diff: %d, RevrsRem=%d)\n",
    1616                 :             :                         num_inp, szCurHdr ? szCurHdr : "Struct", iInchiRec ? 'R' : 'D',
    1617                 :             :                         pOneInput->nNumProtons[iInchiRec][iMobileH].nNumRemovedProtons, num_H_AddedByRevrs);
    1618                 :             :                 }
    1619                 :             : #endif
    1620                 :             :             }
    1621         [ #  # ]:           0 :             for (i = 0; i < NUM_H_ISOTOPES; i++)
    1622                 :             :             {
    1623         [ #  # ]:           0 :                 if (nNumRemovedProtons.nNumRemovedIsotopicH[i] != pOneInput->nNumProtons[iInchiRec][TAUT_YES].nNumRemovedIsotopicH[i])
    1624                 :             :                 {
    1625                 :           0 :                     pOneInput->CompareInchiFlags[0][TAUT_YES] |= INCHIDIFF_MOB_ISO_H;
    1626                 :             : #if ( bRELEASE_VERSION == 0 )
    1627                 :             :                     /* debug output only */
    1628                 :             :                     {
    1629                 :             :                         int num_H_AddedByRevrs = pOneInput->nNumProtons[iInchiRec][TAUT_YES].nNumRemovedIsotopicH[i]
    1630                 :             :                             - nNumRemovedProtons.nNumRemovedIsotopicH[i];
    1631                 :             :                         fprintf(stdout, "COMPARE_INCHI: %ld: %s %cM: Iso Xchg %dH balance (Diff: %d, RevrsRem=%d)\n",
    1632                 :             :                             num_inp, szCurHdr ? szCurHdr : "Struct", iInchiRec ? 'R' : 'D', i + 1,
    1633                 :             :                             pOneInput->nNumProtons[iInchiRec][TAUT_YES].nNumRemovedIsotopicH[i], num_H_AddedByRevrs);
    1634                 :             :                     }
    1635                 :             : #endif
    1636                 :             :                 }
    1637                 :             :             }
    1638                 :             :         }
    1639                 :             :     }
    1640                 :             : 
    1641                 :           0 : exit_function:
    1642                 :             : 
    1643                 :           0 :     return ret;
    1644                 :             : }
    1645                 :             : 
    1646                 :             : 
    1647                 :             : /****************************************************************************/
    1648                 :           0 : int CompareAllDisconnectedOrigInchiToRevInChI(StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
    1649                 :             :     InpInChI* pOneInput,
    1650                 :             :     int bHasSomeFixedH,
    1651                 :             :     long num_inp,
    1652                 :             :     char* szCurHdr)
    1653                 :             : {
    1654                 :             :     int i, k, m, n, iInChI, iMobileH, bMobileH, ifk;
    1655                 :             :     int num_components_D, num_components_R;
    1656                 :             :     int nNumCompHaveSeparateProtons_D, nNumCompHaveSeparateProtons_R;
    1657                 :             :     int num_fragments_D, num_fragments_R, num_fragments_DR, num_fragments, iComponent, ret;
    1658                 :             :     int ifInChI, ifMobileH, bfMobileH, nLink;
    1659                 :             :     COMPONENT_REM_PROTONS nNumRemovedProtons_D;     /* removed from the disconnected layer of the Input InChI */
    1660                 :             :     COMPONENT_REM_PROTONS nNumRemovedProtons_D_all; /* if only totals are avalable */
    1661                 :             :     COMPONENT_REM_PROTONS nNumRemovedProtons_R; /* removed from disconnected layer of the reconstructed struct */
    1662                 :             :     COMPONENT_REM_PROTONS nNumRemovedProtons_R_all;
    1663                 :             :     INCHI_MODE  CompareInchiFlags[TAUT_NUM];
    1664                 :             :     StrFromINChI* pStruct1;
    1665                 :             :     INChI_Aux* pINChI_Aux;
    1666                 :           0 :     INCHI_SORT* pINChISort1 = NULL; /* from reversed structure */
    1667                 :           0 :     INCHI_SORT* pINChISort2 = NULL; /* original input InChI */
    1668                 :           0 :     int        nNumNonTaut1 = 0, nNumNonTaut2 = 0;
    1669                 :             : 
    1670                 :           0 :     ret = 0;
    1671                 :           0 :     memset(pOneInput->CompareInchiFlags[1], 0, sizeof(pOneInput->CompareInchiFlags[1])); /* djb-rwth: memset_s C11/Annex K variant? */
    1672                 :             : 
    1673                 :             :     /* count components that are not subject to disconnection */
    1674         [ #  # ]:           0 :     if (!pOneInput->nNumComponents[INCHI_REC][TAUT_YES] &&
    1675         [ #  # ]:           0 :         !pOneInput->nNumComponents[INCHI_REC][TAUT_NON])
    1676                 :             :     {
    1677                 :           0 :         return 0; /* nothing to do */
    1678                 :             :     }
    1679                 :             : 
    1680                 :           0 :     memset(&nNumRemovedProtons_D, 0, sizeof(nNumRemovedProtons_D)); /* djb-rwth: memset_s C11/Annex K variant? */
    1681                 :           0 :     memset(&nNumRemovedProtons_R, 0, sizeof(nNumRemovedProtons_R)); /* djb-rwth: memset_s C11/Annex K variant? */
    1682                 :           0 :     memset(&nNumRemovedProtons_D_all, 0, sizeof(nNumRemovedProtons_D_all)); /* djb-rwth: memset_s C11/Annex K variant? */
    1683                 :           0 :     memset(&nNumRemovedProtons_R_all, 0, sizeof(nNumRemovedProtons_R_all)); /* djb-rwth: memset_s C11/Annex K variant? */
    1684                 :           0 :     memset(CompareInchiFlags, 0, sizeof(CompareInchiFlags)); /* djb-rwth: memset_s C11/Annex K variant? */
    1685                 :             : 
    1686                 :           0 :     num_components_D = inchi_max(pOneInput->nNumComponents[INCHI_BAS][TAUT_YES],
    1687                 :             :         pOneInput->nNumComponents[INCHI_BAS][TAUT_NON]);
    1688                 :           0 :     num_components_R = inchi_max(pOneInput->nNumComponents[INCHI_REC][TAUT_YES],
    1689                 :             :         pOneInput->nNumComponents[INCHI_REC][TAUT_NON]);
    1690                 :             : 
    1691                 :             :     /***********************************************************************************************/
    1692                 :             :     /* InpInChI: count fragments -- disconnected components that do not match reconnected          */
    1693                 :             :     /* Accumulate removed H and isotopic H from ALL Fixed-H disconnected components except deleted */
    1694                 :             :     /* This segment collects info from the original InChI                                          */
    1695                 :             :     /***********************************************************************************************/
    1696                 :             :     /*---- Original InChI ----*/
    1697                 :             : 
    1698                 :           0 :     num_fragments_D = 0;
    1699                 :           0 :     iInChI = INCHI_BAS;
    1700   [ #  #  #  # ]:           0 :     iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
    1701                 :           0 :     nNumCompHaveSeparateProtons_D = 0;
    1702                 :             : 
    1703                 :             :     /* in case of Mobile-H components here are the proton totals from the original InChI disconn. layer */
    1704                 :           0 :     nNumRemovedProtons_D.nNumRemovedProtons = pOneInput->nNumProtons[iInChI][TAUT_YES].nNumRemovedProtons;
    1705                 :           0 :     memcpy(nNumRemovedProtons_D.nNumRemovedIsotopicH,
    1706                 :           0 :         pOneInput->nNumProtons[iInChI][TAUT_YES].nNumRemovedIsotopicH,
    1707                 :             :         sizeof(nNumRemovedProtons_D.nNumRemovedIsotopicH)); /* total for the disconnected layer */
    1708         [ #  # ]:           0 :     for (k = 0; k < num_components_D; k++)
    1709                 :             :     {
    1710                 :           0 :         bMobileH = iMobileH;
    1711         [ #  # ]:           0 :         if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
    1712                 :             :         {
    1713         [ #  # ]:           0 :             if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
    1714                 :             :             {
    1715                 :           0 :                 bMobileH = TAUT_YES;
    1716                 :             :             }
    1717                 :             :             else
    1718                 :             :             {
    1719                 :           0 :                 continue; /* component is missing ??? */
    1720                 :             :             }
    1721                 :             :         }
    1722         [ #  # ]:           0 :         if (0 > (nLink = pOneInput->pInpInChI[iInChI][bMobileH][k].nLink))
    1723                 :             :         {
    1724                 :             :             /* component in Disconnected layer is linked to the identical one in the Reconnected layer */
    1725         [ #  # ]:           0 :             if (pOneInput->nNumProtons[INCHI_REC][TAUT_YES].pNumProtons)
    1726                 :             :             {
    1727                 :           0 :                 nNumCompHaveSeparateProtons_D++;
    1728                 :           0 :                 nLink = -(1 + nLink);
    1729                 :           0 :                 nNumRemovedProtons_D.nNumRemovedProtons += pOneInput->nNumProtons[INCHI_REC][TAUT_YES].pNumProtons[nLink].nNumRemovedProtons;
    1730         [ #  # ]:           0 :                 for (m = 0; m < NUM_H_ISOTOPES; m++)
    1731                 :             :                 {
    1732                 :           0 :                     nNumRemovedProtons_D.nNumRemovedIsotopicH[m] += pOneInput->nNumProtons[INCHI_REC][TAUT_YES].pNumProtons[nLink].nNumRemovedIsotopicH[m];
    1733                 :             :                 }
    1734                 :             :             }
    1735                 :           0 :             continue; /* same as reconnected */
    1736                 :             :         }
    1737                 :             :         /* component in the reconnected layer that was disconnected */
    1738                 :           0 :         nNumNonTaut2 += (bMobileH == TAUT_NON);
    1739         [ #  # ]:           0 :         if (pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons)
    1740                 :             :         {
    1741                 :           0 :             nNumCompHaveSeparateProtons_D++;
    1742                 :           0 :             nNumRemovedProtons_D.nNumRemovedProtons += pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons[k].nNumRemovedProtons;
    1743         [ #  # ]:           0 :             for (m = 0; m < NUM_H_ISOTOPES; m++)
    1744                 :             :             {
    1745                 :           0 :                 nNumRemovedProtons_D.nNumRemovedIsotopicH[m] += pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons[k].nNumRemovedIsotopicH[m];
    1746                 :             :             }
    1747                 :             :         }
    1748                 :           0 :         num_fragments_D++; /* number of disconnected fragments from original reconnected structure */
    1749                 :             :     }
    1750                 :             :     /* in case of Mobile-H components here are the proton totals from the original InChI */
    1751                 :             :     /*
    1752                 :             :     nNumRemovedProtons_D_all.nNumRemovedProtons = pOneInput->nNumProtons[iInChI][TAUT_YES].nNumRemovedProtons;
    1753                 :             :     memcpy( nNumRemovedProtons_D_all.nNumRemovedIsotopicH,
    1754                 :             :             pOneInput->nNumProtons[iInChI][TAUT_YES].nNumRemovedIsotopicH,
    1755                 :             :             sizeof(nNumRemovedProtons_D_all.nNumRemovedIsotopicH) );
    1756                 :             : 
    1757                 :             :     */
    1758                 :             :     /****************************************************************************************************/
    1759                 :             :     /* count fragments in reconstructed reconnected structure                                           */
    1760                 :             :     /* accumulate removed H and isotopic H from ALL reconstructed reconnected components except deleted */
    1761                 :             :     /* This segment collects info from the reconstructed structure InChI                                */
    1762                 :             :     /****************************************************************************************************/
    1763                 :             :     /*---- InChI from the reconstructed reconnected structure ----*/
    1764                 :           0 :     num_fragments_R = 0;
    1765                 :           0 :     iInChI = INCHI_REC;
    1766   [ #  #  #  # ]:           0 :     iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
    1767                 :           0 :     nNumCompHaveSeparateProtons_R = 0;
    1768         [ #  # ]:           0 :     for (k = 0; k < num_components_R; k++)
    1769                 :             :     {
    1770                 :           0 :         bMobileH = iMobileH;
    1771         [ #  # ]:           0 :         if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
    1772                 :             :         {
    1773         [ #  # ]:           0 :             if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
    1774                 :             :             {
    1775                 :           0 :                 bMobileH = TAUT_YES;
    1776                 :             :             }
    1777                 :             :             else
    1778                 :             :             {
    1779                 :           0 :                 continue; /* component is missing ??? (Deleted proton in Mobile-H layer) */
    1780                 :             :             }
    1781                 :             :         }
    1782         [ #  # ]:           0 :         if (0 < pOneInput->pInpInChI[iInChI][bMobileH][k].nLink)
    1783                 :             :         {
    1784                 :             :             /* this reconstructed reconnected component was NOT DISCONNECTED */
    1785                 :             :             /* same component is in the disconnected layer, it has no metal atoms or is an isolated metal atom */
    1786                 :           0 :             pStruct1 = pStruct[iInChI][bMobileH] + k;
    1787                 :           0 :             ifMobileH = TAUT_YES;  /* Mobile-H Aux_Info contains number removed protons */
    1788                 :           0 :             ifInChI = INCHI_BAS; /* this component cannot be reconnected */
    1789                 :           0 :             ifk = 0;         /* 0th component since it is InChI of a single component */
    1790                 :             :             /* The statement in the following line is *WRONG*, component number mixed with bMobileH:  */
    1791                 :             :             /* in RevInchi, when only Mobile-H is present then its only non-NULL InChI has index 0==TAUT_NON */
    1792         [ #  # ]:           0 :             if (bRevInchiComponentExists(pStruct1, ifInChI, ifMobileH, ifk))
    1793                 :             :             {
    1794                 :             :                 /* count protons */
    1795                 :           0 :                 pINChI_Aux = pStruct1->RevInChI.pINChI_Aux[ifInChI][ifk][ifMobileH];
    1796         [ #  # ]:           0 :                 if (pINChI_Aux)
    1797                 :             :                 {
    1798                 :           0 :                     nNumRemovedProtons_R.nNumRemovedProtons += pINChI_Aux->nNumRemovedProtons;
    1799         [ #  # ]:           0 :                     for (m = 0; m < NUM_H_ISOTOPES; m++)
    1800                 :             :                     {
    1801                 :           0 :                         nNumRemovedProtons_R.nNumRemovedIsotopicH[m] += pINChI_Aux->nNumRemovedIsotopicH[m];
    1802                 :             :                     }
    1803                 :             :                 }
    1804                 :             :             }
    1805         [ #  # ]:           0 :             nNumCompHaveSeparateProtons_R += bRevInchiComponentExists(pStruct1, ifInChI, ALT_TAUT(ifMobileH), ifk);
    1806                 :           0 :             continue; /* same as disconnected, has no metal atoms */
    1807                 :             :         }
    1808                 :             :         /* this reconstructed reconnected component WAS DISCONNECTED; check its fragments */
    1809                 :             :         /* it does not have same component in the disconnected layer */
    1810                 :           0 :         pStruct1 = pStruct[iInChI][bMobileH] + k;
    1811                 :           0 :         num_fragments = pStruct1->RevInChI.num_components[INCHI_BAS];
    1812                 :           0 :         ifInChI = INCHI_BAS; /* disconnected layer */
    1813                 :           0 :         ifMobileH = bHasSomeFixedH ? TAUT_NON : TAUT_YES;
    1814         [ #  # ]:           0 :         for (ifk = 0; ifk < num_fragments; ifk++)
    1815                 :             :         {
    1816                 :           0 :             bfMobileH = ifMobileH;
    1817         [ #  # ]:           0 :             if (!bRevInchiComponentExists(pStruct1, ifInChI, bfMobileH, ifk))
    1818                 :             :             {
    1819         [ #  # ]:           0 :                 if (bRevInchiComponentExists(pStruct1, ifInChI, TAUT_YES, ifk))
    1820                 :             :                 {
    1821                 :           0 :                     bfMobileH = TAUT_YES;
    1822                 :             :                 }
    1823                 :             :                 else
    1824                 :             :                 {
    1825                 :           0 :                     continue; /* fragment does not exist ??? */
    1826                 :             :                 }
    1827                 :             :             }
    1828                 :           0 :             nNumNonTaut1 += (bfMobileH == TAUT_NON);
    1829                 :           0 :             nNumCompHaveSeparateProtons_R += (bfMobileH == TAUT_NON);
    1830                 :             :             /* count protons from fragments made by metal disconnection */
    1831                 :           0 :             pINChI_Aux = pStruct1->RevInChI.pINChI_Aux[ifInChI][ifk][TAUT_YES];
    1832         [ #  # ]:           0 :             if (pINChI_Aux)
    1833                 :             :             {
    1834                 :           0 :                 nNumRemovedProtons_R.nNumRemovedProtons += pINChI_Aux->nNumRemovedProtons;
    1835         [ #  # ]:           0 :                 for (m = 0; m < NUM_H_ISOTOPES; m++)
    1836                 :             :                 {
    1837                 :           0 :                     nNumRemovedProtons_R.nNumRemovedIsotopicH[m] += pINChI_Aux->nNumRemovedIsotopicH[m];
    1838                 :             :                 }
    1839                 :             :             }
    1840                 :           0 :             num_fragments_R++; /* number of disconnected fragments from reconstructed reconnected structure */
    1841                 :             :         }
    1842                 :             :     }
    1843                 :             : 
    1844                 :             :     /*---------------- special treatment of the last reconstructed component -----------------*/
    1845                 :             :     /*---------------- this may contain separate protons added by the reconstruction ---------*/
    1846                 :           0 :     k = num_components_R - 1;
    1847                 :           0 :     pStruct1 = pStruct[iInChI][iMobileH] + k;
    1848   [ #  #  #  #  :           0 :     if (iMobileH == TAUT_YES && !bHasSomeFixedH &&
                   #  # ]
    1849                 :           0 :         bInpInchiComponentDeleted(pOneInput, iInChI, iMobileH, k) &&
    1850         [ #  # ]:           0 :         (num_fragments = pStruct1->RevInChI.num_components[INCHI_BAS]))
    1851                 :             :     {
    1852                 :             : 
    1853                 :           0 :         ifInChI = INCHI_BAS; /* disconnected layer */
    1854                 :           0 :         ifMobileH = TAUT_YES;
    1855         [ #  # ]:           0 :         for (ifk = 0; ifk < num_fragments; ifk++)
    1856                 :             :         {
    1857                 :           0 :             bfMobileH = ifMobileH;
    1858         [ #  # ]:           0 :             if (!bRevInchiComponentDeleted(pStruct1, ifInChI, bfMobileH, ifk))
    1859                 :             :             {
    1860                 :           0 :                 continue; /* fragment does exist ??? Should not happen */
    1861                 :             :             }
    1862                 :             :             /*
    1863                 :             :             nNumNonTaut1           += (bfMobileH == TAUT_NON);
    1864                 :             :             nNumCompHaveSeparateProtons_R += (bfMobileH == TAUT_NON);
    1865                 :             :             */
    1866                 :             :             /* count protons from fragments made by metal disconnection */
    1867                 :           0 :             pINChI_Aux = pStruct1->RevInChI.pINChI_Aux[ifInChI][ifk][TAUT_YES];
    1868         [ #  # ]:           0 :             if (pINChI_Aux)
    1869                 :             :             {
    1870                 :           0 :                 nNumRemovedProtons_R.nNumRemovedProtons += pINChI_Aux->nNumRemovedProtons;
    1871         [ #  # ]:           0 :                 for (m = 0; m < NUM_H_ISOTOPES; m++)
    1872                 :             :                 {
    1873                 :           0 :                     nNumRemovedProtons_R.nNumRemovedIsotopicH[m] += pINChI_Aux->nNumRemovedIsotopicH[m];
    1874                 :             :                 }
    1875                 :             :             }
    1876                 :             :             /*num_fragments_R ++;*/ /* number of disconnected fragments from reconstructed reconnected structure */
    1877                 :             :         }
    1878                 :             :     }
    1879                 :             : 
    1880                 :           0 :     num_fragments_DR = inchi_max(num_fragments_D, num_fragments_R);
    1881                 :             :     /* in case of correct reconstruction, num_fragments_D, num_fragments_R */
    1882         [ #  # ]:           0 :     if (!num_fragments_DR)
    1883                 :             :     {
    1884                 :           0 :         return 0; /* no component was disconnected */
    1885                 :             :     }
    1886         [ #  # ]:           0 :     if (num_fragments_D != num_fragments_R)
    1887                 :             :     {
    1888         [ #  # ]:           0 :         for (i = 0; i < TAUT_NUM; i++)
    1889                 :             :         {
    1890         [ #  # ]:           0 :             if (pOneInput->nNumComponents[INCHI_BAS][i])
    1891                 :             :             {
    1892                 :           0 :                 pOneInput->CompareInchiFlags[1][i] |= INCHIDIFF_PROBLEM;
    1893                 :             :             }
    1894                 :             :         }
    1895                 :           0 :         return 1; /* severe error */
    1896                 :             :     }
    1897                 :             : 
    1898                 :           0 :     pINChISort1 = (INCHI_SORT*)inchi_calloc(num_fragments_DR, sizeof(pINChISort1[0]));
    1899                 :           0 :     pINChISort2 = (INCHI_SORT*)inchi_calloc(num_fragments_DR, sizeof(pINChISort2[0]));
    1900   [ #  #  #  # ]:           0 :     if (!pINChISort1 || !pINChISort2)
    1901                 :             :     {
    1902                 :           0 :         ret = RI_ERR_ALLOC;
    1903                 :           0 :         goto exit_function;
    1904                 :             :     }
    1905                 :             : 
    1906                 :             :     /* accumulate original InChI of fragments -- disconnected components that do not match reconnected */
    1907                 :           0 :     iInChI = INCHI_BAS;
    1908   [ #  #  #  # ]:           0 :     iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
    1909         [ #  # ]:           0 :     for (k = n = 0; k < num_components_D; k++)
    1910                 :             :     {
    1911                 :           0 :         bMobileH = iMobileH;
    1912         [ #  # ]:           0 :         if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
    1913                 :             :         {
    1914         [ #  # ]:           0 :             if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
    1915                 :             :             {
    1916                 :           0 :                 bMobileH = TAUT_YES;
    1917                 :             :             }
    1918                 :             :             else
    1919                 :             :             {
    1920                 :           0 :                 continue; /* component is missing ??? (Deleted proton in Mobile-H layer) */
    1921                 :             :             }
    1922                 :             :         }
    1923         [ #  # ]:           0 :         if (0 > pOneInput->pInpInChI[iInChI][bMobileH][k].nLink)
    1924                 :             :         {
    1925                 :           0 :             continue; /* same as reconnected */
    1926                 :             :         }
    1927                 :             :         /* the component exists in disconnected layer of the orig. InChI only: it is a fragment */
    1928                 :           0 :         pINChISort2[n].pINChI[bMobileH] = pOneInput->pInpInChI[iInChI][bMobileH] + k;
    1929   [ #  #  #  # ]:           0 :         if (bMobileH == TAUT_NON &&
    1930         [ #  # ]:           0 :             (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k) ||
    1931                 :           0 :                 bInpInchiComponentDeleted(pOneInput, iInChI, TAUT_YES, k)))
    1932                 :             :         {
    1933                 :           0 :             pINChISort2[n].pINChI[TAUT_YES] = pOneInput->pInpInChI[iInChI][TAUT_YES] + k;
    1934                 :             :         }
    1935                 :             :         /* the last sort key is a number of removed protons */
    1936         [ #  # ]:           0 :         pINChISort2[n].ord_number = pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons ?
    1937                 :           0 :             pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons[k].nNumRemovedProtons : 0;
    1938                 :           0 :         pINChISort2[n].n1 = k;  /* orig. InChI disconnected layer component number */
    1939                 :           0 :         pINChISort2[n].n2 = -1; /* no fragment index */
    1940                 :           0 :         n++;
    1941                 :             :     }
    1942                 :             : 
    1943                 :             :     /* accumulate fragments from the reconstructed structure */
    1944                 :           0 :     iInChI = INCHI_REC;
    1945   [ #  #  #  # ]:           0 :     iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
    1946         [ #  # ]:           0 :     for (k = n = 0; k < num_components_R; k++)
    1947                 :             :     {
    1948                 :           0 :         bMobileH = iMobileH;
    1949         [ #  # ]:           0 :         if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
    1950                 :             :         {
    1951         [ #  # ]:           0 :             if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
    1952                 :             :             {
    1953                 :           0 :                 bMobileH = TAUT_YES;
    1954                 :             :             }
    1955                 :             :             else
    1956                 :             :             {
    1957                 :           0 :                 continue; /* component is missing ??? (Deleted proton in Mobile-H layer) */
    1958                 :             :             }
    1959                 :             :         }
    1960                 :             :         /* the reconstructed structure */
    1961         [ #  # ]:           0 :         if (0 < pOneInput->pInpInChI[iInChI][bMobileH][k].nLink)
    1962                 :             :         {
    1963                 :           0 :             continue; /* same as disconnected, has no metal atoms */
    1964                 :             :         }
    1965                 :             :         /* this reconstructed structure was disconnected */
    1966                 :           0 :         pStruct1 = pStruct[iInChI][bMobileH] + k;
    1967                 :           0 :         num_fragments = pStruct1->RevInChI.num_components[INCHI_BAS];
    1968                 :           0 :         ifInChI = INCHI_BAS;
    1969                 :           0 :         ifMobileH = bHasSomeFixedH ? TAUT_NON : TAUT_YES;
    1970         [ #  # ]:           0 :         for (i = 0; i < num_fragments; i++)
    1971                 :             :         {
    1972                 :           0 :             bfMobileH = ifMobileH;
    1973         [ #  # ]:           0 :             if (!bRevInchiComponentExists(pStruct1, ifInChI, bfMobileH, i))
    1974                 :             :             {
    1975         [ #  # ]:           0 :                 if (bRevInchiComponentExists(pStruct1, ifInChI, TAUT_YES, i))
    1976                 :             :                 {
    1977                 :           0 :                     bfMobileH = TAUT_YES;
    1978                 :             :                 }
    1979                 :             :                 else
    1980                 :             :                 {
    1981                 :           0 :                     continue; /* component is missing ??? */
    1982                 :             :                 }
    1983                 :             :             }
    1984                 :           0 :             pINChISort1[n].pINChI[bfMobileH] = pStruct1->RevInChI.pINChI[ifInChI][i][bfMobileH];
    1985         [ #  # ]:           0 :             if (bfMobileH == TAUT_NON /*&& bRevInchiComponentExists( pStruct1, ifInChI, TAUT_YES, i )*/)
    1986                 :             :             {
    1987                 :           0 :                 pINChISort1[n].pINChI[TAUT_YES] = pStruct1->RevInChI.pINChI[ifInChI][i][TAUT_YES];
    1988                 :             :                 /* remove Fixed-H InChI if is is identical to Mobile-H */
    1989                 :             :                 /* do it exactly same way the identical components were removed from InpInChI */
    1990         [ #  # ]:           0 :                 if (!CompareReversedINChI(pINChISort1[n].pINChI[bfMobileH],
    1991                 :           0 :                     pINChISort1[n].pINChI[TAUT_YES], NULL, NULL))
    1992                 :             :                 {
    1993                 :           0 :                     pINChISort1[n].pINChI[bfMobileH] = NULL; /* remove Fixed-H layer */
    1994                 :             :                 }
    1995                 :             :                 else
    1996                 :             :                 {
    1997                 :           0 :                     pINChISort1[n].ord_number = pStruct1->RevInChI.pINChI_Aux[ifInChI][i][TAUT_YES]->nNumRemovedProtons;
    1998                 :             :                 }
    1999                 :             :             }
    2000                 :             : 
    2001                 :           0 :             pINChISort1[n].n1 = k;  /* reconstructed reconnected structure component index */
    2002                 :           0 :             pINChISort1[n].n2 = i;  /* index of a fragment made out of this component */
    2003                 :           0 :             n++;
    2004                 :             :         }
    2005                 :             :     }
    2006                 :             : 
    2007                 :             :     /* sort fragment InChI before comparing them */
    2008                 :           0 :     qsort(pINChISort1, num_fragments_D, sizeof(pINChISort1[0]), CompINChITaut2);
    2009                 :           0 :     qsort(pINChISort2, num_fragments_R, sizeof(pINChISort2[0]), CompINChITaut2);
    2010                 :             : 
    2011                 :             :     /* compare fragments -- components present in disconnected layer only */
    2012         [ #  # ]:           0 :     for (iComponent = 0; iComponent < num_fragments_DR; iComponent++)
    2013                 :             :     {
    2014                 :             :         INChI* pInChI1[TAUT_NUM]; /* from reversed structure */
    2015                 :             :         INChI* pInChI2[TAUT_NUM]; /* original input InChI */
    2016         [ #  # ]:           0 :         for (i = 0; i < TAUT_NUM; i++)
    2017                 :             :         {
    2018                 :           0 :             pInChI1[i] = pINChISort1[iComponent].pINChI[i];
    2019                 :           0 :             pInChI2[i] = pINChISort2[iComponent].pINChI[i];
    2020                 :             :         }
    2021                 :           0 :         CompareTwoPairsOfInChI(pInChI1, pInChI2, !bHasSomeFixedH, CompareInchiFlags);
    2022                 :             :     }
    2023                 :             : 
    2024         [ #  # ]:           0 :     if ( /*nNumNonTaut1 && nNumNonTaut2 &&*/ bHasSomeFixedH)
    2025                 :             :     {
    2026   [ #  #  #  # ]:           0 :         if (nNumCompHaveSeparateProtons_D || nNumCompHaveSeparateProtons_R)
    2027                 :             :         {
    2028                 :             :             /* for each component, compare number removed protons */
    2029                 :             :             /* comparison does not make sense if Disconnected Fixed-H layer is not present */
    2030         [ #  # ]:           0 :             for (iComponent = 0; iComponent < num_fragments_DR; iComponent++)
    2031                 :             :             {
    2032                 :             :                 NUM_H   nNumRemovedIsotopicH1[NUM_H_ISOTOPES];
    2033                 :             :                 NUM_H   nNumRemovedIsotopicH2[NUM_H_ISOTOPES];
    2034                 :             : 
    2035                 :           0 :                 memset(nNumRemovedIsotopicH1, 0, sizeof(nNumRemovedIsotopicH1)); /* djb-rwth: memset_s C11/Annex K variant? */
    2036                 :           0 :                 memset(nNumRemovedIsotopicH2, 0, sizeof(nNumRemovedIsotopicH2)); /* djb-rwth: memset_s C11/Annex K variant? */
    2037                 :             :                 /* compare removed protons */
    2038         [ #  # ]:           0 :                 if (pINChISort1[iComponent].ord_number != pINChISort2[iComponent].ord_number)
    2039                 :             :                 {
    2040                 :           0 :                     CompareInchiFlags[TAUT_YES] |= INCHIDIFF_MOBH_PROTONS; /* diff number of removed protons */
    2041                 :             :                 }
    2042                 :             :                 /* also compare removed isotopic atoms H */
    2043                 :           0 :                 k = pINChISort2[iComponent].n1; /* input InChI, OneInput */
    2044         [ #  # ]:           0 :                 if (pOneInput->nNumProtons[INCHI_BAS][TAUT_YES].pNumProtons)
    2045                 :             :                 {
    2046                 :           0 :                     memcpy(nNumRemovedIsotopicH2,
    2047                 :           0 :                         pOneInput->nNumProtons[INCHI_BAS][TAUT_YES].pNumProtons[k].nNumRemovedIsotopicH,
    2048                 :             :                         sizeof(nNumRemovedIsotopicH2));
    2049                 :             :                 }
    2050                 :             :                 /* get fragments of reconstructed structure removed protons info */
    2051                 :           0 :                 k = pINChISort1[iComponent].n1; /* restored component number */
    2052                 :           0 :                 i = pINChISort1[iComponent].n2; /* subcomponent number */
    2053                 :           0 :                 iInChI = INCHI_REC;
    2054   [ #  #  #  # ]:           0 :                 iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
    2055                 :           0 :                 bMobileH = iMobileH;
    2056         [ #  # ]:           0 :                 if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
    2057                 :             :                 {
    2058         [ #  # ]:           0 :                     if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
    2059                 :             :                     {
    2060                 :           0 :                         bMobileH = TAUT_YES;
    2061                 :             :                     }
    2062                 :             :                     else
    2063                 :             :                     {
    2064                 :           0 :                         goto compare_iso_H;
    2065                 :             :                     }
    2066                 :             :                 }
    2067         [ #  # ]:           0 :                 if (pOneInput->pInpInChI[iInChI][bMobileH][k].nLink)
    2068                 :             :                 {
    2069                 :           0 :                     continue;
    2070                 :             :                     /*
    2071                 :             :                     ret = RI_ERR_PROGR;
    2072                 :             :                     goto exit_function;
    2073                 :             :                     */
    2074                 :             :                 }
    2075                 :           0 :                 pStruct1 = pStruct[iInChI][bMobileH] + k;
    2076                 :           0 :                 num_fragments = pStruct1->RevInChI.num_components[INCHI_BAS];
    2077                 :           0 :                 ifInChI = INCHI_BAS;
    2078                 :           0 :                 ifMobileH = bHasSomeFixedH ? TAUT_NON : TAUT_YES;
    2079         [ #  # ]:           0 :                 if (i < num_fragments)
    2080                 :             :                 {
    2081                 :           0 :                     bfMobileH = ifMobileH;
    2082         [ #  # ]:           0 :                     if (!bRevInchiComponentExists(pStruct1, ifInChI, bfMobileH, i))
    2083                 :             :                     {
    2084         [ #  # ]:           0 :                         if (!bRevInchiComponentExists(pStruct1, ifInChI, TAUT_YES, i))
    2085                 :             :                             /* djb-rwth: removing redundant code */
    2086                 :             :                         {
    2087                 :           0 :                             goto compare_iso_H;
    2088                 :             :                         }
    2089                 :             :                     }
    2090                 :           0 :                     memcpy(nNumRemovedIsotopicH1,
    2091                 :           0 :                         pStruct1->RevInChI.pINChI_Aux[ifInChI][i][TAUT_YES]->nNumRemovedIsotopicH,
    2092                 :             :                         sizeof(nNumRemovedIsotopicH1));
    2093                 :             :                 }
    2094                 :           0 :             compare_iso_H:
    2095         [ #  # ]:           0 :                 if (memcmp(nNumRemovedIsotopicH1, nNumRemovedIsotopicH2, sizeof(nNumRemovedIsotopicH1)))
    2096                 :             :                 {
    2097                 :           0 :                     CompareInchiFlags[TAUT_YES] |= INCHIDIFF_REM_ISO_H;
    2098                 :             :                 }
    2099                 :             :             }
    2100                 :             :         }
    2101                 :             :     }
    2102                 :             :     else /*if ( !nNumNonTaut1 && !nNumNonTaut2 || !bHasSomeFixedH )*/
    2103                 :             :     {
    2104                 :             :         /* compare totals for removed protons and isotopic H */
    2105                 :           0 :         if (pOneInput->nNumProtons[INCHI_BAS][TAUT_YES].nNumRemovedProtons !=
    2106         [ #  # ]:           0 :             nNumRemovedProtons_R.nNumRemovedProtons)
    2107                 :             :         {
    2108                 :           0 :             CompareInchiFlags[TAUT_YES] |= INCHIDIFF_MOBH_PROTONS;
    2109                 :             :         }
    2110         [ #  # ]:           0 :         if (memcmp(pOneInput->nNumProtons[INCHI_BAS][TAUT_YES].nNumRemovedIsotopicH,
    2111                 :             :             nNumRemovedProtons_R.nNumRemovedIsotopicH,
    2112                 :             :             sizeof(nNumRemovedProtons_R.nNumRemovedIsotopicH)))
    2113                 :             :         {
    2114                 :           0 :             CompareInchiFlags[TAUT_YES] |= INCHIDIFF_REM_ISO_H;
    2115                 :             :         }
    2116                 :             :     }
    2117                 :             : 
    2118         [ #  # ]:           0 :     if (!nNumNonTaut1 == !nNumNonTaut2)
    2119                 :             :     {
    2120                 :             :         ; /* difference if(nNumNonTaut1 != nNumNonTaut2) will be caught in InChI comparison */
    2121                 :             :     }
    2122                 :             :     else
    2123                 :             :     {
    2124         [ #  # ]:           0 :         if (nNumNonTaut1)
    2125                 :             :         {
    2126                 :             :             /* reconstructed has Fixed-H while the original has not: extra Fixed-H layer */
    2127                 :           0 :             CompareInchiFlags[TAUT_YES] |= INCHIDIFF_WRONG_TAUT;
    2128                 :             :         }
    2129                 :             :         else
    2130                 :             :         {
    2131                 :             :             /* the original InChI has Fixed-H while the reconstructed one has not: missing Fixed-H layer */
    2132                 :           0 :             CompareInchiFlags[TAUT_YES] |= INCHIDIFF_NO_TAUT;
    2133                 :             :         }
    2134                 :             :     }
    2135         [ #  # ]:           0 :     for (i = 0; i < TAUT_NUM; i++)
    2136                 :             :     {
    2137                 :           0 :         pOneInput->CompareInchiFlags[1][i] |= CompareInchiFlags[i];
    2138                 :             :     }
    2139                 :             : 
    2140                 :             :     /* compare totals */
    2141         [ #  # ]:           0 :     if (nNumRemovedProtons_R.nNumRemovedProtons != nNumRemovedProtons_D.nNumRemovedProtons)
    2142                 :             :     {
    2143                 :           0 :         CompareInchiFlags[TAUT_YES] |= INCHIDIFF_MOBH_PROTONS; /* diff number of removed protons */
    2144                 :             :     }
    2145         [ #  # ]:           0 :     if (memcmp(nNumRemovedProtons_R.nNumRemovedIsotopicH,
    2146                 :             :         nNumRemovedProtons_D.nNumRemovedIsotopicH,
    2147                 :             :         sizeof(nNumRemovedProtons_D.nNumRemovedIsotopicH)))
    2148                 :             :     {
    2149                 :           0 :         CompareInchiFlags[TAUT_YES] |= INCHIDIFF_REM_ISO_H;
    2150                 :             :     }
    2151                 :             : 
    2152                 :           0 : exit_function:
    2153                 :             : 
    2154         [ #  # ]:           0 :     if (pINChISort1)
    2155                 :             :     {
    2156         [ #  # ]:           0 :         inchi_free(pINChISort1);
    2157                 :             :     }
    2158         [ #  # ]:           0 :     if (pINChISort2)
    2159                 :             :     {
    2160         [ #  # ]:           0 :         inchi_free(pINChISort2);
    2161                 :             :     }
    2162                 :             : 
    2163                 :           0 :     return ret;
    2164                 :             : }
    2165                 :             : 
    2166                 :             : 
    2167                 :             : /****************************************************************************/
    2168                 :           0 : int CompareTwoPairsOfInChI(INChI* pInChI1[TAUT_NUM],
    2169                 :             :     INChI* pInChI2[TAUT_NUM],
    2170                 :             :     int bMobileH,
    2171                 :             :     INCHI_MODE CompareInchiFlags[])
    2172                 :             : {
    2173                 :           0 :     int iMobileH, err = 0;
    2174                 :             :     INCHI_MODE cmp;
    2175         [ #  # ]:           0 :     for (iMobileH = 0; iMobileH < TAUT_NUM; iMobileH++)
    2176                 :             :     {
    2177         [ #  # ]:           0 :         if (!pInChI1[iMobileH] != !pInChI2[iMobileH])
    2178                 :             :         {
    2179         [ #  # ]:           0 :             if (iMobileH == TAUT_NON &&
    2180   [ #  #  #  # ]:           0 :                 pInChI1[TAUT_YES] && pInChI2[TAUT_YES]) /* djb-rwth: condition corrected */
    2181                 :             :             {
    2182                 :           0 :                 CompareInchiFlags[iMobileH] |= INCHIDIFF_COMP_HLAYER;
    2183                 :             :             }
    2184                 :             :             else
    2185                 :             :             {
    2186                 :           0 :                 CompareInchiFlags[iMobileH] |= INCHIDIFF_COMP_NUMBER;
    2187                 :             :             }
    2188                 :           0 :             continue;
    2189                 :             :         }
    2190   [ #  #  #  # ]:           0 :         if (pInChI1[iMobileH] && pInChI2[iMobileH])
    2191                 :             :         {
    2192                 :           0 :             cmp = CompareReversedINChI3(pInChI1[iMobileH], pInChI2[iMobileH], NULL, NULL, &err);
    2193         [ #  # ]:           0 :             if (cmp)
    2194                 :             :             {
    2195                 :           0 :                 CompareInchiFlags[iMobileH] |= cmp;
    2196                 :             :             }
    2197                 :             :         }
    2198                 :             :     }
    2199                 :             : 
    2200                 :           0 :     return err;
    2201                 :             : }
    2202                 :             : 
    2203                 :             : 
    2204                 :             : /****************************************************************************/
    2205                 :           0 : int CompareOneOrigInchiToRevInChI(StrFromINChI* pStruct,
    2206                 :             :     INChI* pInChI[TAUT_NUM],
    2207                 :             :     int bMobileH,
    2208                 :             :     int iComponent,
    2209                 :             :     long num_inp,
    2210                 :             :     char* szCurHdr,
    2211                 :             :     COMPONENT_REM_PROTONS* nCurRemovedProtons,
    2212                 :             :     INCHI_MODE CompareInchiFlags[])
    2213                 :             : {
    2214                 :           0 :     int ret, err = 0;
    2215                 :             :     INCHI_MODE cmp;
    2216                 :             : 
    2217         [ #  # ]:           0 :     if (pStruct) /* djb-rwth: fixing coverity ID #499601 */
    2218                 :             :     {
    2219                 :           0 :         ret = pStruct->RevInChI.nRetVal;
    2220                 :             :     }
    2221                 :             :     else
    2222                 :             :     {
    2223                 :           0 :         ret = -1;
    2224                 :             :     }
    2225                 :             : 
    2226   [ #  #  #  #  :           0 :     if ((ret == _IS_OKAY || ret == _IS_WARNING) && pStruct) /* djb-rwth: fixing a NULL pointer dereference */
                   #  # ]
    2227                 :           0 :     {
    2228                 :             :         /* ignore bMobileH for now */
    2229                 :             :         int i, i0, b /* created type */, b0 /* requested type*/, j, k;
    2230                 :             :         /* pINChI[iINCHI][iComponent][bTaut] */
    2231                 :             :         /* i0 = requested Rec/Disconnected: 1/0 */
    2232                 :             :         /* i  = what InChI creaded out of the restored structure */
    2233                 :             :         /* b0 = requested Mobile/Fixed-H: 1/0 */
    2234                 :             :         /* b  = what InChI creaded out of the restored structure */
    2235                 :           0 :         i = i0 = pStruct->iINCHI;
    2236                 :           0 :         b = b0 = pStruct->iMobileH;
    2237   [ #  #  #  # ]:           0 :         if (i == INCHI_REC && !pStruct->RevInChI.num_components[i])
    2238                 :             :         {
    2239                 :           0 :             i = INCHI_BAS;
    2240                 :             :         }
    2241   [ #  #  #  # ]:           0 :         if (b == TAUT_NON && (!pStruct->RevInChI.pINChI[i] ||
    2242         [ #  # ]:           0 :             !pStruct->RevInChI.pINChI[i][0][b] ||
    2243         [ #  # ]:           0 :             !pStruct->RevInChI.pINChI[i][0][b]->nNumberOfAtoms))
    2244                 :             :         {
    2245                 :           0 :             b = TAUT_YES;
    2246                 :             :         }
    2247   [ #  #  #  #  :           0 :         if (pStruct->bDeleted && (!pInChI[0] || pInChI[0]->bDeleted))
                   #  # ]
    2248                 :             :         {
    2249                 :           0 :             return 0;
    2250                 :             :         }
    2251                 :             : 
    2252         [ #  # ]:           0 :         if (pStruct->RevInChI.pINChI[i]) /* djb-rwth: fixing a NULL pointer dereference */
    2253                 :             :         {
    2254         [ #  # ]:           0 :             if ((pStruct->RevInChI.num_components[i] > 1 &&
    2255         [ #  # ]:           0 :                 !pStruct->RevInChI.pINChI[i][1][b]->bDeleted) ||
    2256         [ #  # ]:           0 :                 pStruct->RevInChI.num_components[i] < 1) /* djb-rwth: addressing LLVM warning */
    2257                 :             :             {
    2258                 :           0 :                 CompareInchiFlags[bMobileH] |= INCHIDIFF_COMP_NUMBER;
    2259                 :             :             }
    2260                 :             :         }
    2261   [ #  #  #  #  :           0 :         if (b != b0 || b != bMobileH || b0 != bMobileH || i > i0)
             #  #  #  # ]
    2262                 :             :         {
    2263                 :             :             /* do not print messages about TAUT_YES instead of TAUT_NON */
    2264                 :           0 :             CompareInchiFlags[bMobileH] |= INCHIDIFF_COMP_HLAYER;
    2265                 :             :         }
    2266                 :             : 
    2267   [ #  #  #  # ]:           0 :         if (pStruct->RevInChI.num_components[i] && pStruct->RevInChI.pINChI[i]) /* djb-rwth: fixing a NULL pointer dereference */
    2268                 :             :         {
    2269                 :             :             /* compare InChI from restored structure; '0' in [i][0][b] is the first component */
    2270   [ #  #  #  #  :           0 :             if (b == TAUT_YES && pStruct->RevInChI.pINChI[i][0][b]->bDeleted && ( !pInChI[0] || pInChI[0]->bDeleted ))
             #  #  #  # ]
    2271                 :             :             {
    2272                 :             :                 /* the 1st component is made out of proton(s) and the input component is missing or also a proton */
    2273                 :           0 :                 cmp = 0;
    2274                 :             :             }
    2275                 :             :             else
    2276                 :             :             {
    2277                 :           0 :                 cmp = CompareReversedINChI3( pStruct->RevInChI.pINChI[i][0][b], pInChI[0], NULL, NULL, &err );
    2278         [ #  # ]:           0 :                 if (cmp)
    2279                 :             :                 {
    2280                 :           0 :                     CompareInchiFlags[bMobileH] |= cmp;
    2281                 :             :                 }
    2282                 :             :             }
    2283   [ #  #  #  # ]:           0 :             if (b == b0 && b == TAUT_NON)
    2284                 :             :             {
    2285         [ #  # ]:           0 :                 if ((pStruct->RevInChI.pINChI[i][0][TAUT_YES] &&
    2286         [ #  # ]:           0 :                     !pStruct->RevInChI.pINChI[i][0][TAUT_YES]->bDeleted) ||
    2287   [ #  #  #  # ]:           0 :                     (pInChI[1] && !pInChI[1]->bDeleted)) /* djb-rwth: addressing LLVM warnings */
    2288                 :             :                 {
    2289                 :             :                     /* in addition to fixed-H also compare mobile-H InChI */
    2290                 :           0 :                     cmp = CompareReversedINChI3(pStruct->RevInChI.pINChI[i][0][TAUT_YES], pInChI[1], NULL, NULL, &err);
    2291         [ #  # ]:           0 :                     if (cmp)
    2292                 :             :                     {
    2293                 :           0 :                         CompareInchiFlags[TAUT_YES] |= cmp;
    2294                 :             :                     }
    2295                 :             :                 }
    2296                 :             :                 /* compare removed H */
    2297         [ #  # ]:           0 :                 if (pStruct->nNumRemovedProtonsMobHInChI != pStruct->RevInChI.pINChI_Aux[i][0][TAUT_YES]->nNumRemovedProtons)
    2298                 :             :                 {
    2299                 :           0 :                     CompareInchiFlags[TAUT_YES] |= INCHIDIFF_MOBH_PROTONS;
    2300                 :             :                 }
    2301                 :             :             }
    2302                 :           0 :             memset(nCurRemovedProtons, 0, sizeof(*nCurRemovedProtons)); /* djb-rwth: memset_s C11/Annex K variant? */
    2303         [ #  # ]:           0 :             for (k = 0; k < pStruct->RevInChI.num_components[i]; k++)
    2304                 :             :             {
    2305   [ #  #  #  # ]:           0 :                 if (!k || pStruct->RevInChI.pINChI[i][k][TAUT_YES]->bDeleted)
    2306                 :             :                 {
    2307                 :             :                     /* get removed protons from the 1st component; add othere only if they are deleted protons */
    2308                 :           0 :                     nCurRemovedProtons->nNumRemovedProtons += pStruct->RevInChI.pINChI_Aux[i][k][TAUT_YES]->nNumRemovedProtons;
    2309         [ #  # ]:           0 :                     for (j = 0; j < NUM_H_ISOTOPES; j++)
    2310                 :             :                     {
    2311                 :           0 :                         nCurRemovedProtons->nNumRemovedIsotopicH[j] += pStruct->RevInChI.pINChI_Aux[i][k][TAUT_YES]->nNumRemovedIsotopicH[j];
    2312                 :             :                     }
    2313                 :             :                 }
    2314                 :             :             }
    2315                 :             :         }
    2316                 :             :     }
    2317                 :             :     else
    2318                 :             :     {
    2319                 :           0 :         CompareInchiFlags[bMobileH] |= INCHIDIFF_STR2INCHI_ERR;
    2320                 :             :     }
    2321                 :             : 
    2322                 :           0 :     return err;
    2323                 :             : }
    2324                 :             : 
    2325                 :             : 
    2326                 :             : /****************************************************************************/
    2327                 :           0 : INCHI_MODE CompareReversedStereoINChI3(INChI_Stereo* s1,
    2328                 :             :     /* InChI from reversed struct   */
    2329                 :             :     INChI_Stereo* s2,
    2330                 :             :     /* input InChI                  */
    2331                 :             :     ICR* picr)
    2332                 :             : {
    2333                 :           0 :     int ret = 0;
    2334                 :             :     int j1, j2, num_dif, num_extra_undf, num_miss_undf, num_in1_only, num_in2_only; /* djb-rwth: removing redundant variables */
    2335                 :           0 :     int bAddSb = !(picr->num_sb_undef_in1_only + picr->num_sb_in1_only + picr->num_sb_in2_only);
    2336                 :           0 :     int bAddSc = !(picr->num_sc_undef_in1_only + picr->num_sc_in1_only + picr->num_sc_in2_only);
    2337                 :             : 
    2338         [ #  # ]:           0 :     int nNumSc1 = s1 ? s1->nNumberOfStereoCenters : 0;
    2339         [ #  # ]:           0 :     int nNumSc2 = s2 ? s2->nNumberOfStereoCenters : 0;
    2340         [ #  # ]:           0 :     int nNumSb1 = s1 ? s1->nNumberOfStereoBonds : 0;
    2341         [ #  # ]:           0 :     int nNumSb2 = s2 ? s2->nNumberOfStereoBonds : 0;
    2342                 :             : 
    2343   [ #  #  #  #  :           0 :     if ((nNumSc1 || nNumSc2) &&
                   #  # ]
    2344                 :           0 :         (nNumSc1 != nNumSc2 ||
    2345         [ #  # ]:           0 :             memcmp(s1->nNumber, s2->nNumber, nNumSc1 * sizeof(s1->nNumber[0])) ||
    2346         [ #  # ]:           0 :             memcmp(s1->t_parity, s2->t_parity, nNumSc1 * sizeof(s1->t_parity[0])))) /* djb-rwth: condition corrected */
    2347                 :             :     {
    2348                 :             : 
    2349                 :           0 :         num_dif = num_extra_undf = num_miss_undf = num_in1_only = num_in2_only = 0; /* djb-rwth: removing redundant code */
    2350   [ #  #  #  # ]:           0 :         for (j1 = j2 = 0; j1 < nNumSc1 && j2 < nNumSc2; )
    2351                 :             :         {
    2352         [ #  # ]:           0 :             if (s1->nNumber[j1] == s2->nNumber[j2])
    2353                 :             :             {
    2354         [ #  # ]:           0 :                 if (s1->t_parity[j1] != s2->t_parity[j2])
    2355                 :             :                     /* djb-rwth: removing redundant code */
    2356                 :             :                 {
    2357                 :           0 :                     num_dif++;
    2358                 :             :                 }
    2359                 :           0 :                 j1++;
    2360                 :           0 :                 j2++;
    2361                 :             :             }
    2362                 :             :             else
    2363                 :             :             {
    2364         [ #  # ]:           0 :                 if (s1->nNumber[j1] < s2->nNumber[j2])
    2365                 :             :                 {
    2366                 :           0 :                     num_in1_only++;
    2367         [ #  # ]:           0 :                     if (s1->t_parity[j1] == AB_PARITY_UNDF)
    2368                 :             :                     {
    2369                 :           0 :                         num_extra_undf++;
    2370                 :             :                     }
    2371         [ #  # ]:           0 :                     if (bAddSc)
    2372                 :             :                     {
    2373         [ #  # ]:           0 :                         if (picr->num_sc_in1_only < ICR_MAX_SC_IN1_ONLY)
    2374                 :           0 :                             picr->sc_in1_only[picr->num_sc_in1_only++] = j1;
    2375         [ #  # ]:           0 :                         if (s1->t_parity[j1] == AB_PARITY_UNDF)
    2376                 :             :                         {
    2377         [ #  # ]:           0 :                             if (picr->num_sc_undef_in1_only < ICR_MAX_SC_UNDF)
    2378                 :           0 :                                 picr->sc_undef_in1_only[picr->num_sc_undef_in1_only++] = j1;
    2379                 :             :                         }
    2380                 :             :                     }
    2381                 :           0 :                     j1++;
    2382                 :             :                 }
    2383                 :             :                 else
    2384                 :             :                 {
    2385                 :           0 :                     num_in2_only++;
    2386         [ #  # ]:           0 :                     if (s2->t_parity[j2] == AB_PARITY_UNDF)
    2387                 :             :                     {
    2388                 :           0 :                         num_miss_undf++;
    2389                 :             :                     }
    2390         [ #  # ]:           0 :                     if (bAddSc)
    2391                 :             :                     {
    2392         [ #  # ]:           0 :                         if (picr->num_sc_in2_only < ICR_MAX_SC_IN2_ONLY)
    2393                 :           0 :                             picr->sc_in2_only[picr->num_sc_in2_only++] = j2;
    2394         [ #  # ]:           0 :                         if (s2->t_parity[j2] == AB_PARITY_UNDF)
    2395                 :             :                         {
    2396         [ #  # ]:           0 :                             if (picr->num_sc_undef_in2_only < ICR_MAX_SC_UNDF)
    2397                 :           0 :                                 picr->sc_undef_in2_only[picr->num_sc_undef_in2_only++] = j1;
    2398                 :             :                         }
    2399                 :             :                     }
    2400                 :           0 :                     j2++;
    2401                 :             :                 }
    2402                 :             :             }
    2403                 :             :         }
    2404                 :             : 
    2405         [ #  # ]:           0 :         while (j1 < nNumSc1)
    2406                 :             :         {
    2407         [ #  # ]:           0 :             if (s1->t_parity[j1] == AB_PARITY_UNDF)
    2408                 :             :             {
    2409                 :           0 :                 num_extra_undf++;
    2410                 :             :             }
    2411                 :           0 :             num_in1_only++;
    2412         [ #  # ]:           0 :             if (bAddSc)
    2413                 :             :             {
    2414         [ #  # ]:           0 :                 if (picr->num_sc_in1_only < ICR_MAX_SC_IN1_ONLY)
    2415                 :           0 :                     picr->sc_in1_only[picr->num_sc_in1_only++] = j1;
    2416         [ #  # ]:           0 :                 if (s1->t_parity[j1] == AB_PARITY_UNDF)
    2417                 :             :                 {
    2418         [ #  # ]:           0 :                     if (picr->num_sc_undef_in1_only < ICR_MAX_SC_UNDF)
    2419                 :           0 :                         picr->sc_undef_in1_only[picr->num_sc_undef_in1_only++] = j1;
    2420                 :             :                 }
    2421                 :             :             }
    2422                 :           0 :             j1++;
    2423                 :             :         }
    2424                 :             : 
    2425         [ #  # ]:           0 :         while (j2 < nNumSc2)
    2426                 :             :         {
    2427         [ #  # ]:           0 :             if (s2->t_parity[j2] == AB_PARITY_UNDF)
    2428                 :             :             {
    2429                 :           0 :                 num_miss_undf++;
    2430                 :             :             }
    2431                 :           0 :             num_in2_only++;
    2432         [ #  # ]:           0 :             if (bAddSc)
    2433                 :             :             {
    2434         [ #  # ]:           0 :                 if (picr->num_sc_in2_only < ICR_MAX_SC_IN2_ONLY)
    2435                 :           0 :                     picr->sc_in2_only[picr->num_sc_in2_only++] = j2;
    2436                 :             :             }
    2437                 :           0 :             j2++;
    2438                 :             :         }
    2439                 :             : 
    2440         [ #  # ]:           0 :         if (num_dif)
    2441                 :             :         {
    2442                 :           0 :             ret |= INCHIDIFF_SC_PARITY;
    2443                 :             :         }
    2444         [ #  # ]:           0 :         if (num_in1_only)
    2445                 :             :         {
    2446         [ #  # ]:           0 :             if (num_extra_undf)
    2447                 :             :             {
    2448                 :           0 :                 ret |= INCHIDIFF_SC_EXTRA_UNDF;
    2449                 :             :             }
    2450         [ #  # ]:           0 :             if (num_in1_only != num_extra_undf)
    2451                 :             :             {
    2452                 :           0 :                 ret |= INCHIDIFF_SC_EXTRA;
    2453                 :             :             }
    2454                 :             :         }
    2455         [ #  # ]:           0 :         if (num_in2_only)
    2456                 :             :         {
    2457         [ #  # ]:           0 :             if (num_miss_undf)
    2458                 :             :             {
    2459                 :           0 :                 ret |= INCHIDIFF_SC_MISS_UNDF;
    2460                 :             :             }
    2461         [ #  # ]:           0 :             if (num_in2_only != num_miss_undf)
    2462                 :             :             {
    2463                 :           0 :                 ret |= INCHIDIFF_SC_MISS;
    2464                 :             :             }
    2465                 :             :         }
    2466                 :             :     }
    2467                 :             : 
    2468   [ #  #  #  #  :           0 :     if (s1 && s2 && (s2->nCompInv2Abs != 2) && s1->nCompInv2Abs != s2->nCompInv2Abs && s1->nCompInv2Abs && s2->nCompInv2Abs)
          #  #  #  #  #  
                #  #  # ]
    2469                 :             :     {
    2470                 :           0 :         ret |= INCHIDIFF_SC_INV; /* 2007-07-13 DT: added (s2->nCompInv2Abs != 2) to fix bug reoprted by Yerin on 2007/02/28 */
    2471                 :             :         /* Bug description: falsely reported "Stereo centers/allenes: Falsely inverted" for /S2 or /S3 */
    2472                 :             :     }
    2473                 :             : 
    2474   [ #  #  #  #  :           0 :     if ((nNumSb1 || nNumSb2) &&
                   #  # ]
    2475                 :           0 :         (nNumSb1 != nNumSb2 ||
    2476         [ #  # ]:           0 :             memcmp(s1->nBondAtom1, s2->nBondAtom1, nNumSb1 * sizeof(s1->nBondAtom1[0])) ||
    2477         [ #  # ]:           0 :             memcmp(s1->nBondAtom2, s2->nBondAtom2, nNumSb1 * sizeof(s1->nBondAtom2[0])) ||
    2478         [ #  # ]:           0 :             memcmp(s1->b_parity, s2->b_parity, nNumSb1 * sizeof(s1->b_parity[0]))))
    2479                 :             :     {
    2480                 :             : 
    2481                 :           0 :         num_dif = num_extra_undf = num_miss_undf = num_in1_only = num_in2_only = 0; /* djb-rwth: removing redundant code */
    2482   [ #  #  #  # ]:           0 :         for (j1 = j2 = 0; j1 < nNumSb1 && j2 < nNumSb2; )
    2483                 :             :         {
    2484         [ #  # ]:           0 :             if (s1->nBondAtom1[j1] == s2->nBondAtom1[j2] &&
    2485         [ #  # ]:           0 :                 s1->nBondAtom2[j1] == s2->nBondAtom2[j2])
    2486                 :             :             {
    2487         [ #  # ]:           0 :                 if (s1->b_parity[j1] != s2->b_parity[j2])
    2488                 :             :                     /* djb-rwth: removing redundant code */
    2489                 :             :                 {
    2490                 :           0 :                     num_dif++;
    2491                 :             :                 }
    2492                 :           0 :                 j1++;
    2493                 :           0 :                 j2++;
    2494                 :             :             }
    2495                 :             :             else
    2496                 :             :             {
    2497         [ #  # ]:           0 :                 if (s1->nBondAtom1[j1] < s2->nBondAtom1[j2] ||
    2498   [ #  #  #  # ]:           0 :                     (s1->nBondAtom1[j1] == s2->nBondAtom1[j2] && s1->nBondAtom2[j1] < s2->nBondAtom2[j2])) /* djb-rwth: addressing LLVM warning */
    2499                 :             :                 {
    2500                 :           0 :                     num_in1_only++;
    2501         [ #  # ]:           0 :                     if (s1->b_parity[j1] == AB_PARITY_UNDF)
    2502                 :             :                     {
    2503                 :           0 :                         num_extra_undf++;
    2504                 :             :                     }
    2505         [ #  # ]:           0 :                     if (bAddSb)
    2506                 :             :                     {
    2507         [ #  # ]:           0 :                         if (picr->num_sb_in1_only < ICR_MAX_SB_IN1_ONLY)
    2508                 :           0 :                             picr->sb_in1_only[picr->num_sb_in1_only++] = j1;
    2509         [ #  # ]:           0 :                         if (s1->b_parity[j1] == AB_PARITY_UNDF)
    2510                 :             :                         {
    2511         [ #  # ]:           0 :                             if (picr->num_sb_undef_in1_only < ICR_MAX_SB_UNDF)
    2512                 :           0 :                                 picr->sb_undef_in1_only[picr->num_sb_undef_in1_only++] = j1;
    2513                 :             :                         }
    2514                 :             :                     }
    2515                 :           0 :                     j1++;
    2516                 :             :                 }
    2517                 :             :                 else
    2518                 :             :                 {
    2519                 :           0 :                     num_in2_only++;
    2520         [ #  # ]:           0 :                     if (s2->b_parity[j2] == AB_PARITY_UNDF)
    2521                 :             :                     {
    2522                 :           0 :                         num_miss_undf++;
    2523                 :             :                     }
    2524         [ #  # ]:           0 :                     if (bAddSb)
    2525                 :             :                     {
    2526         [ #  # ]:           0 :                         if (picr->num_sb_in2_only < ICR_MAX_SB_IN2_ONLY)
    2527                 :           0 :                             picr->sb_in2_only[picr->num_sb_in2_only++] = j2;
    2528         [ #  # ]:           0 :                         if (s2->b_parity[j2] == AB_PARITY_UNDF)
    2529                 :             :                         {
    2530         [ #  # ]:           0 :                             if (picr->num_sb_undef_in2_only < ICR_MAX_SB_UNDF)
    2531                 :           0 :                                 picr->sb_undef_in2_only[picr->num_sb_undef_in2_only++] = j1;
    2532                 :             :                         }
    2533                 :             :                     }
    2534                 :           0 :                     j2++;
    2535                 :             :                 }
    2536                 :             :             }
    2537                 :             :         }
    2538         [ #  # ]:           0 :         while (j1 < nNumSb1)
    2539                 :             :         {
    2540                 :           0 :             num_in1_only++;
    2541         [ #  # ]:           0 :             if (s1->b_parity[j1] == AB_PARITY_UNDF)
    2542                 :             :             {
    2543                 :           0 :                 num_extra_undf++;
    2544                 :             :             }
    2545         [ #  # ]:           0 :             if (bAddSb)
    2546                 :             :             {
    2547         [ #  # ]:           0 :                 if (picr->num_sb_in1_only < ICR_MAX_SB_IN1_ONLY)
    2548                 :           0 :                     picr->sb_in1_only[picr->num_sb_in1_only++] = j1;
    2549         [ #  # ]:           0 :                 if (s1->b_parity[j1] == AB_PARITY_UNDF)
    2550                 :             :                 {
    2551         [ #  # ]:           0 :                     if (picr->num_sb_undef_in1_only < ICR_MAX_SB_UNDF)
    2552                 :           0 :                         picr->sb_undef_in1_only[picr->num_sb_undef_in1_only++] = j1;
    2553                 :             :                 }
    2554                 :             :             }
    2555                 :           0 :             j1++;
    2556                 :             :         }
    2557         [ #  # ]:           0 :         while (j2 < nNumSb2)
    2558                 :             :         {
    2559                 :           0 :             num_in2_only++;
    2560         [ #  # ]:           0 :             if (s2->b_parity[j2] == AB_PARITY_UNDF)
    2561                 :             :             {
    2562                 :           0 :                 num_miss_undf++;
    2563                 :             :             }
    2564         [ #  # ]:           0 :             if (bAddSb)
    2565                 :             :             {
    2566         [ #  # ]:           0 :                 if (picr->num_sb_in2_only < ICR_MAX_SB_IN2_ONLY)
    2567                 :           0 :                     picr->sb_in2_only[picr->num_sb_in2_only++] = j2;
    2568         [ #  # ]:           0 :                 if (s2->b_parity[j2] == AB_PARITY_UNDF)
    2569                 :             :                 {
    2570         [ #  # ]:           0 :                     if (picr->num_sb_undef_in2_only < ICR_MAX_SB_UNDF)
    2571                 :           0 :                         picr->sb_undef_in2_only[picr->num_sb_undef_in2_only++] = j1;
    2572                 :             :                 }
    2573                 :             :             }
    2574                 :           0 :             j2++;
    2575                 :             :         }
    2576         [ #  # ]:           0 :         if (num_dif)
    2577                 :             :         {
    2578                 :           0 :             ret |= INCHIDIFF_SB_PARITY;
    2579                 :             :         }
    2580         [ #  # ]:           0 :         if (num_in1_only)
    2581                 :             :         {
    2582         [ #  # ]:           0 :             if (num_extra_undf)
    2583                 :             :             {
    2584                 :           0 :                 ret |= INCHIDIFF_SB_EXTRA_UNDF;
    2585                 :             :             }
    2586         [ #  # ]:           0 :             if (num_in1_only != num_extra_undf)
    2587                 :             :             {
    2588                 :           0 :                 ret |= INCHIDIFF_SB_EXTRA;
    2589                 :             :             }
    2590                 :             :         }
    2591         [ #  # ]:           0 :         if (num_in2_only)
    2592                 :             :         {
    2593         [ #  # ]:           0 :             if (num_miss_undf)
    2594                 :             :             {
    2595                 :           0 :                 ret |= INCHIDIFF_SB_MISS_UNDF;
    2596                 :             :             }
    2597         [ #  # ]:           0 :             if (num_in2_only != num_miss_undf)
    2598                 :             :             {
    2599                 :           0 :                 ret |= INCHIDIFF_SB_MISS;
    2600                 :             :             }
    2601                 :             :         }
    2602                 :             :     }
    2603                 :             : 
    2604                 :           0 :     return ret;
    2605                 :             : }
    2606                 :             : 
    2607                 :             : 
    2608                 :             : /****************************************************************************/
    2609                 :           0 : INCHI_MODE CompareReversedINChI3(INChI* i1 /* InChI from reversed struct */,
    2610                 :             :     INChI* i2 /* input InChI */,
    2611                 :             :     INChI_Aux* a1,
    2612                 :             :     INChI_Aux* a2,
    2613                 :             :     int* err)
    2614                 :             : {
    2615                 :           0 :     INCHI_MODE ret = 0;
    2616                 :           0 :     INChI_Stereo* Stereo1 = NULL, * Stereo2 = NULL;
    2617                 :             :     int  n1, n2, m, j, j1, j2, ret2, num_H1, num_H2;
    2618                 :             :     ICR icr;
    2619                 :           0 :     ICR* picr = &icr;
    2620                 :             : 
    2621                 :           0 :     *err = 0;
    2622                 :             : 
    2623                 :           0 :     memset(picr, 0, sizeof(*picr)); /* djb-rwth: memset_s C11/Annex K variant? */
    2624                 :             : 
    2625   [ #  #  #  # ]:           0 :     if (i1 == NULL && i2 == NULL)
    2626                 :             :     {
    2627                 :           0 :         return 0;
    2628                 :             :     }
    2629         [ #  # ]:           0 :     if ((i1 == NULL) ^ (i2 == NULL))
    2630                 :             :     {
    2631                 :           0 :         ret |= INCHIDIFF_PROBLEM; /* one InChI exists while another doesn't */
    2632                 :           0 :         goto exit_function;
    2633                 :             :     }
    2634                 :             : 
    2635         [ #  # ]:           0 :     if (i1->nErrorCode == i2->nErrorCode)
    2636                 :             :     {
    2637         [ #  # ]:           0 :         if (i1->nErrorCode)
    2638                 :             :         {
    2639                 :           0 :             ret |= INCHIDIFF_PROBLEM; /* both InChI have same error codes */
    2640                 :           0 :             goto exit_function;
    2641                 :             :         }
    2642                 :             :     }
    2643                 :             :     else
    2644                 :             :     {
    2645                 :           0 :         ret |= INCHIDIFF_PROBLEM; /* at least one InChI has an error code */
    2646                 :           0 :         goto exit_function;
    2647                 :             :     }
    2648                 :             : 
    2649         [ #  # ]:           0 :     if (i1->nNumberOfAtoms != i2->nNumberOfAtoms)
    2650                 :             :     {
    2651                 :           0 :         ret |= INCHIDIFF_NUM_AT;
    2652                 :           0 :         goto exit_function;
    2653                 :             :     }
    2654         [ #  # ]:           0 :     if (i1->nNumberOfAtoms > 0)
    2655                 :             :     {
    2656         [ #  # ]:           0 :         if (memcmp(i1->nAtom, i2->nAtom, i1->nNumberOfAtoms * sizeof(i1->nAtom[0])))
    2657                 :             :         {
    2658                 :           0 :             ret |= INCHIDIFF_ATOMS;
    2659                 :           0 :             goto exit_function;
    2660                 :             :         }
    2661                 :             :         /* INCHIDIFF_NON_TAUT_H,  INCHIDIFF_MORE_FH, INCHIDIFF_LESS_FH */
    2662         [ #  # ]:           0 :         if (memcmp(i1->nNum_H, i2->nNum_H, i1->nNumberOfAtoms * sizeof(i1->nNum_H[0])))
    2663                 :             :         {
    2664                 :           0 :             ret |= INCHIDIFF_POSITION_H;
    2665         [ #  # ]:           0 :             for (j1 = 0; j1 < i1->nNumberOfAtoms; j1++)
    2666                 :             :             {
    2667   [ #  #  #  # ]:           0 :                 if (i1->nNum_H[j1] != i2->nNum_H[j1] && picr->num_diff_pos_H < ICR_MAX_DIFF_FIXED_H)
    2668                 :             :                 {
    2669                 :           0 :                     picr->diff_pos_H_at[picr->num_diff_pos_H] = j1;
    2670                 :           0 :                     picr->diff_pos_H_nH[picr->num_diff_pos_H] = i1->nNum_H[j1] - i2->nNum_H[j1];
    2671                 :           0 :                     picr->num_diff_pos_H++;
    2672                 :             :                 }
    2673                 :             :             }
    2674                 :             :         }
    2675                 :             :         /* fixed H */
    2676   [ #  #  #  # ]:           0 :         if (i1->nNum_H_fixed || i2->nNum_H_fixed)
    2677                 :             :         {
    2678                 :           0 :             int bHasFixedH1 = 0, bHasFixedH2 = 0, i;
    2679         [ #  # ]:           0 :             if (i1->nNum_H_fixed)
    2680                 :             :             {
    2681         [ #  # ]:           0 :                 for (i = 0; i < i1->nNumberOfAtoms; i++)
    2682                 :             :                 {
    2683         [ #  # ]:           0 :                     if (i1->nNum_H_fixed[i])
    2684                 :             :                     {
    2685                 :           0 :                         bHasFixedH1++;
    2686                 :             :                     }
    2687                 :             :                 }
    2688                 :             :             }
    2689         [ #  # ]:           0 :             if (i2->nNum_H_fixed)
    2690                 :             :             {
    2691         [ #  # ]:           0 :                 for (i = 0; i < i2->nNumberOfAtoms; i++)
    2692                 :             :                 {
    2693         [ #  # ]:           0 :                     if (i2->nNum_H_fixed[i])
    2694                 :             :                     {
    2695                 :           0 :                         bHasFixedH2++;
    2696                 :             :                     }
    2697                 :             :                 }
    2698                 :             :             }
    2699   [ #  #  #  # ]:           0 :             if (bHasFixedH1 && !bHasFixedH2)
    2700                 :             :             {
    2701         [ #  # ]:           0 :                 for (i = j = 0; i < i1->nNumberOfAtoms; i++)
    2702                 :             :                 {
    2703         [ #  # ]:           0 :                     if (i1->nNum_H_fixed[i])
    2704                 :             :                     {
    2705         [ #  # ]:           0 :                         if (j < ICR_MAX_DIFF_FIXED_H)
    2706                 :             :                         {
    2707                 :           0 :                             picr->fixed_H_at1_more[j] = i;
    2708                 :           0 :                             picr->fixed_H_nH1_more[j] = i1->nNum_H_fixed[i];
    2709                 :           0 :                             j++;
    2710                 :             :                         }
    2711                 :             :                     }
    2712                 :             :                 }
    2713                 :           0 :                 picr->num_fixed_H1_more = j;
    2714                 :           0 :                 ret |= INCHIDIFF_MORE_FH; /* Extra Fixed-H */
    2715                 :             :             }
    2716                 :             :             else
    2717                 :             :             {
    2718   [ #  #  #  # ]:           0 :                 if (!bHasFixedH1 && bHasFixedH2)
    2719                 :             :                 {
    2720         [ #  # ]:           0 :                     for (i = j = 0; i < i2->nNumberOfAtoms; i++)
    2721                 :             :                     {
    2722         [ #  # ]:           0 :                         if (i2->nNum_H_fixed[i])
    2723                 :             :                         {
    2724         [ #  # ]:           0 :                             if (j < ICR_MAX_DIFF_FIXED_H)
    2725                 :             :                             {
    2726                 :           0 :                                 picr->fixed_H_at2_more[j] = i;
    2727                 :           0 :                                 picr->fixed_H_nH2_more[j] = i2->nNum_H_fixed[i];
    2728                 :           0 :                                 j++;
    2729                 :             :                             }
    2730                 :             :                         }
    2731                 :             :                     }
    2732                 :           0 :                     picr->num_fixed_H2_more = j;
    2733                 :           0 :                     ret |= INCHIDIFF_LESS_FH; /* Missed Fixed-H */
    2734                 :             :                 }
    2735                 :             :                 else
    2736                 :             :                 {
    2737   [ #  #  #  # ]:           0 :                     if (bHasFixedH1 && bHasFixedH2 &&
    2738         [ #  # ]:           0 :                         memcmp(i1->nNum_H_fixed, i2->nNum_H_fixed, i1->nNumberOfAtoms * sizeof(i1->nNum_H_fixed[0])))
    2739                 :             :                     {
    2740         [ #  # ]:           0 :                         for (i = j1 = j2 = 0; i < i1->nNumberOfAtoms; i++)
    2741                 :             :                         {
    2742         [ #  # ]:           0 :                             if (i1->nNum_H_fixed[i] > i2->nNum_H_fixed[i])
    2743                 :             :                             {
    2744         [ #  # ]:           0 :                                 if (j1 < ICR_MAX_DIFF_FIXED_H)
    2745                 :             :                                 {
    2746                 :           0 :                                     picr->fixed_H_at1_more[j1] = i;
    2747                 :           0 :                                     picr->fixed_H_nH1_more[j1] = i1->nNum_H_fixed[i] - i2->nNum_H_fixed[i];
    2748                 :           0 :                                     j1++;
    2749                 :             :                                 }
    2750                 :             :                             }
    2751                 :             :                             else
    2752         [ #  # ]:           0 :                                 if (i1->nNum_H_fixed[i] < i2->nNum_H_fixed[i])
    2753                 :             :                                 {
    2754         [ #  # ]:           0 :                                     if (j2 < ICR_MAX_DIFF_FIXED_H)
    2755                 :             :                                     {
    2756                 :           0 :                                         picr->fixed_H_at2_more[j2] = i;
    2757                 :           0 :                                         picr->fixed_H_nH2_more[j2] = i2->nNum_H_fixed[i] - i1->nNum_H_fixed[i];
    2758                 :           0 :                                         j2++;
    2759                 :             :                                     }
    2760                 :             :                                 }
    2761                 :             :                         }
    2762   [ #  #  #  # ]:           0 :                         ret |= (j1 ? INCHIDIFF_MORE_FH : 0) | (j2 ? INCHIDIFF_LESS_FH : 0);
    2763                 :           0 :                         picr->num_fixed_H1_more = j1;
    2764                 :           0 :                         picr->num_fixed_H2_more = j2;
    2765                 :             :                     }
    2766                 :             :                 }
    2767                 :             :             }
    2768                 :             :         }
    2769                 :             :     }
    2770                 :             : 
    2771                 :             :     /* compare formulas and H */
    2772                 :           0 :     num_H1 = 0;
    2773                 :           0 :     num_H2 = 0;
    2774                 :           0 :     ret2 = CompareHillFormulasNoH(i1->szHillFormula, i2->szHillFormula, &num_H1, &num_H2);
    2775                 :           0 :     picr->tot_num_H1 = num_H1;
    2776                 :           0 :     picr->tot_num_H2 = num_H2;
    2777         [ #  # ]:           0 :     if (ret2)
    2778                 :             :     {
    2779                 :           0 :         ret |= INCHIDIFF_NUM_EL;
    2780                 :           0 :         goto exit_function;
    2781                 :             :     }
    2782         [ #  # ]:           0 :     if (num_H1 > num_H2)
    2783                 :             :     {
    2784                 :           0 :         ret |= INCHIDIFF_MORE_H;
    2785                 :             :     }
    2786         [ #  # ]:           0 :     if (num_H1 < num_H2)
    2787                 :             :     {
    2788                 :           0 :         ret |= INCHIDIFF_LESS_H;
    2789                 :             :     }
    2790                 :             : 
    2791         [ #  # ]:           0 :     if (i1->lenConnTable != i2->lenConnTable)
    2792                 :             :     {
    2793                 :           0 :         ret |= INCHIDIFF_CON_LEN;
    2794                 :           0 :         goto exit_function;
    2795                 :             :     }
    2796                 :             :     else
    2797                 :             :     {
    2798   [ #  #  #  # ]:           0 :         if (i1->lenConnTable > 0 && memcmp(i1->nConnTable, i2->nConnTable, i1->lenConnTable * sizeof(i1->nConnTable[0])))
    2799                 :             :         {
    2800                 :           0 :             ret |= INCHIDIFF_CON_TBL;
    2801                 :           0 :             goto exit_function;
    2802                 :             :         }
    2803                 :             :     }
    2804                 :             :     /* output special cases: different number of t-groups, different sizes of t-groups, different endpoints */
    2805                 :             :     /* in isotopic or deprotonated cases i1->lenTautomer == 1 && i1->nTautomer[0] = 0 */
    2806                 :             :         /*
    2807                 :             :     if ( i1->lenTautomer != i2->lenTautomer && (i1->lenTautomer > 1 || i2->lenTautomer > 1) )
    2808                 :             :     {
    2809                 :             :         ret |=  INCHIDIFF_TAUT_LEN;
    2810                 :             :     }
    2811                 :             :     */
    2812                 :             : 
    2813                 :             :     /* compare number of t-groups */
    2814         [ #  # ]:           0 :     n1 = i1->lenTautomer ? i1->nTautomer[0] : 0;
    2815         [ #  # ]:           0 :     n2 = i2->lenTautomer ? i2->nTautomer[0] : 0;
    2816   [ #  #  #  # ]:           0 :     if (!n1 && n2)
    2817                 :             :     {
    2818                 :           0 :         ret |= INCHIDIFF_NO_TAUT;
    2819                 :             :     }
    2820                 :             :     else
    2821                 :             :     {
    2822   [ #  #  #  # ]:           0 :         if (n1 && !n2)
    2823                 :             :         {
    2824                 :           0 :             ret |= INCHIDIFF_WRONG_TAUT;
    2825                 :             :         }
    2826                 :             :         else
    2827                 :             :         {
    2828   [ #  #  #  # ]:           0 :             if (n1 == 1 && n2 > 1)
    2829                 :             :             {
    2830                 :           0 :                 ret |= INCHIDIFF_SINGLE_TG;
    2831                 :             :             }
    2832                 :             :             else
    2833                 :             :             {
    2834   [ #  #  #  # ]:           0 :                 if (n1 > 1 && n2 == 1)
    2835                 :             :                 {
    2836                 :           0 :                     ret |= INCHIDIFF_MULTIPLE_TG;
    2837                 :             :                 }
    2838                 :             :                 else
    2839                 :             :                 {
    2840         [ #  # ]:           0 :                     if (n1 != n2)
    2841                 :             :                     {
    2842                 :           0 :                         ret |= INCHIDIFF_NUM_TG;
    2843                 :             :                     }
    2844                 :             :                 }
    2845                 :             :             }
    2846                 :             :         }
    2847                 :             :     }
    2848                 :             : 
    2849   [ #  #  #  # ]:           0 :     if (n1 || n2)
    2850                 :             :     {
    2851                 :             :         /* number of endpoints */
    2852                 :           0 :         int num1 = 0, num2 = 0, num_M1 = 0, num_M2 = 0;
    2853                 :             :         int len, num_eq, num_in1_only, num_in2_only;
    2854                 :           0 :         AT_NUMB* pe1 = (AT_NUMB*)inchi_malloc(((long long)i1->lenTautomer + 1) * sizeof(pe1[0])); /* djb-rwth: cast operator added */
    2855                 :           0 :         AT_NUMB* pe2 = (AT_NUMB*)inchi_malloc(((long long)i2->lenTautomer + 1) * sizeof(pe2[0])); /* djb-rwth: cast operator added */
    2856                 :           0 :         num_H1 = num_H2 = 0;
    2857                 :             :         /* collect endpoints, H, (-) */
    2858   [ #  #  #  # ]:           0 :         if (!pe1 || !pe2)
    2859                 :             :         {
    2860   [ #  #  #  # ]:           0 :             if (pe1) inchi_free(pe1);
    2861   [ #  #  #  # ]:           0 :             if (pe2) inchi_free(pe2);
    2862                 :           0 :             *err = RI_ERR_ALLOC; /* allocation error */
    2863                 :           0 :             goto exit_function;
    2864                 :             :         }
    2865         [ #  # ]:           0 :         for (m = 1; m < i1->lenTautomer; m += len)
    2866                 :             :         {
    2867                 :           0 :             len = i1->nTautomer[m++];
    2868                 :           0 :             num_H1 += i1->nTautomer[m];
    2869                 :           0 :             num_M1 += i1->nTautomer[m + 1];
    2870         [ #  # ]:           0 :             for (j = 2; j < len; j++)
    2871                 :             :             {
    2872                 :           0 :                 pe1[num1++] = i1->nTautomer[m + j];
    2873                 :             :             }
    2874                 :             :         }
    2875         [ #  # ]:           0 :         for (m = 1; m < i2->lenTautomer; m += len)
    2876                 :             :         {
    2877                 :           0 :             len = i2->nTautomer[m++];
    2878                 :           0 :             num_H2 += i2->nTautomer[m];
    2879                 :           0 :             num_M2 += i2->nTautomer[m + 1];
    2880         [ #  # ]:           0 :             for (j = 2; j < len; j++)
    2881                 :             :             {
    2882                 :           0 :                 pe2[num2++] = i2->nTautomer[m + j];
    2883                 :             :             }
    2884                 :             :         }
    2885                 :           0 :         picr->num_taut_H1 = num_H1;
    2886                 :           0 :         picr->num_taut_H2 = num_H2;
    2887                 :           0 :         picr->num_taut_M1 = num_M1;
    2888                 :           0 :         picr->num_taut_M2 = num_M2;
    2889                 :             :         /* sort endpoints */
    2890                 :           0 :         insertions_sort_AT_NUMB(pe1, num1);
    2891                 :           0 :         insertions_sort_AT_NUMB(pe2, num2);
    2892                 :             :         /* compare */
    2893                 :             :         /*
    2894                 :             :         if ( num1 < num2 ) {
    2895                 :             :             ret |= INCHIDIFF_LESS_TG_ENDP;
    2896                 :             :         } else
    2897                 :             :         if ( num1 > num2 ) {
    2898                 :             :             ret |= INCHIDIFF_MORE_TG_ENDP;
    2899                 :             :         }
    2900                 :             :         */
    2901                 :             :         /* compare all */
    2902                 :           0 :         num_eq = num_in1_only = num_in2_only = 0;
    2903   [ #  #  #  # ]:           0 :         for (j1 = j2 = 0; j1 < num1 && j2 < num2; )
    2904                 :             :         {
    2905         [ #  # ]:           0 :             if (pe1[j1] == pe2[j2])
    2906                 :             :             {
    2907                 :           0 :                 j1++;
    2908                 :           0 :                 j2++;
    2909                 :           0 :                 num_eq++;
    2910                 :             :             }
    2911                 :             :             else
    2912                 :             :             {
    2913         [ #  # ]:           0 :                 if (pe1[j1] < pe2[j1])
    2914                 :             :                 {
    2915         [ #  # ]:           0 :                     if (picr->num_endp_in1_only < ICR_MAX_ENDP_IN1_ONLY)
    2916                 :             :                     {
    2917                 :           0 :                         picr->endp_in1_only[picr->num_endp_in1_only++] = pe1[j1];
    2918                 :             :                     }
    2919                 :           0 :                     j1++;
    2920                 :           0 :                     num_in1_only++;
    2921                 :             :                 }
    2922                 :             :                 else
    2923                 :             :                 {
    2924         [ #  # ]:           0 :                     if (picr->num_endp_in2_only < ICR_MAX_ENDP_IN2_ONLY)
    2925                 :             :                     {
    2926                 :           0 :                         picr->endp_in2_only[picr->num_endp_in2_only++] = pe2[j2];
    2927                 :             :                     }
    2928                 :           0 :                     j2++;
    2929                 :           0 :                     num_in2_only++;
    2930                 :             :                 }
    2931                 :             :             }
    2932                 :             :         }
    2933         [ #  # ]:           0 :         while (j1 < num1)
    2934                 :             :         {
    2935         [ #  # ]:           0 :             if (picr->num_endp_in1_only < ICR_MAX_ENDP_IN1_ONLY)
    2936                 :             :             {
    2937                 :           0 :                 picr->endp_in1_only[picr->num_endp_in1_only++] = pe1[j1];
    2938                 :             :             }
    2939                 :           0 :             j1++;
    2940                 :           0 :             num_in1_only++;
    2941                 :             :         }
    2942         [ #  # ]:           0 :         while (j2 < num2)
    2943                 :             :         {
    2944         [ #  # ]:           0 :             if (picr->num_endp_in2_only < ICR_MAX_ENDP_IN2_ONLY)
    2945                 :             :             {
    2946                 :           0 :                 picr->endp_in2_only[picr->num_endp_in2_only++] = pe2[j2];
    2947                 :             :             }
    2948                 :           0 :             j2++;
    2949                 :           0 :             num_in2_only++;
    2950                 :             :         }
    2951         [ #  # ]:           0 :         if (num_in1_only)
    2952                 :             :         {
    2953                 :           0 :             ret |= INCHIDIFF_EXTRA_TG_ENDP;
    2954                 :             :         }
    2955         [ #  # ]:           0 :         if (num_in2_only)
    2956                 :             :         {
    2957                 :           0 :             ret |= INCHIDIFF_MISS_TG_ENDP;
    2958                 :             :         }
    2959   [ #  #  #  #  :           0 :         if (!num_in1_only && !num_in2_only && num_eq)
                   #  # ]
    2960                 :             :         {
    2961                 :             :             ; /* same t-groups endpoints */
    2962                 :             :         }
    2963                 :             :         else
    2964                 :             :         {
    2965                 :           0 :             ret |= INCHIDIFF_DIFF_TG_ENDP;
    2966                 :             :         }
    2967         [ #  # ]:           0 :         inchi_free(pe1);
    2968         [ #  # ]:           0 :         inchi_free(pe2);
    2969                 :             :     }
    2970                 :             : 
    2971   [ #  #  #  # ]:           0 :     if ((i1->lenTautomer > 1 && i2->lenTautomer > 1) &&
    2972         [ #  # ]:           0 :         (i1->lenTautomer != i2->lenTautomer ||
    2973         [ #  # ]:           0 :             memcmp(i1->nTautomer, i2->nTautomer, i1->lenTautomer * sizeof(i1->nTautomer[0]))))
    2974                 :           0 :         ret |= INCHIDIFF_TG;
    2975                 :             : 
    2976         [ #  # ]:           0 :     if (i1->nNumberOfIsotopicAtoms != i2->nNumberOfIsotopicAtoms)
    2977                 :             :     {
    2978                 :           0 :         ret |= INCHIDIFF_NUM_ISO_AT;
    2979                 :             :     }
    2980                 :             :     else
    2981                 :             :     {
    2982   [ #  #  #  # ]:           0 :         if (i1->nNumberOfIsotopicAtoms > 0 && memcmp(i1->IsotopicAtom, i2->IsotopicAtom, i1->nNumberOfIsotopicAtoms * sizeof(i1->IsotopicAtom[0])))
    2983                 :             :         {
    2984                 :           0 :             ret |= INCHIDIFF_ISO_AT;
    2985                 :             :         }
    2986                 :             :     }
    2987         [ #  # ]:           0 :     if (i1->nTotalCharge != i2->nTotalCharge)
    2988                 :           0 :         ret |= INCHIDIFF_CHARGE;
    2989   [ #  #  #  #  :           0 :     if (a1 && a1->nNumRemovedProtons && (!a2 || a2->nNumRemovedProtons != a1->nNumRemovedProtons))
             #  #  #  # ]
    2990                 :             :     {
    2991                 :           0 :         ret |= INCHIDIFF_REM_PROT;
    2992                 :             :     }
    2993   [ #  #  #  # ]:           0 :     if (a1 && (!a2 ||
    2994         [ #  # ]:           0 :         a2->nNumRemovedIsotopicH[0] != a1->nNumRemovedIsotopicH[0] ||
    2995         [ #  # ]:           0 :         a2->nNumRemovedIsotopicH[1] != a1->nNumRemovedIsotopicH[1] ||
    2996         [ #  # ]:           0 :         a2->nNumRemovedIsotopicH[2] != a1->nNumRemovedIsotopicH[2]))
    2997                 :             :     {
    2998                 :           0 :         ret |= INCHIDIFF_REM_ISO_H;
    2999                 :             :     }
    3000                 :             : 
    3001                 :             :     /*
    3002                 :             :     if ( i1->nPossibleLocationsOfIsotopicH && i2->nPossibleLocationsOfIsotopicH ) {
    3003                 :             :         if ( i1->nPossibleLocationsOfIsotopicH[0] != i2->nPossibleLocationsOfIsotopicH[0] ||
    3004                 :             :              memcmp(i1->nPossibleLocationsOfIsotopicH, i2->nPossibleLocationsOfIsotopicH,
    3005                 :             :                     sizeof(i1->nPossibleLocationsOfIsotopicH[0])*i1->nPossibleLocationsOfIsotopicH[0]) )
    3006                 :             :             return 18;
    3007                 :             :     } else
    3008                 :             :     if ( !i1->nPossibleLocationsOfIsotopicH != !i2->nPossibleLocationsOfIsotopicH ) {
    3009                 :             :         return 19;
    3010                 :             :     }
    3011                 :             :     */
    3012         [ #  # ]:           0 :     if (i1->StereoIsotopic &&
    3013         [ #  # ]:           0 :         i1->StereoIsotopic->nNumberOfStereoBonds + i1->StereoIsotopic->nNumberOfStereoCenters)
    3014                 :             :     {
    3015                 :           0 :         Stereo1 = i1->StereoIsotopic;
    3016                 :             :     }
    3017                 :             :     else
    3018                 :             :     {
    3019                 :           0 :         Stereo1 = i1->Stereo;
    3020                 :             :     }
    3021         [ #  # ]:           0 :     if (i2->StereoIsotopic &&
    3022         [ #  # ]:           0 :         i2->StereoIsotopic->nNumberOfStereoBonds + i2->StereoIsotopic->nNumberOfStereoCenters)
    3023                 :             :     {
    3024                 :           0 :         Stereo2 = i2->StereoIsotopic;
    3025                 :             :     }
    3026                 :             :     else
    3027                 :             :     {
    3028                 :           0 :         Stereo2 = i2->Stereo;
    3029                 :             :     }
    3030                 :           0 :     ret |= CompareReversedStereoINChI3(Stereo1, Stereo2, picr);
    3031                 :             : 
    3032                 :           0 : exit_function:
    3033                 :           0 :     picr->flags = ret;
    3034                 :             : 
    3035                 :           0 :     return ret;
    3036                 :             : }
    3037                 :             : 
    3038                 :             : 
    3039                 :             : /* message group names */
    3040                 :             : const CMP_INCHI_MSG_GROUP CompareInchiMsgsGroup[] =
    3041                 :             : {
    3042                 :             :     {IDGRP_ERR,     " Error:"},
    3043                 :             :     {IDGRP_H,       " Hydrogens:"},
    3044                 :             :     {IDGRP_MOB_GRP, " Mobile-H groups:"},
    3045                 :             :     {IDGRP_ISO_AT,  " Isotopic:"},
    3046                 :             :     {IDGRP_CHARGE,  " Charge(s):"},
    3047                 :             :     {IDGRP_PROTONS, " Proton balance:"},
    3048                 :             :     {IDGRP_ISO_H,   " Exchangeable isotopic H:"},
    3049                 :             :     {IDGRP_SC,      " Stereo centers/allenes:"},
    3050                 :             :     {IDGRP_SB,      " Stereobonds/cumulenes:"},
    3051                 :             :     {IDGRP_HLAYER,  " Fixed-H layer:"},
    3052                 :             :     {IDGRP_COMP,    " Number of components:"},
    3053                 :             :     {IDGRP_CONV_ERR," Conversion encountered:"},
    3054                 :             :     {IDGRP_ZERO,    ""}
    3055                 :             : };
    3056                 :             : 
    3057                 :             : 
    3058                 :             : 
    3059                 :             : /* messages */
    3060                 :             : const CMP_INCHI_MSG  CompareInchiMsgs[] =
    3061                 :             : {
    3062                 :             :     {INCHIDIFF_PROBLEM      ,IDGRP_ERR,     " Wrong result"                   }, /*0x00000001,  severe: at least one InChI does not exist */
    3063                 :             :     {INCHIDIFF_POSITION_H   ,IDGRP_H,       " Locations or number"            }, /*0x00000002,  difference in non-taut {Mobile-H} or all H {Fixed-H} location/number */
    3064                 :             :     {INCHIDIFF_MORE_FH      ,IDGRP_H,       " Fixed-H"                        }, /*0x00000004,  extra fixed H */
    3065                 :             :     {INCHIDIFF_LESS_FH      ,IDGRP_H,       " Fixed-H"                        }, /*0x00000004,  missing fixed H */
    3066                 :             :     {INCHIDIFF_MORE_H       ,IDGRP_H,       " Number"                         }, /*0x00000008,  formulas differ in number of H */
    3067                 :             :     {INCHIDIFF_LESS_H       ,IDGRP_H,       " Number"                         }, /*0x00000008,  formulas differ in number of H */
    3068                 :             :     {INCHIDIFF_NO_TAUT      ,IDGRP_MOB_GRP, " Missing"                        }, /*0x00000010,  restored structure has no taut groups while the original InChI has some */
    3069                 :             :     {INCHIDIFF_WRONG_TAUT   ,IDGRP_MOB_GRP, " Falsely present"                }, /*0x00000020,  restored has tautomerism while the original does not have it */
    3070                 :             :     {INCHIDIFF_SINGLE_TG    ,IDGRP_MOB_GRP, " One instead of multiple"        }, /*0x00000040,  restored has 1 taut. group while the original InChI has multiple tg */
    3071                 :             :     {INCHIDIFF_MULTIPLE_TG  ,IDGRP_MOB_GRP, " Multiple instead of one"        }, /*0x00000080,  restored has multiple tg while the original InChI has only one tg */
    3072                 :             :     {INCHIDIFF_EXTRA_TG_ENDP,IDGRP_MOB_GRP, " Attachment points"              }, /*0x00000100,  extra tautomeric endpoint{s} in restored structure */
    3073                 :             :     {INCHIDIFF_MISS_TG_ENDP ,IDGRP_MOB_GRP, " Attachment points"              }, /*0x00000100,  one or more tg endpoint is not in the restored structure */
    3074                 :             :     {INCHIDIFF_DIFF_TG_ENDP ,IDGRP_MOB_GRP, " Attachment points"              }, /*0x00000100,  lists of tg endpoints are different */
    3075                 :             :     {INCHIDIFF_NUM_TG       ,IDGRP_MOB_GRP, " Number"                         }, /*0x00000200,  different number of tautomeric groups */
    3076                 :             :     {INCHIDIFF_TG           ,IDGRP_MOB_GRP, " Do not match"                   }, /*0x00000200,  different tautomeric groups */
    3077                 :             :     {INCHIDIFF_NUM_ISO_AT   ,IDGRP_ISO_AT,  " Atoms do not match"             }, /*0x00000400,  ?severe: restored struct. has different number of isotopic atoms */
    3078                 :             :     {INCHIDIFF_ISO_AT       ,IDGRP_ISO_AT,  " Atoms do not match"             }, /*0x00000400,  ?severe: restored struct. has different locations/isotopes of isotopic atoms */
    3079                 :             :     {INCHIDIFF_REM_ISO_H    ,IDGRP_ISO_H,   " Does not match for a component" }, /*0x00000800,  isotopic H removed */
    3080                 :             :     {INCHIDIFF_MOB_ISO_H    ,IDGRP_ISO_H,   " Do not match"                   }, /*0x00001000,  different number of mobile exchangeable isotopic H */
    3081                 :             :     {INCHIDIFF_CHARGE       ,IDGRP_CHARGE,  " Do not match"                   }, /*0x00002000,  restored structure has different charge */
    3082                 :             :     {INCHIDIFF_REM_PROT     ,IDGRP_PROTONS, " Does not match for a component" }, /*0x00004000,  proton{s} removed/added from the restored structure */
    3083                 :             :     {INCHIDIFF_MOBH_PROTONS ,IDGRP_PROTONS, " Does not match"                 }, /*0x00008000,  different proton balance */
    3084                 :             :     {INCHIDIFF_SC_INV       ,IDGRP_SC,      " Falsely inverted"               }, /*0x00010000,  restores structure has different inversion stereocenter mark */
    3085                 :             :     {INCHIDIFF_SC_PARITY    ,IDGRP_SC,      " Wrong parity"                   }, /*0x00020000,  restored structure has stereoatoms or allenes with different parity */
    3086                 :             :     {INCHIDIFF_SC_EXTRA_UNDF,IDGRP_SC,      " Extra undefined"                }, /*0x00040000,  restored structure has extra undefined stereocenter{s} */
    3087                 :             :     {INCHIDIFF_SC_EXTRA     ,IDGRP_SC,      " Extra known"                    }, /*0x00080000,  restored structure has extra stereocenter{s} */
    3088                 :             :     {INCHIDIFF_SC_MISS_UNDF ,IDGRP_SC,      " Missing undefined"              }, /*0x00100000,  restored structure has not some undefined stereocenter{s} */
    3089                 :             :     {INCHIDIFF_SC_MISS      ,IDGRP_SC,      " Missing known"                  }, /*0x00200000,  restored structure has not some stereocenters that are not undefined */
    3090                 :             :     {INCHIDIFF_SB_PARITY    ,IDGRP_SB,      " Wrong parity"                   }, /*0x00400000,  restored structure has stereobonds or cumulenes with different parity */
    3091                 :             :     {INCHIDIFF_SB_EXTRA_UNDF,IDGRP_SB,      " Extra undefined"                }, /*0x00800000,  restored structure has extra undefined stereobond{s} */
    3092                 :             :     {INCHIDIFF_SB_EXTRA     ,IDGRP_SB,      " Missing known"                  }, /*0x01000000,  restored structure has extra stereobond{s} */
    3093                 :             :     {INCHIDIFF_SB_MISS_UNDF ,IDGRP_SB,      " Missing undefined"              }, /*0x02000000,  restored structure has not some undefined stereocenters */
    3094                 :             :     {INCHIDIFF_SB_MISS      ,IDGRP_SB,      " Missing known"                  }, /*0x04000000,  restored structure has not some stereobonds that are not undefined */
    3095                 :             :     {INCHIDIFF_COMP_HLAYER  ,IDGRP_HLAYER,  " Missing or extra"               }, /*0x08000000,  Restored component has Mobile-H layer instead of both Mobile-H & Fixed-H or both instead of one */
    3096                 :             :     {INCHIDIFF_COMP_NUMBER  ,IDGRP_COMP,    " Does not match"                 }, /*0x10000000,  wrong number of components */
    3097                 :             :     {INCHIDIFF_STR2INCHI_ERR,IDGRP_CONV_ERR," Error"                          },  /*0x20000000   Restored structure to InChI conversion error */
    3098                 :             :     {INCHIDIFF_ZERO         ,IDGRP_ZERO,    ""                                }
    3099                 :             : };
    3100                 :             : 
    3101                 :             : 
    3102                 :             : /*************************************************************************/
    3103                 :           0 : int AddOneMsg(char* szMsg,
    3104                 :             :     int used_len,
    3105                 :             :     int tot_len,
    3106                 :             :     const char* szAddMsg,
    3107                 :             :     const char* szDelim)
    3108                 :             : {
    3109                 :           0 :     const char ellip[] = "...";
    3110                 :           0 :     int len = (int)strlen(szAddMsg);
    3111   [ #  #  #  # ]:           0 :     int len_delim = (used_len && szDelim) ? strlen(szDelim) : 0;
    3112                 :             :     int len_to_copy;
    3113         [ #  # ]:           0 :     if (len + len_delim + used_len < tot_len)
    3114                 :             :     {
    3115         [ #  # ]:           0 :         if (len_delim)
    3116                 :             :         {
    3117                 :           0 :             strcpy(szMsg + used_len, szDelim);
    3118                 :           0 :             used_len += len_delim;
    3119                 :             :         }
    3120                 :           0 :         strcpy(szMsg + used_len, szAddMsg);
    3121                 :           0 :         used_len += len;
    3122                 :             :     }
    3123                 :             :     else
    3124                 :             :     {
    3125         [ #  # ]:           0 :         if ((len_to_copy = (tot_len - used_len - len_delim - (int)sizeof(ellip))) > 10)
    3126                 :             :         {
    3127         [ #  # ]:           0 :             if (len_delim)
    3128                 :             :             {
    3129                 :           0 :                 strcpy(szMsg + used_len, szDelim);
    3130                 :           0 :                 used_len += len_delim;
    3131                 :             :             }
    3132                 :           0 :             strncpy(szMsg + used_len, szAddMsg, len_to_copy);
    3133                 :           0 :             used_len += len_to_copy;
    3134                 :           0 :             strcpy(szMsg + used_len, ellip);
    3135                 :           0 :             used_len += sizeof(ellip) - 1;
    3136                 :             :         }
    3137                 :             :     }
    3138                 :             : 
    3139                 :           0 :     return used_len;
    3140                 :             : }
    3141                 :             : 
    3142                 :             : 
    3143                 :             : /****************************************************************************/
    3144                 :           0 : int FillOutCompareMessage(char* szMsg, int nLenMsg, INCHI_MODE bits[])
    3145                 :             : {
    3146                 :           0 :     int bMobileH, k, n, len = (int)strlen(szMsg);
    3147                 :             :     int iPrevGrpIdx, iCurGrpIdx, bFound;
    3148                 :             :     INCHI_MODE bit;
    3149                 :             :     static const char* hdr = " Problems/mismatches:";
    3150                 :             :     char szOneMsg[256];
    3151                 :             : 
    3152                 :           0 :     int mismatch = 0;
    3153                 :             : 
    3154   [ #  #  #  # ]:           0 :     if (bits[TAUT_YES] || bits[TAUT_NON])
    3155                 :             :     {
    3156                 :             : 
    3157                 :           0 :         mismatch = -1;
    3158                 :             : 
    3159         [ #  # ]:           0 :         if (!strstr(szMsg, hdr))
    3160                 :             :         {
    3161                 :           0 :             len = AddOneMsg(szMsg, len, nLenMsg, hdr, NULL);
    3162                 :             :         }
    3163                 :             : 
    3164         [ #  # ]:           0 :         for (bMobileH = TAUT_YES; 0 <= bMobileH; bMobileH--)
    3165                 :             :         {
    3166                 :             :             /*      bMobileH = TAUT_YES, TAUT_NON */
    3167                 :             : 
    3168         [ #  # ]:           0 :             if (bits[bMobileH])
    3169                 :             :             {
    3170         [ #  # ]:           0 :                 strcpy(szOneMsg, bMobileH == TAUT_YES ? " Mobile-H(" : " Fixed-H(");
    3171                 :           0 :                 len = AddOneMsg(szMsg, len, nLenMsg, szOneMsg, NULL);
    3172                 :             :             }
    3173                 :             : 
    3174                 :           0 :             bit = 1;
    3175                 :           0 :             iPrevGrpIdx = -1;
    3176                 :             : 
    3177                 :             :             do
    3178                 :             :             {
    3179         [ #  # ]:           0 :                 if (bit & bits[bMobileH])
    3180                 :             :                 {
    3181                 :             :                     /* search for the message */
    3182                 :           0 :                     bFound = 0;
    3183   [ #  #  #  # ]:           0 :                     for (k = 0; CompareInchiMsgs[k].nBit != INCHIDIFF_ZERO && !bFound; k++)
    3184                 :             :                     {
    3185         [ #  # ]:           0 :                         if (bit & (INCHI_MODE)CompareInchiMsgs[k].nBit)
    3186                 :             :                         {
    3187                 :             :                             /* message found */
    3188         [ #  # ]:           0 :                             for (n = 0; CompareInchiMsgsGroup[n].nGroupID != IDGRP_ZERO; n++)
    3189                 :             :                             {
    3190         [ #  # ]:           0 :                                 if (CompareInchiMsgsGroup[n].nGroupID == CompareInchiMsgs[k].nGroupID)
    3191                 :             :                                 {
    3192                 :           0 :                                     iCurGrpIdx = n;
    3193         [ #  # ]:           0 :                                     if (iCurGrpIdx != iPrevGrpIdx)
    3194                 :             :                                     {
    3195         [ #  # ]:           0 :                                         if (iPrevGrpIdx >= 0)
    3196                 :             :                                         {
    3197                 :           0 :                                             len = AddOneMsg(szMsg, len, nLenMsg, ";", NULL);
    3198                 :             :                                         }
    3199                 :           0 :                                         len = AddOneMsg(szMsg, len, nLenMsg, CompareInchiMsgsGroup[iCurGrpIdx].szGroupName, NULL);
    3200                 :             :                                     }
    3201         [ #  # ]:           0 :                                     len = AddOneMsg(szMsg, len, nLenMsg, CompareInchiMsgs[k].szMsg, iCurGrpIdx == iPrevGrpIdx ? "," : NULL);
    3202                 :           0 :                                     iPrevGrpIdx = iCurGrpIdx;
    3203                 :           0 :                                     bFound = 1;
    3204                 :           0 :                                     break;
    3205                 :             :                                 }
    3206                 :             :                             }
    3207                 :             :                         }
    3208                 :             :                     }
    3209                 :             :                 }
    3210                 :           0 :                 bit <<= 1;
    3211         [ #  # ]:           0 :             } while (bit);
    3212                 :             : 
    3213         [ #  # ]:           0 :             if (bits[bMobileH])
    3214                 :             :             {
    3215                 :           0 :                 len = AddOneMsg(szMsg, len, nLenMsg, ")", NULL);
    3216                 :             :             }
    3217                 :             : 
    3218                 :             :         }
    3219                 :             :     }
    3220                 :             : 
    3221                 :           0 :     return mismatch; /*len; */
    3222                 :             : }
    3223                 :             : 
    3224                 :             : 
    3225                 :             : #endif
        

Generated by: LCOV version 2.0-1