LCOV - code coverage report
Current view: top level - src - ichirvr7.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 0.0 % 1173 0
Test Date: 2026-05-04 07:05:02 Functions: 0.0 % 17 0
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 0.0 % 1156 0

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

Generated by: LCOV version 2.0-1