LCOV - code coverage report
Current view: top level - src - ichimak2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 57.5 % 645 371
Test Date: 2026-10-14 12:14:55 Functions: 83.3 % 12 10
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 43.7 % 622 272

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <stdlib.h>
       7                 :             : #include <string.h>
       8                 :             : 
       9                 :             : #include "mode.h"
      10                 :             : #include "ichimain.h"
      11                 :             : #include "ichi_io.h"
      12                 :             : 
      13                 :             : #include "bcf_s.h"
      14                 :             : #include "stb_sprintf.h"
      15                 :             : 
      16                 :             : #include "logging.h"                   /*(@nnuk : Nauman Ullah Khan) :: Needed for logging functionality*/
      17                 :             : 
      18                 :             : /* Local */
      19                 :             : 
      20                 :             : int GetHillFormulaCounts( U_CHAR *nAtom,
      21                 :             :                           S_CHAR *nNum_H,
      22                 :             :                           int num_atoms,
      23                 :             :                           AT_NUMB *nTautomer,
      24                 :             :                           int lenTautomer,
      25                 :             :                           int *pnum_C,
      26                 :             :                           int *pnum_H,
      27                 :             :                           int *pnLen,
      28                 :             :                           int *pnNumNonHAtoms );
      29                 :             : int MakeHillFormula( U_CHAR *nAtom,
      30                 :             :                      int num_atoms,
      31                 :             :                      char *szLinearCT,
      32                 :             :                      int nLen_szLinearCT,
      33                 :             :                      int num_C,
      34                 :             :                      int num_H,
      35                 :             :                      int *bOverflow );
      36                 :             : 
      37                 :             : #if ( FIX_DALKE_BUGS == 1 )
      38                 :             : #else
      39                 :             : char *AllocateAndFillHillFormula( INChI *pINChI );
      40                 :             : #endif
      41                 :             : 
      42                 :             : int AddElementAndCount( const char *szElement,
      43                 :             :                         int mult, char *szLinearCT,
      44                 :             :                         int nLenLinearCT,
      45                 :             :                         int *bOverflow );
      46                 :             : 
      47                 :             : int Copy2StereoBondOrAllene( INChI_Stereo *Stereo,
      48                 :             :                              int *nNumberOfStereoCenters,
      49                 :             :                              int *nNumberOfStereoBonds,
      50                 :             :                              AT_STEREO_DBLE *LinearCTStereoDble,
      51                 :             :                              AT_NUMB *pCanonOrd, AT_RANK *pCanonRank,
      52                 :             :                              sp_ATOM *at,
      53                 :             :                              int bIsotopic );
      54                 :             : 
      55                 :             : int CopyLinearCTStereoToINChIStereo( INChI_Stereo *Stereo,
      56                 :             :                                      AT_STEREO_CARB *LinearCTStereoCarb,
      57                 :             :                                      int nLenLinearCTStereoCarb,
      58                 :             :                                      AT_STEREO_DBLE *LinearCTStereoDble,
      59                 :             :                                      int nLenLinearCTStereoDble,
      60                 :             :                                      AT_NUMB *pCanonOrd, AT_RANK *pCanonRank,
      61                 :             :                                      sp_ATOM *at,
      62                 :             :                                      int bIsotopic,
      63                 :             :                                      AT_STEREO_CARB *LinearCTStereoCarbInv,
      64                 :             :                                      AT_STEREO_DBLE *LinearCTStereoDbleInv,
      65                 :             :                                      AT_NUMB *pCanonOrdInv,
      66                 :             :                                      AT_RANK *pCanonRankInv );
      67                 :             : 
      68                 :             : int GetHillFormulaIndexLength( int count );
      69                 :             : 
      70                 :             : int MarkAmbiguousStereo( sp_ATOM *at,
      71                 :             :                          inp_ATOM *norm_at,
      72                 :             :                          int bIsotopic,
      73                 :             :                          AT_NUMB *pCanonOrd,
      74                 :             :                          AT_STEREO_CARB *LinearCTStereoCarb, int nLenLinearCTStereoCarb,
      75                 :             :                          AT_STEREO_DBLE *LinearCTStereoDble, int nLenLinearCTStereoDble );
      76                 :             : 
      77                 :             : INCHI_MODE UnmarkAllUndefinedUnknownStereo( INChI_Stereo *Stereo, INCHI_MODE nUserMode );
      78                 :             : 
      79                 :             : int CleanCoord( MOL_COORD szCoord, int delim );
      80                 :             : 
      81                 :             : 
      82                 :             : 
      83                 :             : /****************************************************************************
      84                 :             :     Print single-component Hill formula whole structure output.
      85                 :             : ****************************************************************************/
      86                 :         146 : int MakeHillFormulaString( char *szHillFormula,
      87                 :             :                            INCHI_IOS_STRING *strbuf,
      88                 :             :                            int *bOverflow )
      89                 :             : {
      90                 :         146 :     int nUsedLength0 = strbuf->nUsedLength;
      91   [ +  -  +  - ]:         146 :     if (szHillFormula && !*bOverflow)
      92                 :             :     {
      93         [ -  + ]:         146 :         if (-1 == inchi_strbuf_printf( strbuf, "%s", szHillFormula ))
      94                 :             :         {
      95                 :           0 :             *bOverflow |= 1;
      96                 :           0 :             return  nUsedLength0 + 1;
      97                 :             :         }
      98                 :             :     }
      99                 :         146 :     return ( strbuf->nUsedLength - nUsedLength0 );
     100                 :             : }
     101                 :             : 
     102                 :             : 
     103                 :             : /****************************************************************************
     104                 :             :     MS Windows dependent: sprintf() is supposed to return the length
     105                 :             :     of the output string.
     106                 :             :     Carbon atoms are always first.
     107                 :             :     Bridging hydrogen atoms are always last.
     108                 :             : ****************************************************************************/
     109                 :         367 : int GetHillFormulaIndexLength( int count )
     110                 :             : {
     111                 :             :     char szCount[16];
     112         [ +  + ]:         367 :     if (count > 1)
     113                 :             :     {
     114                 :         198 :         return sprintf(szCount, "%d", count);
     115                 :             :     }
     116                 :             : 
     117                 :         169 :     return 0;
     118                 :             : }
     119                 :             : 
     120                 :             : 
     121                 :             : /****************************************************************************
     122                 :             :     Estimate dimensions of Hill formula for single component
     123                 :             : ****************************************************************************/
     124                 :         161 : int GetHillFormulaCounts( U_CHAR *nAtom,
     125                 :             :                           S_CHAR *nNum_H,
     126                 :             :                           int num_atoms,
     127                 :             :                           AT_NUMB *nTautomer,
     128                 :             :                           int lenTautomer,
     129                 :             :                           int *pnum_C,
     130                 :             :                           int *pnum_H,
     131                 :             :                           int *pnLen,
     132                 :             :                           int *pnNumNonHAtoms )
     133                 :             : {
     134                 :             :     char szElement[4];
     135                 :         161 :     U_CHAR nPrevAtom = (U_CHAR) -2;
     136                 :             :     int  bCarbon, bHydrogen, nElemLen, nFormLen, nNumNonHAtoms;
     137                 :             :     int  mult, i, num_H, num_C;
     138                 :             : 
     139                 :         161 :     num_H = 0;
     140                 :         161 :     num_C = 0;
     141                 :         161 :     bCarbon = 0;
     142                 :         161 :     bHydrogen = 0;
     143                 :         161 :     nElemLen = 0;
     144                 :         161 :     nFormLen = 0;
     145                 :         161 :     mult = 0;
     146                 :         161 :     nNumNonHAtoms = num_atoms;
     147                 :             : 
     148         [ +  + ]:         971 :     for (i = 0; i < num_atoms; i++)
     149                 :             :     {
     150         [ +  + ]:         810 :         if (nPrevAtom != nAtom[i])
     151                 :             :         {
     152         [ +  + ]:         272 :             if (mult)
     153                 :             :             {
     154         [ -  + ]:         111 :                 if (bHydrogen)
     155                 :             :                 {
     156                 :           0 :                     num_H += mult;
     157                 :             :                 }
     158         [ +  + ]:         111 :                 else if (bCarbon)
     159                 :             :                 {
     160                 :          62 :                     num_C += mult;
     161                 :             :                 }
     162                 :             :                 else
     163                 :             :                 {
     164                 :          49 :                     nFormLen += nElemLen;
     165                 :          49 :                     nFormLen += GetHillFormulaIndexLength( mult );
     166                 :             :                 }
     167                 :             :             }
     168                 :             :             /*if (-1 == get_element_chemical_symbol( (int) nAtom[i], szElement ))*/
     169         [ -  + ]:         272 :             if (-1 == get_element_or_pseudoelement_symbol( (int) nAtom[i], szElement ))
     170                 :             :             {
     171                 :           0 :                 return -1;
     172                 :             :             }
     173                 :         272 :             mult = 1;
     174                 :         272 :             nElemLen = (int) strlen( szElement );
     175                 :         272 :             nPrevAtom = nAtom[i];
     176                 :         272 :             bCarbon = !strcmp( szElement, "C" );
     177                 :         272 :             bHydrogen = !strcmp( szElement, "H" );
     178         [ +  + ]:         272 :             if (bHydrogen)
     179                 :             :             {
     180                 :           6 :                 nNumNonHAtoms = i;
     181                 :             :             }
     182                 :             :         }
     183                 :             :         else
     184                 :             :         {
     185                 :         538 :             mult++;
     186                 :             :         }
     187                 :             : 
     188                 :         810 :         num_H += nNum_H[i];
     189                 :             :     }
     190                 :             : 
     191                 :             :     /* NumGroups; ((NumAt+1, NumH, At1..AtNumAt),...) */
     192                 :             : 
     193   [ +  -  +  + ]:         161 :     if (nTautomer && lenTautomer > 0)
     194                 :             :     {
     195                 :          14 :         int num_groups = nTautomer[0];
     196                 :             : 
     197   [ +  +  +  - ]:          26 :         for (i = 1; i < lenTautomer && num_groups > 0; i += nTautomer[i] + 1, num_groups--)
     198                 :             :         {
     199                 :          12 :             num_H += nTautomer[i + 1];
     200                 :             :         }
     201                 :             :     }
     202                 :             : 
     203         [ +  - ]:         161 :     if (mult)
     204                 :             :     {
     205         [ +  + ]:         161 :         if (bHydrogen)
     206                 :             :         {
     207                 :           6 :             num_H += mult;
     208                 :             :         }
     209         [ +  + ]:         155 :         else if (bCarbon)
     210                 :             :         {
     211                 :          11 :             num_C += mult;
     212                 :             :         }
     213                 :             :         else
     214                 :             :         {
     215                 :         144 :             nFormLen += nElemLen;
     216                 :         144 :             nFormLen += GetHillFormulaIndexLength( mult );
     217                 :             :         }
     218                 :             :     }
     219                 :             : 
     220         [ +  + ]:         161 :     if (num_C)
     221                 :             :     {
     222                 :          73 :         nFormLen += (int) strlen( "C" );
     223                 :          73 :         nFormLen += GetHillFormulaIndexLength( num_C );
     224                 :             :     }
     225                 :             : 
     226         [ +  + ]:         161 :     if (num_H)
     227                 :             :     {
     228                 :         101 :         nFormLen += (int) strlen( "H" );
     229                 :         101 :         nFormLen += GetHillFormulaIndexLength( num_H );
     230                 :             :     }
     231                 :             : 
     232                 :         161 :     *pnum_C = num_C;
     233                 :         161 :     *pnum_H = num_H;
     234                 :         161 :     *pnLen = nFormLen;
     235                 :         161 :     *pnNumNonHAtoms = nNumNonHAtoms;
     236                 :             : 
     237                 :         161 :     return 0;
     238                 :             : }
     239                 :             : 
     240                 :             : 
     241                 :             : /****************************************************************************
     242                 :             :  Add a portion to Hill formula for single component.
     243                 :             : ****************************************************************************/
     244                 :         367 : int AddElementAndCount( const char *szElement, int mult, char *szLinearCT, int nLenLinearCT, int *bOverflow )
     245                 :             : {
     246                 :             :     char szMult[16];
     247                 :             :     int len1, len2;
     248   [ +  -  +  -  :         367 :     if (mult > 0 && !*bOverflow && 0 < ( len1 = strlen( szElement ) ))
                   +  - ]
     249                 :             :     {
     250         [ +  + ]:         367 :         if (mult > 1)
     251                 :             :         {
     252                 :         198 :             len2 = sprintf(szMult, "%d", mult);
     253                 :             :         }
     254                 :             :         else
     255                 :             :         {
     256                 :         169 :             len2 = 0;
     257                 :         169 :             szMult[0] = '\0';
     258                 :             :         }
     259         [ +  - ]:         367 :         if (len1 + len2 < nLenLinearCT)
     260                 :             :         {
     261                 :         367 :             memcpy(szLinearCT, szElement, len1);
     262                 :         367 :             memcpy(szLinearCT + len1, szMult, (long long)len2 + 1); /*  adding zero termination */ /* djb-rwth: added cast operator */
     263                 :         367 :             return len1 + len2;
     264                 :             :         }
     265                 :             :         else
     266                 :             :         {
     267                 :           0 :             ( *bOverflow )++;
     268                 :             :         }
     269                 :             :     }
     270                 :             : 
     271                 :           0 :     return 0;
     272                 :             : }
     273                 :             : 
     274                 :             : 
     275                 :             : /****************************************************************************
     276                 :             :     Make Hill formula for single component.
     277                 :             : 
     278                 :             :     If num_C > 0 then nAtom does not contain C or H
     279                 :             :     otherwise all elements are in alphabetic order
     280                 :             : ****************************************************************************/
     281                 :         161 : int MakeHillFormula( U_CHAR *nAtom,
     282                 :             :                      int num_atoms,
     283                 :             :                      char *szLinearCT,
     284                 :             :                      int nLen_szLinearCT,
     285                 :             :                      int num_C,
     286                 :             :                      int num_H,
     287                 :             :                      int *bOverflow )
     288                 :             : {
     289                 :             :     char szElement[4];
     290                 :             :     int  mult, compare2H;
     291                 :             :     int  i, nLen, bOvfl;
     292                 :             :     U_CHAR nPrevAtom;
     293                 :             : 
     294                 :         161 :     nLen = 0;
     295                 :         161 :     mult = 0;
     296                 :         161 :     bOvfl = 0;
     297                 :         161 :     nPrevAtom = (U_CHAR) -2; /*  non-existent number */
     298                 :         161 :     memset(szElement, '\0', sizeof(szElement)); /* djb-rwth: fixing coverity ID #499542 */
     299                 :             : 
     300         [ +  + ]:         161 :     if (num_C)
     301                 :             :     {
     302                 :          73 :         nLen += AddElementAndCount( "C", num_C, szLinearCT + nLen, nLen_szLinearCT - nLen, &bOvfl );
     303         [ +  - ]:          73 :         if (num_H)
     304                 :             :         {
     305                 :          73 :             nLen += AddElementAndCount( "H", num_H, szLinearCT + nLen, nLen_szLinearCT - nLen, &bOvfl );
     306                 :          73 :             num_H = 0;
     307                 :             :         }
     308                 :             :     }
     309                 :             : 
     310         [ +  + ]:         494 :     for (i = 0; i < num_atoms; i++)
     311                 :             :     {
     312                 :             : 
     313         [ +  + ]:         333 :         if (nPrevAtom != nAtom[i])
     314                 :             :         {
     315         [ +  + ]:         193 :             if (mult)
     316                 :             :             {
     317                 :          46 :                 nLen += AddElementAndCount( szElement, mult, szLinearCT + nLen, nLen_szLinearCT - nLen, &bOvfl );
     318                 :             :             }
     319                 :         193 :             mult = 1;
     320                 :             :             /*if (-1 == get_element_chemical_symbol( (int) nAtom[i], szElement ))*/
     321         [ -  + ]:         193 :             if (-1 == get_element_or_pseudoelement_symbol( (int) nAtom[i], szElement ))
     322                 :             :             {
     323                 :           0 :                 return -1; /*  wrong element */
     324                 :             :             }
     325                 :             : 
     326                 :         193 :             nPrevAtom = nAtom[i];
     327         [ -  + ]:         193 :             if (!strcmp( "C", szElement ))
     328                 :             :             {
     329                 :           0 :                 return -1;
     330                 :             :             }
     331                 :         193 :             compare2H = strcmp( "H", szElement );
     332         [ -  + ]:         193 :             if (!compare2H)
     333                 :             :             {
     334                 :           0 :                 return -1;
     335                 :             :             }
     336   [ +  +  +  + ]:         193 :             if (compare2H < 0 && num_H)
     337                 :             :             {
     338                 :             :                 /*   H-atom should be located in front of szElement */
     339                 :          15 :                 nLen += AddElementAndCount( "H", num_H, szLinearCT + nLen, nLen_szLinearCT - nLen, &bOvfl );
     340                 :          15 :                 num_H = 0;
     341                 :             :             }
     342                 :             :         }
     343                 :             :         else
     344                 :             :         {
     345                 :         140 :             mult++;
     346                 :             :         }
     347                 :             :     }
     348         [ +  + ]:         161 :     if (mult)
     349                 :             :     {
     350                 :             :         /*  the last element if any */
     351                 :         147 :         nLen += AddElementAndCount( szElement, mult, szLinearCT + nLen, nLen_szLinearCT - nLen, &bOvfl );
     352                 :             :     }
     353         [ +  + ]:         161 :     if (num_H)
     354                 :             :     {
     355                 :             :         /*  if H has not been output... */
     356                 :          13 :         nLen += AddElementAndCount( "H", num_H, szLinearCT + nLen, nLen_szLinearCT - nLen, &bOvfl );
     357                 :             :     }
     358                 :         161 :     *bOverflow |= ( 0 != bOvfl );
     359                 :             : 
     360         [ -  + ]:         161 :     return bOvfl ? nLen_szLinearCT + 1 : nLen;
     361                 :             : }
     362                 :             : 
     363                 :             : 
     364                 :             : /****************************************************************************
     365                 :             :     Allocate space and produce Hill formula for single component
     366                 :             : ****************************************************************************/
     367                 :         161 : char *AllocateAndFillHillFormula( INChI *pINChI )
     368                 :             : {
     369                 :             :     int num_C, num_H, nLen, nNumNonHAtoms, ret, bOverflow;
     370                 :         161 :     char *pHillFormula = NULL;
     371                 :             : 
     372                 :         161 :     bOverflow = 0;
     373                 :             : 
     374         [ +  - ]:         161 :     if (!GetHillFormulaCounts( pINChI->nAtom,
     375                 :             :         pINChI->nNum_H,
     376                 :             :         pINChI->nNumberOfAtoms,
     377                 :             :         pINChI->nTautomer,
     378                 :             :         pINChI->lenTautomer,
     379                 :             :         &num_C, &num_H,
     380                 :             :         &nLen,
     381                 :             :         &nNumNonHAtoms ))
     382                 :             :     {
     383                 :             : 
     384                 :             : #if ( FIX_GAF_2019_2==1 )
     385                 :         161 :         pHillFormula = (char*)inchi_calloc((long long )nLen + 1, sizeof(char)); /* djb-rwth: cast operator added */
     386                 :             : #else
     387                 :             :         pHillFormula = (char*)inchi_malloc(nLen + 1);
     388                 :             : #endif
     389                 :             : 
     390         [ +  - ]:         161 :         if (pHillFormula)
     391                 :             :         {
     392                 :             : 
     393                 :         161 :             ret = MakeHillFormula( pINChI->nAtom + num_C,
     394                 :             :                                    nNumNonHAtoms - num_C,
     395                 :             :                                    pHillFormula,
     396                 :             :                                    nLen + 1,
     397                 :             :                                    num_C, num_H,
     398                 :             :                                    &bOverflow );
     399                 :             : 
     400   [ +  -  -  + ]:         161 :             if (ret != nLen || bOverflow)
     401                 :             :             {
     402         [ #  # ]:           0 :                 inchi_free( pHillFormula );
     403                 :           0 :                 pHillFormula = NULL;
     404                 :             :             }
     405                 :             :         }
     406                 :             :     }
     407                 :             : 
     408                 :         161 :     return pHillFormula;
     409                 :             : }
     410                 :             : 
     411                 :             : 
     412                 :             : /************************************************************************************/
     413                 :             : /* Return value: 0 => copied to stereo bonds; 1=> Allene copied to stereocenters    */
     414                 :             : /* on input nNumberOfStereoBonds==NULL means second call, use Stereo->...Inv        */
     415                 :             : /************************************************************************************/
     416                 :           0 : int Copy2StereoBondOrAllene( INChI_Stereo *Stereo,
     417                 :             :                              int *nNumberOfStereoCenters,
     418                 :             :                              int *nNumberOfStereoBonds,
     419                 :             :                              AT_STEREO_DBLE *LinearCTStereoDble,
     420                 :             :                              AT_NUMB *pCanonOrd,
     421                 :             :                              AT_RANK *pCanonRank,
     422                 :             :                              sp_ATOM *at,
     423                 :             :                              int bIsotopic )
     424                 :             : {
     425                 :             :     int cumulene_len,
     426                 :             :         j,
     427                 :           0 :         next_j = 0 /* ordering number of the central allene atom */,
     428                 :             :         next_neigh;
     429                 :             :     AT_RANK
     430                 :             :         at_num;
     431                 :             :     int parity;
     432                 :             : 
     433   [ #  #  #  # ]:           0 :     if (pCanonOrd && pCanonRank)
     434                 :             :     {
     435                 :           0 :         j = pCanonOrd[(int) LinearCTStereoDble->at_num1 - 1];
     436                 :             : 
     437                 :             :         /* if allene then find the central atom, at[next_j] */
     438                 :             : 
     439         [ #  # ]:           0 :         if (bIsotopic)
     440                 :             :         {
     441                 :           0 :             cumulene_len = BOND_CHAIN_LEN( at[j].stereo_bond_parity2[0] );
     442                 :             : 
     443   [ #  #  #  # ]:           0 :             if (cumulene_len % 2 && ( 1 >= MAX_NUM_STEREO_BONDS || !at[j].stereo_bond_neighbor2[1] ))
     444                 :             :             {
     445                 :           0 :                 next_j = at[j].neighbor[(int) at[j].stereo_bond_ord2[0]];
     446                 :             : 
     447   [ #  #  #  # ]:           0 :                 for (cumulene_len = ( cumulene_len - 1 ) / 2; cumulene_len && 2 == at[next_j].valence; cumulene_len--)
     448                 :             :                 {
     449                 :           0 :                     next_neigh = ( j == at[next_j].neighbor[0] );
     450                 :           0 :                     j = next_j;
     451                 :           0 :                     next_j = at[next_j].neighbor[next_neigh];
     452                 :             :                 }
     453                 :             :                 /* next_j is the central atom */
     454                 :             :             }
     455                 :             :             else
     456                 :             :             {
     457                 :           0 :                 cumulene_len = -1; /* not an allene */
     458                 :             :             }
     459                 :             :         }
     460                 :             :         else
     461                 :             :         {
     462                 :           0 :             cumulene_len = BOND_CHAIN_LEN( at[j].stereo_bond_parity[0] );
     463                 :             : 
     464   [ #  #  #  # ]:           0 :             if (cumulene_len % 2 && ( 1 >= MAX_NUM_STEREO_BONDS || !at[j].stereo_bond_neighbor[1] ))
     465                 :             :             {
     466                 :           0 :                 next_j = at[j].neighbor[(int) at[j].stereo_bond_ord[0]];
     467                 :             : 
     468   [ #  #  #  # ]:           0 :                 for (cumulene_len = ( cumulene_len - 1 ) / 2; cumulene_len && 2 == at[next_j].valence; cumulene_len--)
     469                 :             :                 {
     470                 :           0 :                     next_neigh = ( j == at[next_j].neighbor[0] );
     471                 :           0 :                     j = next_j;
     472                 :           0 :                     next_j = at[next_j].neighbor[next_neigh];
     473                 :             :                 }
     474                 :             :             }
     475                 :             :             else
     476                 :             :             {
     477                 :           0 :                 cumulene_len = -1; /* not an allene */
     478                 :             :             }
     479                 :             :         }
     480                 :             : 
     481         [ #  # ]:           0 :         if (!cumulene_len)
     482                 :             :         {
     483                 :             :             /* allene has been found; insert new stereocenter and parity */
     484                 :             : 
     485                 :             :             AT_NUMB *nNumber;
     486                 :             :             S_CHAR  *t_parity;
     487                 :             : 
     488         [ #  # ]:           0 :             nNumber = nNumberOfStereoBonds ? Stereo->nNumber : Stereo->nNumberInv;
     489         [ #  # ]:           0 :             t_parity = nNumberOfStereoBonds ? Stereo->t_parity : Stereo->t_parityInv;
     490                 :             : 
     491                 :           0 :             at_num = pCanonRank[next_j];
     492                 :           0 :             parity = LinearCTStereoDble->parity;
     493                 :             : 
     494                 :             :             /* free room for the new stereocenter */
     495   [ #  #  #  # ]:           0 :             for (j = 0; j < *nNumberOfStereoCenters && Stereo->nNumber[j] < at_num; j++)
     496                 :             :             {
     497                 :             :                 ;
     498                 :             :             }
     499                 :             : 
     500         [ #  # ]:           0 :             if (j < *nNumberOfStereoCenters)
     501                 :             :             {
     502                 :           0 :                 memmove(nNumber + j + 1, nNumber + j, (*nNumberOfStereoCenters - (long long)j) * sizeof(nNumber[0])); /* djb-rwth: cast operator added */
     503                 :           0 :                 memmove(t_parity + j + 1, t_parity + j, (*nNumberOfStereoCenters - (long long)j) * sizeof(t_parity[0])); /* djb-rwth: cast operator added */
     504                 :             :             }
     505                 :             : 
     506                 :             :             /* fill the new stereo center info */
     507                 :             : 
     508                 :           0 :             nNumber[j] = at_num;
     509                 :           0 :             t_parity[j] = parity;
     510                 :           0 :             ( *nNumberOfStereoCenters )++;
     511                 :           0 :             return 1;
     512                 :             :         }
     513                 :             :     }
     514                 :             : 
     515                 :             :     /* Save the stereo bond info */
     516                 :             : 
     517         [ #  # ]:           0 :     if (nNumberOfStereoBonds)
     518                 :             :     {
     519                 :           0 :         j = *nNumberOfStereoBonds;
     520                 :           0 :         Stereo->b_parity[j] = LinearCTStereoDble->parity;
     521                 :           0 :         Stereo->nBondAtom1[j] = LinearCTStereoDble->at_num1;
     522                 :           0 :         Stereo->nBondAtom2[j] = LinearCTStereoDble->at_num2;
     523                 :           0 :         ( *nNumberOfStereoBonds )++;
     524                 :             :     }
     525                 :             : 
     526                 :           0 :     return 0;
     527                 :             : }
     528                 :             : 
     529                 :             : 
     530                 :             : /***************************************************************************/
     531                 :          55 : int CopyLinearCTStereoToINChIStereo( INChI_Stereo *Stereo,
     532                 :             :                                      AT_STEREO_CARB *LinearCTStereoCarb,
     533                 :             :                                      int nLenLinearCTStereoCarb,
     534                 :             :                                      AT_STEREO_DBLE *LinearCTStereoDble,
     535                 :             :                                      int nLenLinearCTStereoDble,
     536                 :             :                                      AT_NUMB *pCanonOrd, AT_RANK *pCanonRank,
     537                 :             :                                      sp_ATOM *at,
     538                 :             :                                      int bIsotopic,
     539                 :             :                                      AT_STEREO_CARB *LinearCTStereoCarbInv,
     540                 :             :                                      AT_STEREO_DBLE *LinearCTStereoDbleInv,
     541                 :             :                                      AT_NUMB *pCanonOrdInv, AT_RANK *pCanonRankInv )
     542                 :             : {
     543                 :          55 :     int n, i, nErrorCode = 0, len;
     544                 :             :     int bAllene;
     545                 :             :     int diff;
     546                 :             :     int lenInv, bAlleneInv;
     547                 :             : 
     548                 :             :     /* Stereo centers */
     549                 :             : 
     550                 :             :     /* djb-rwth: fixing oss-fuzz issue #68271 */
     551         [ +  - ]:          55 :     if (Stereo)
     552                 :             :     {
     553                 :          55 :         n = Stereo->nNumberOfStereoCenters = nLenLinearCTStereoCarb;
     554                 :             : 
     555         [ +  + ]:         242 :         for (i = 0; i < n; i++)
     556                 :             :         {
     557         [ +  - ]:         187 :             if (LinearCTStereoCarb) /* djb-rwth: fixing a NULL pointer dereference */
     558                 :             :             {
     559                 :         187 :                 Stereo->nNumber[i] = LinearCTStereoCarb[i].at_num;
     560                 :         187 :                 Stereo->t_parity[i] = LinearCTStereoCarb[i].parity;
     561                 :             :             }
     562         [ +  - ]:         187 :             if (LinearCTStereoCarbInv) /* djb-rwth: fixing a NULL pointer dereference */
     563                 :             :             {
     564                 :         187 :                 Stereo->nNumberInv[i] = LinearCTStereoCarbInv[i].at_num;
     565                 :         187 :                 Stereo->t_parityInv[i] = LinearCTStereoCarbInv[i].parity;
     566                 :             :             }
     567                 :             :         }
     568                 :             : 
     569                 :             :         /* Stereo bonds */
     570                 :             : 
     571                 :          55 :         n = nLenLinearCTStereoDble;
     572                 :          55 :         lenInv = Stereo->nNumberOfStereoCenters;
     573                 :             : 
     574         [ -  + ]:          55 :         for (i = len = 0; i < n; i++)
     575                 :             :         {
     576                 :             :             bAllene =
     577                 :           0 :                 Copy2StereoBondOrAllene(Stereo,
     578                 :             :                     &Stereo->nNumberOfStereoCenters,
     579                 :             :                     &len,
     580                 :           0 :                     LinearCTStereoDble + i,
     581                 :             :                     pCanonOrd, pCanonRank,
     582                 :             :                     at,
     583                 :             :                     bIsotopic);
     584                 :             : 
     585                 :             :             bAlleneInv =
     586                 :           0 :                 Copy2StereoBondOrAllene(Stereo,
     587                 :             :                     &lenInv,
     588                 :             :                     NULL,
     589                 :           0 :                     LinearCTStereoDbleInv + i,
     590                 :             :                     pCanonOrdInv, pCanonRankInv,
     591                 :             :                     at,
     592                 :             :                     bIsotopic);
     593                 :             : 
     594                 :             :             /* make sure double bond stereo is identical in original and inverted geometry */
     595                 :             :             /* Note: all allenes are AFTER double bonds in LinearCTStereoDble... */
     596   [ #  #  #  #  :           0 :             if (bAllene != bAlleneInv || (!bAllene &&
                   #  # ]
     597                 :           0 :                 CompareLinCtStereoDble(LinearCTStereoDble + i, 1,
     598                 :           0 :                     LinearCTStereoDbleInv + i, 1))) /* djb-rwth: addressing LLVM warning */
     599                 :             :             {
     600                 :             :                 /* double bond stereo Inv is NOT identical to Abs */
     601                 :           0 :                 nErrorCode = -4;
     602                 :           0 :                 goto exit_function;
     603                 :             :             }
     604                 :             :         }
     605                 :             : 
     606                 :          55 :         Stereo->nNumberOfStereoBonds = len;
     607                 :             : 
     608         [ -  + ]:          55 :         if (lenInv != Stereo->nNumberOfStereoCenters)
     609                 :             :         {
     610                 :           0 :             nErrorCode = -5; /* different number of stereo centers in Abs and Inv */
     611                 :           0 :             goto exit_function;
     612                 :             :         }
     613                 :             : 
     614                 :             : 
     615                 :             :         /* compare inverted stereocenters to absolute */
     616                 :             : 
     617                 :          55 :         n = Stereo->nNumberOfStereoCenters;
     618                 :             :         /* djb-rwth: removing redundant code */
     619                 :             : 
     620         [ +  + ]:          64 :         for (i = 0, diff = 0; i < n; i++)
     621                 :             :         {
     622         [ -  + ]:          60 :             if (Stereo->nNumberInv[i] != Stereo->nNumber[i])
     623                 :             :             {
     624         [ #  # ]:           0 :                 diff = (Stereo->nNumberInv[i] > Stereo->nNumber[i]) ? 2 : -2;
     625                 :           0 :                 break; /* Abs != Inv */
     626                 :             :             }
     627         [ +  + ]:          60 :             if (Stereo->t_parityInv[i] != Stereo->t_parity[i])
     628                 :             :             {
     629         [ +  + ]:          51 :                 diff = (Stereo->t_parityInv[i] > Stereo->t_parity[i]) ? 1 : -1;
     630                 :          51 :                 break; /* Abs != Inv */
     631                 :             :             }
     632                 :             :         }
     633                 :             : 
     634                 :          55 :         Stereo->nCompInv2Abs =
     635   [ +  +  +  + ]:          55 :             (diff > 0) ? 1 : (diff < 0) ? -1 : 0;
     636                 :             : 
     637   [ +  +  +  + ]:          55 :         if (diff == -1 || diff == 1)
     638                 :             :         {
     639                 :             :             /* The first found difference was in parities */
     640         [ +  + ]:         216 :             for (i = 0, diff = 0; i < n; i++)
     641                 :             :             {
     642         [ -  + ]:         174 :                 if (Stereo->nNumberInv[i] != Stereo->nNumber[i])
     643                 :             :                 {
     644                 :           0 :                     diff = 2; /* difference in stereo center numbering */
     645                 :           0 :                     break;
     646                 :             :                 }
     647                 :             : 
     648                 :             :                 /*  Parities can be only 1, 2, 3, 4. Therefore only mutually inverted pairs
     649                 :             :                  *  (t_parityInv, t_parity) = (1,2) or (2,1) statisfy conditions
     650                 :             :                  *  (t_parityInv != t_parity) && (t_parityInv + t_parity == 3)
     651                 :             :                  */
     652                 :             : 
     653         [ +  + ]:         174 :                 if (Stereo->t_parityInv[i] == Stereo->t_parity[i] ||
     654         [ -  + ]:         165 :                     Stereo->t_parityInv[i] + Stereo->t_parity[i] != 3)
     655                 :             :                 {
     656                 :           9 :                     diff = 1; /* parities are same or different and cannot be obtained by simple inversion */
     657                 :           9 :                     break;
     658                 :             :                 }
     659                 :             :             }
     660                 :          51 :             Stereo->bTrivialInv = !diff;
     661                 :             :         }
     662                 :             :         else
     663                 :             :         {
     664                 :           4 :             Stereo->bTrivialInv = 0;
     665                 :             :         }
     666                 :             :     }
     667                 :             :     else
     668                 :             :     {
     669                 :           0 :         nErrorCode = 1;
     670                 :             :     }
     671                 :             : 
     672                 :          55 : exit_function:
     673                 :          55 :     return nErrorCode;
     674                 :             : }
     675                 :             : 
     676                 :             : 
     677                 :             : /****************************************************************************/
     678                 :         161 : int MarkAmbiguousStereo( sp_ATOM *at,
     679                 :             :                          inp_ATOM *norm_at,
     680                 :             :                          int bIsotopic,
     681                 :             :                          AT_NUMB *pCanonOrd,
     682                 :             :                          AT_STEREO_CARB *LinearCTStereoCarb,
     683                 :             :                          int nLenLinearCTStereoCarb,
     684                 :             :                          AT_STEREO_DBLE *LinearCTStereoDble,
     685                 :             :                          int nLenLinearCTStereoDble )
     686                 :             : {
     687                 :             :     int n, i, j1, j2, num, mark_atom, mark_bond;
     688                 :             : 
     689         [ -  + ]:         161 :     if (!pCanonOrd)
     690                 :             :     {
     691                 :           0 :         return -1;
     692                 :             :     }
     693                 :             : 
     694                 :         161 :     num = 0;
     695                 :             : 
     696                 :         161 :     n = nLenLinearCTStereoCarb;
     697                 :             : 
     698         [ -  + ]:         161 :     mark_atom = bIsotopic ? AMBIGUOUS_STEREO_ATOM_ISO : AMBIGUOUS_STEREO_ATOM;
     699                 :             : 
     700         [ +  + ]:         348 :     for (i = 0; i < n; i++)
     701                 :             :     {
     702                 :             :         /*  Mark ambiguous stereo centers (for displaying and "Ambiguous stereo" message) */
     703   [ +  -  +  -  :         187 :         if (ATOM_PARITY_NOT_UNKN( LinearCTStereoCarb[i].parity ) &&
                   +  - ]
     704         [ -  + ]:         187 :              at[j1 = pCanonOrd[(int) LinearCTStereoCarb[i].at_num - 1]].bAmbiguousStereo)
     705                 :             :         {
     706                 :           0 :             at[j1].bAmbiguousStereo |= mark_atom;
     707                 :           0 :             norm_at[j1].bAmbiguousStereo |= mark_atom;
     708                 :           0 :             num++;
     709                 :             :         }
     710                 :             :     }
     711                 :             : 
     712                 :         161 :     n = nLenLinearCTStereoDble;
     713                 :             : 
     714         [ -  + ]:         161 :     mark_bond = bIsotopic ? AMBIGUOUS_STEREO_BOND_ISO : AMBIGUOUS_STEREO_BOND;
     715                 :             : 
     716         [ -  + ]:         161 :     for (i = 0; i < n; i++)
     717                 :             :     {
     718                 :             :         /*  Mark ambiguous stereo bonds or allenes (for displaying and "Ambiguous stereo" message) */
     719                 :             : 
     720   [ #  #  #  # ]:           0 :         if (ATOM_PARITY_WELL_DEF( LinearCTStereoDble[i].parity ))
     721                 :             :         {
     722                 :           0 :             j1 = pCanonOrd[(int) LinearCTStereoDble[i].at_num1 - 1];
     723                 :           0 :             j2 = pCanonOrd[(int) LinearCTStereoDble[i].at_num2 - 1];
     724                 :             : 
     725   [ #  #  #  # ]:           0 :             if (at[j1].bAmbiguousStereo || at[j2].bAmbiguousStereo)
     726                 :             :             {
     727                 :             :                 /* If it is an allene then mark the central atom only
     728                 :             :                    because the bonds should not be marked to avoid misleading
     729                 :             :                    message "Ambiguous stereo: bond(s)": Allene makes a stereocenter
     730                 :             :                 */
     731                 :             : 
     732         [ #  # ]:           0 :                 int j1_parity = bIsotopic ? at[j1].stereo_bond_parity2[0] : at[j1].stereo_bond_parity[0];
     733                 :             : 
     734                 :           0 :                 int cumulene_len = BOND_CHAIN_LEN( j1_parity ); /* 0 => double bond, 1 => allene, 2 => cumulene,..*/
     735                 :             : 
     736   [ #  #  #  #  :           0 :                 if (cumulene_len % 2 && ( 1 >= MAX_NUM_STEREO_BONDS ||
                   #  # ]
     737                 :           0 :                     !( bIsotopic ? at[j1].stereo_bond_neighbor2[1] : at[j1].stereo_bond_neighbor[1] ) )
     738                 :             :                     )
     739                 :             :                 {
     740                 :             :                     /*  found an allene; locate its central atom */
     741                 :             : 
     742                 :             :                     int next_j, next_neigh;
     743                 :           0 :                     int j = j1;
     744                 :             : 
     745         [ #  # ]:           0 :                     next_j = at[j].neighbor[bIsotopic ? at[j].stereo_bond_ord2[0] : at[j].stereo_bond_ord[0]];
     746                 :             : 
     747                 :           0 :                     for (cumulene_len = ( cumulene_len - 1 ) / 2;
     748   [ #  #  #  # ]:           0 :                          cumulene_len && 2 == at[next_j].valence;
     749                 :           0 :                          cumulene_len--)
     750                 :             :                     {
     751                 :           0 :                         next_neigh = ( j == at[next_j].neighbor[0] );
     752                 :           0 :                         j = next_j;
     753                 :           0 :                         next_j = at[next_j].neighbor[next_neigh];
     754                 :             :                     }
     755                 :             :                     /* next_j is the central atom */
     756         [ #  # ]:           0 :                     if (2 == at[next_j].valence)
     757                 :             :                     {
     758                 :           0 :                         at[next_j].bAmbiguousStereo |= mark_atom;
     759                 :           0 :                         norm_at[next_j].bAmbiguousStereo |= mark_atom;
     760                 :           0 :                         num++;
     761                 :           0 :                         continue; /* do not mark the cumulene "bond" endpoints */
     762                 :             :                     }
     763                 :             :                 }
     764                 :             : 
     765                 :             :                 /* Not an allene, mark double bond or cumulene end atoms */
     766         [ #  # ]:           0 :                 if (at[j1].bAmbiguousStereo)
     767                 :             :                 {
     768                 :           0 :                     at[j1].bAmbiguousStereo |= mark_bond; /*  ??? */
     769                 :           0 :                     norm_at[j1].bAmbiguousStereo |= mark_bond;
     770                 :           0 :                     num++;
     771                 :             :                 }
     772                 :             : 
     773         [ #  # ]:           0 :                 if (at[j2].bAmbiguousStereo)
     774                 :             :                 {
     775                 :           0 :                     at[j2].bAmbiguousStereo |= mark_bond; /*  ??? */
     776                 :           0 :                     norm_at[j2].bAmbiguousStereo |= mark_bond;
     777                 :           0 :                     num++;
     778                 :             :                 }
     779                 :             :             }
     780                 :             :         }
     781                 :             :     }
     782                 :             : 
     783                 :         161 :     return num;
     784                 :             : }
     785                 :             : 
     786                 :             : 
     787                 :             : /****************************************************************************/
     788                 :         161 : INCHI_MODE UnmarkAllUndefinedUnknownStereo( INChI_Stereo *Stereo,
     789                 :             :                                             INCHI_MODE nUserMode )
     790                 :             : {
     791                 :         161 :     INCHI_MODE nRet = 0;
     792                 :             :     int   i, n;
     793                 :             : 
     794   [ +  -  +  -  :         161 :     if (!Stereo || (Stereo && !Stereo->nNumberOfStereoCenters && !Stereo->nNumberOfStereoBonds)) /* djb-rwth: addressing LLVM warning */
             +  +  +  - ]
     795                 :             :     {
     796                 :         106 :         return nRet;
     797                 :             :     }
     798                 :             : 
     799                 :             :     /* Stereocenters */
     800         [ +  + ]:          55 :     if (!Stereo->nCompInv2Abs &&
     801   [ +  -  +  - ]:           4 :         ( n = Stereo->nNumberOfStereoCenters ) > 0 && ( nUserMode & REQ_MODE_SC_IGN_ALL_UU ))
     802                 :             :     {
     803                 :             : 
     804   [ +  +  -  +  :          11 :         for (i = 0; i < n && !ATOM_PARITY_WELL_DEF( Stereo->t_parity[i] ); i++)
                   +  - ]
     805                 :             :         {
     806                 :             :             ;
     807                 :             :         }
     808                 :             : 
     809         [ +  - ]:           4 :         if (i == n)
     810                 :             :         {
     811                 :           4 :             Stereo->nNumberOfStereoCenters = 0;
     812                 :             : 
     813         [ +  + ]:          11 :             for (i = 0; i < n; i++)
     814                 :             :             {
     815                 :           7 :                 Stereo->t_parity[i] = 0;
     816                 :           7 :                 Stereo->nNumber[i] = 0;
     817                 :           7 :                 Stereo->t_parityInv[i] = 0;
     818                 :           7 :                 Stereo->nNumberInv[i] = 0;
     819                 :             :             }
     820                 :             : 
     821                 :           4 :             nRet |= REQ_MODE_SC_IGN_ALL_UU;
     822                 :             :         }
     823                 :             :     }
     824                 :             : 
     825                 :             :     /* Stereobonds */
     826                 :             : 
     827   [ -  +  -  - ]:          55 :     if (( n = Stereo->nNumberOfStereoBonds ) > 0 && ( nUserMode & REQ_MODE_SB_IGN_ALL_UU ))
     828                 :             :     {
     829   [ #  #  #  #  :           0 :         for (i = 0; i < n && !ATOM_PARITY_WELL_DEF( Stereo->b_parity[i] ); i++)
                   #  # ]
     830                 :             :         {
     831                 :             :             ;
     832                 :             :         }
     833                 :             : 
     834         [ #  # ]:           0 :         if (i == n)
     835                 :             :         {
     836                 :           0 :             Stereo->nNumberOfStereoBonds = 0;
     837         [ #  # ]:           0 :             for (i = 0; i < n; i++)
     838                 :             :             {
     839                 :           0 :                 Stereo->b_parity[i] = 0;
     840                 :           0 :                 Stereo->nBondAtom1[i] = 0;
     841                 :           0 :                 Stereo->nBondAtom2[i] = 0;
     842                 :             :             }
     843                 :           0 :             nRet |= REQ_MODE_SB_IGN_ALL_UU;
     844                 :             :         }
     845                 :             :     }
     846                 :             : 
     847                 :          55 :     return nRet;
     848                 :             : }
     849                 :             : 
     850                 :             : 
     851                 :             : #if ( defined(TARGET_API_LIB) )
     852                 :             : 
     853                 :             : 
     854                 :             : /****************************************************************************/
     855                 :           0 : void WriteCoord( char *str, double x )
     856                 :             : {
     857         [ #  # ]:           0 :     if (x < -9999999.9)
     858                 :             :     {
     859                 :             : #ifdef GHI100_FIX
     860                 :             : #if (SPRINTF_FLAG == 2)
     861                 :             :         dbl2int(str, 10, 2, 'e', x);
     862                 :             : #elif (SPRINTF_FLAG == 1)
     863                 :             :         stbsp_sprintf(str, "%10.2e", x);
     864                 :             : #else
     865                 :             :         sprintf(str, "%10.2e", x);
     866                 :             : #endif
     867                 :             : #endif
     868                 :           0 :         sprintf(str, "%10.2e", x);
     869                 :             :     }
     870                 :             :     else
     871                 :             :     {
     872         [ #  # ]:           0 :         if (x < -999999.99)
     873                 :             :         {
     874                 :             : #ifdef GHI100_FIX
     875                 :             : #if (SPRINTF_FLAG == 2)
     876                 :             :             dbl2int(str, 10, 2, 'f', x);
     877                 :             : #elif (SPRINTF_FLAG == 1)
     878                 :             :             stbsp_sprintf(str, "%10.2f", x);
     879                 :             : #else
     880                 :             :             sprintf( str, "%10.2f", x );
     881                 :             : #endif
     882                 :             : #endif
     883                 :           0 :             sprintf( str, "%10.2f", x );
     884                 :             :         }
     885                 :             :         else
     886                 :             :         {
     887         [ #  # ]:           0 :             if (x < -99999.999)
     888                 :             :             {
     889                 :             : #ifdef GHI100_FIX
     890                 :             : #if (SPRINTF_FLAG == 2)
     891                 :             :                 dbl2int(str, 10, 3, 'f', x);
     892                 :             : #elif (SPRINTF_FLAG == 1)
     893                 :             :                 stbsp_sprintf(str, "%10.3f", x);
     894                 :             : #else
     895                 :             :                 sprintf( str, "%10.3f", x );
     896                 :             : #endif
     897                 :             : #endif
     898                 :           0 :                 sprintf( str, "%10.3f", x );
     899                 :             :             }
     900                 :             :             else
     901                 :             :             {
     902         [ #  # ]:           0 :                 if (x < 99999.9999)
     903                 :             :                 {
     904                 :             : #ifdef GHI100_FIX
     905                 :             : #if (SPRINTF_FLAG == 2)
     906                 :             :                     dbl2int(str, 10, 4, 'f', x);
     907                 :             : #elif (SPRINTF_FLAG == 1)
     908                 :             :                     stbsp_sprintf(str, "%10.4f", x);
     909                 :             : #else
     910                 :             :                     sprintf( str, "%10.4f", x );
     911                 :             : #endif
     912                 :             : #endif
     913                 :           0 :                     sprintf( str, "%10.4f", x );
     914                 :             :                 }
     915                 :             :                 else
     916                 :             :                 {
     917         [ #  # ]:           0 :                     if (x < 999999.999)
     918                 :             :                     {
     919                 :             : #ifdef GHI100_FIX
     920                 :             : #if (SPRINTF_FLAG == 2)
     921                 :             :                         dbl2int(str, 10, 3, 'f', x);
     922                 :             : #elif (SPRINTF_FLAG == 1)
     923                 :             :                         stbsp_sprintf(str, "%10.3f", x);
     924                 :             : #else
     925                 :             :                         sprintf( str, "%10.3f", x );
     926                 :             : #endif
     927                 :             : #endif
     928                 :           0 :                         sprintf( str, "%10.3f", x );
     929                 :             :                     }
     930                 :             :                     else
     931                 :             :                     {
     932         [ #  # ]:           0 :                         if (x < 9999999.99)
     933                 :             :                         {
     934                 :             : #ifdef GHI100_FIX
     935                 :             : #if (SPRINTF_FLAG == 2)
     936                 :             :                             dbl2int(str, 10, 2, 'f', x);
     937                 :             : #elif (SPRINTF_FLAG == 1)
     938                 :             :                             stbsp_sprintf(str, "%10.2f", x);
     939                 :             : #else
     940                 :             :                             sprintf( str, "%10.2f", x );
     941                 :             : #endif
     942                 :             : #endif
     943                 :           0 :                             sprintf( str, "%10.2f", x );
     944                 :             :                         }
     945                 :             :                         else
     946                 :             :                         {
     947         [ #  # ]:           0 :                             if (x < 99999999.9)
     948                 :             :                             {
     949                 :             : #ifdef GHI100_FIX
     950                 :             : #if (SPRINTF_FLAG == 2)
     951                 :             :                                 dbl2int(str, 10, 1, 'f', x);
     952                 :             : #elif (SPRINTF_FLAG == 1)
     953                 :             :                                 stbsp_sprintf(str, "%10.1f", x);
     954                 :             : #else
     955                 :             :                                 sprintf( str, "%10.1f", x );
     956                 :             : #endif
     957                 :             : #endif
     958                 :           0 :                                 sprintf( str, "%10.1f", x );
     959                 :             :                             }
     960                 :             :                             else
     961                 :             :                             {
     962                 :             : #ifdef GHI100_FIX
     963                 :             : #if (SPRINTF_FLAG == 2)
     964                 :             :                                 dbl2int(str, 10, 3, 'e', x);
     965                 :             : #elif (SPRINTF_FLAG == 1)
     966                 :             :                                 stbsp_sprintf(str, "%10.3e", x);
     967                 :             : #else
     968                 :             :                                 sprintf( str, "%10.3e", x );
     969                 :             : #endif
     970                 :             : #endif
     971                 :           0 :                                 sprintf( str, "%10.3e", x );
     972                 :             :                             }
     973                 :             :                         }
     974                 :             :                     }
     975                 :             :                 }
     976                 :             :             }
     977                 :             :         }
     978                 :             :     }
     979                 :           0 : }
     980                 :             : #endif
     981                 :             : 
     982                 :             : 
     983                 :             : 
     984                 :             : /* used CANON_STAT members
     985                 :             : 
     986                 :             :     pCS->LinearCT
     987                 :             :     pCS->LinearCTIsotopic
     988                 :             :     pCS->LinearCTIsotopicStereoCarb
     989                 :             :     pCS->LinearCTIsotopicStereoCarbInv
     990                 :             :     pCS->LinearCTIsotopicStereoDble
     991                 :             :     pCS->LinearCTIsotopicStereoDbleInv
     992                 :             :     pCS->LinearCTIsotopicTautomer
     993                 :             :     pCS->LinearCTStereoCarb
     994                 :             :     pCS->LinearCTStereoCarbInv
     995                 :             :     pCS->LinearCTStereoDble
     996                 :             :     pCS->LinearCTStereoDbleInv
     997                 :             :     pCS->nCanonOrd
     998                 :             :     pCS->nCanonOrdIsotopic
     999                 :             :     pCS->nCanonOrdIsotopicStereo
    1000                 :             :     pCS->nCanonOrdIsotopicStereoInv
    1001                 :             :     pCS->nCanonOrdIsotopicStereoTaut
    1002                 :             :     pCS->nCanonOrdIsotopicTaut
    1003                 :             :     pCS->nCanonOrdStereo
    1004                 :             :     pCS->nCanonOrdStereoInv
    1005                 :             :     pCS->nCanonOrdStereoTaut
    1006                 :             :     pCS->nCanonOrdTaut
    1007                 :             :     pCS->nLenCanonOrd
    1008                 :             :     pCS->nLenCanonOrdIsotopic
    1009                 :             :     pCS->nLenCanonOrdIsotopicStereo
    1010                 :             :     pCS->nLenCanonOrdIsotopicStereoTaut
    1011                 :             :     pCS->nLenCanonOrdIsotopicTaut
    1012                 :             :     pCS->nLenCanonOrdStereo
    1013                 :             :     pCS->nLenCanonOrdStereoTaut
    1014                 :             :     pCS->nLenCanonOrdTaut
    1015                 :             :     pCS->nLenLinearCTAtOnly
    1016                 :             :     pCS->nLenLinearCTIsotopic
    1017                 :             :     pCS->nLenLinearCTIsotopicStereoCarb
    1018                 :             :     pCS->nLenLinearCTIsotopicStereoDble
    1019                 :             :     pCS->nLenLinearCTIsotopicTautomer
    1020                 :             :     pCS->nLenLinearCTStereoCarb
    1021                 :             :     pCS->nLenLinearCTStereoDble
    1022                 :             :     pCS->nNum_H
    1023                 :             :     pCS->nNum_H_fixed
    1024                 :             :     pCS->nSymmRank
    1025                 :             :     pCS->nSymmRankIsotopic
    1026                 :             :     pCS->nSymmRankIsotopicTaut
    1027                 :             :     pCS->nSymmRankTaut
    1028                 :             :     pCS->t_group_info
    1029                 :             :     pCS->t_group_info->num_t_groups
    1030                 :             : 
    1031                 :             : */
    1032                 :             : 
    1033                 :             : 
    1034                 :             : /****************************************************************************
    1035                 :             :     Serialization: one-component InChI
    1036                 :             : ****************************************************************************/
    1037                 :         161 : int FillOutINChI( INChI *pINChI,
    1038                 :             :                   INChI_Aux *pINChI_Aux,
    1039                 :             :                   int num_atoms,
    1040                 :             :                   int num_at_tg,
    1041                 :             :                   int num_removed_H,
    1042                 :             :                   sp_ATOM *at,
    1043                 :             :                   inp_ATOM *norm_at,
    1044                 :             :                   CANON_STAT *pCS,
    1045                 :             :                   CANON_GLOBALS *pCG,
    1046                 :             :                   int bTautomeric,
    1047                 :             :                   INCHI_MODE nUserMode,
    1048                 :             :                   char *pStrErrStruct,
    1049                 :             :                   int bNoWarnings )
    1050                 :             : {
    1051                 :         161 :     int i, j, m, n, g, len, ii, ret = 0;
    1052                 :             : 
    1053                 :         161 :     AT_NUMB   *pSymmRank, *pOrigNosInCanonOrd, *pConstitEquNumb, *pCanonOrd = NULL, *pCanonOrdInv = NULL, *pCanonOrdTaut;
    1054                 :         161 :     T_GROUP_INFO     *t_group_info = pCS->t_group_info;
    1055                 :             :     T_GROUP *t_group;
    1056                 :             : 
    1057                 :         161 :     int nErrorCode = 0;
    1058                 :             :     AT_NUMB *pCanonRank, *pCanonRankInv; /* canonical ranks of the atoms or tautomeric groups */
    1059                 :         161 :     AT_NUMB *pCanonRankAtoms = NULL, *pSortOrd = NULL;
    1060                 :             :     AT_RANK nMinOrd;
    1061                 :             : 
    1062                 :             :     INChI_Stereo *Stereo;
    1063                 :         161 :     int          bUseNumberingInv = 0, bUseIsotopicNumberingInv = 0;
    1064                 :             : 
    1065                 :             :     INCHI_MODE    nStereoUnmarkMode;
    1066                 :             : 
    1067                 :             :     /*AT_NUMB  *pCanonOrdNonIso = NULL, *pCanonOrdIso = NULL;*/
    1068                 :             :     /*AT_NUMB  *nOrigAtNosInCanonOrdNonIso = NULL, *nOrigAtNosInCanonOrdIso = NULL;*/
    1069                 :             : 
    1070                 :             : 
    1071                 :             :     /*  Check for warnings */
    1072   [ +  -  +  - ]:         161 :     if (pCS->nLenLinearCTStereoCarb < 0 || pCS->nLenLinearCTStereoDble < 0 ||
    1073   [ +  -  -  + ]:         161 :          pCS->nLenCanonOrdStereo < 0 || pCS->nLenCanonOrdStereoTaut < 0)
    1074                 :             :     {
    1075                 :           0 :         nErrorCode |= WARN_FAILED_STEREO;
    1076                 :             :     }
    1077   [ +  -  +  - ]:         161 :     if (pCS->nLenLinearCTIsotopic < 0 || pCS->nLenLinearCTIsotopicTautomer < 0 ||
    1078   [ +  -  -  + ]:         161 :          pCS->nLenCanonOrdIsotopic < 0 || pCS->nLenCanonOrdIsotopicTaut < 0)
    1079                 :             :     {
    1080                 :           0 :         nErrorCode |= WARN_FAILED_ISOTOPIC;
    1081                 :             :     }
    1082   [ +  -  +  - ]:         161 :     if (pCS->nLenLinearCTIsotopicStereoCarb < 0 || pCS->nLenLinearCTIsotopicStereoDble < 0 ||
    1083   [ +  -  -  + ]:         161 :          pCS->nLenCanonOrdIsotopicStereo < 0 || pCS->nLenCanonOrdIsotopicStereoTaut < 0)
    1084                 :             :     {
    1085                 :           0 :         nErrorCode |= WARN_FAILED_ISOTOPIC_STEREO;
    1086                 :             :     }
    1087                 :             : 
    1088                 :         161 :     pCanonRankAtoms = (AT_NUMB *) inchi_calloc( (long long)num_at_tg + 1, sizeof( pCanonRankAtoms[0] ) ); /* djb-rwth: cast operator added */
    1089                 :             : 
    1090                 :         161 :     pSortOrd = (AT_NUMB *) inchi_calloc( (long long)num_at_tg + 1, sizeof( pSortOrd[0] ) ); /*  must have more than num_atoms */ /* djb-rwth: cast operator added */
    1091                 :             : 
    1092   [ +  -  -  + ]:         161 :     if (!pCanonRankAtoms || !pSortOrd)
    1093                 :             :     {
    1094                 :           0 :         nErrorCode = 0;
    1095                 :           0 :         ret = CT_OUT_OF_RAM;  /*   <BRKPT> */
    1096                 :           0 :         pINChI->nErrorCode = pINChI_Aux->nErrorCode = CT_OUT_OF_RAM;
    1097                 :           0 :         goto exit_function;
    1098                 :             :     }
    1099                 :             : 
    1100                 :             :     /*  Total charge */
    1101                 :             :     /* djb-rwth: fixing oss-fuzz issue #69656 */
    1102         [ +  + ]:         971 :     for (i = 0, n = 0; i < num_atoms + num_removed_H; i++)
    1103                 :             :     {
    1104                 :         810 :         n += at[i].charge;
    1105                 :             :     }
    1106                 :         161 :     pINChI->nTotalCharge = n;
    1107                 :             : 
    1108                 :             :     /*  Number of atoms */
    1109                 :         161 :     pINChI->nNumberOfAtoms = num_atoms;
    1110                 :         161 :     pINChI_Aux->nNumberOfAtoms = num_atoms;
    1111                 :             : 
    1112                 :             :     /* Removed protons and detachable isotopic H */
    1113   [ +  -  +  - ]:         161 :     if (bTautomeric && t_group_info)
    1114                 :             :     {
    1115                 :         161 :         pINChI_Aux->nNumRemovedProtons = t_group_info->tni.nNumRemovedProtons;
    1116                 :             : 
    1117         [ +  + ]:         644 :         for (i = 0; i < NUM_H_ISOTOPES; i++)
    1118                 :             :         {
    1119                 :         483 :             pINChI_Aux->nNumRemovedIsotopicH[i] = t_group_info->num_iso_H[i]
    1120                 :         483 :                 + t_group_info->tni.nNumRemovedProtonsIsotopic[i];
    1121                 :             :         }
    1122                 :             : 
    1123         [ -  + ]:         161 :         if (pINChI_Aux->bNormalizationFlags & FLAG_FORCE_SALT_TAUT)
    1124                 :             :         {
    1125                 :           0 :             pINChI->nFlags |= INCHI_FLAG_HARD_ADD_REM_PROTON;
    1126                 :             :         }
    1127         [ +  + ]:         161 :         if (pINChI_Aux->bNormalizationFlags & ( FLAG_NORM_CONSIDER_TAUT &~FLAG_PROTON_CHARGE_CANCEL ))
    1128                 :             :         {
    1129         [ +  - ]:          14 :             if (!bNoWarnings)
    1130                 :             :             {
    1131                 :          14 :                 WarningMessage( pStrErrStruct, "Proton(s) added/removed" );
    1132                 :             :             }
    1133                 :             :         }
    1134         [ -  + ]:         161 :         if (pINChI_Aux->bNormalizationFlags & FLAG_PROTON_CHARGE_CANCEL)
    1135                 :             :         {
    1136         [ #  # ]:           0 :             if (!bNoWarnings)
    1137                 :             :             {
    1138                 :           0 :                 WarningMessage( pStrErrStruct, "Charges neutralized" );
    1139                 :             :             }
    1140                 :             :         }
    1141                 :             :     }
    1142                 :             : 
    1143                 :             :     /* Abs or rel stereo may establish one of two canonical numberings */
    1144   [ +  +  -  + ]:         161 :     if (( pCS->nLenLinearCTStereoCarb > 0 || pCS->nLenLinearCTStereoDble > 0 ) &&
    1145         [ +  - ]:          55 :           pCS->nLenCanonOrdStereo > 0 &&
    1146   [ +  -  -  + ]:          55 :           ( (pCS->LinearCTStereoCarb && pCS->LinearCTStereoCarbInv) ||
    1147   [ #  #  #  # ]:           0 :               (pCS->LinearCTStereoDble && pCS->LinearCTStereoDbleInv) ) &&
    1148   [ +  -  +  - ]:          55 :           pCS->nCanonOrdStereo && pCS->nCanonOrdStereoInv
    1149                 :             :        ) /* djb-rwth: addressing LLVM warning */
    1150                 :             :     {
    1151                 :          55 :         pCanonRank = pCanonRankAtoms;
    1152                 :          55 :         pCanonOrd = pCS->nCanonOrdStereo;
    1153                 :          55 :         pCanonRankInv = pSortOrd;
    1154                 :          55 :         pCanonOrdInv = pCS->nCanonOrdStereoInv;
    1155                 :          55 :         Stereo = pINChI->Stereo;
    1156                 :             : 
    1157         [ +  + ]:         611 :         for (i = 0; i < num_at_tg; i++)
    1158                 :             :         {
    1159                 :         556 :             pCanonRankInv[pCanonOrdInv[i]] =
    1160                 :         556 :                 pCanonRank[pCanonOrd[i]] = (AT_NUMB) ( i + 1 );
    1161                 :             :         }
    1162                 :             : 
    1163                 :             :         /********************************************************************/
    1164                 :             :         /* Copy stereo bonds and stereo centers; compare Inv and Abs stereo */
    1165                 :             :         /********************************************************************/
    1166                 :             : 
    1167                 :          55 :         nErrorCode = CopyLinearCTStereoToINChIStereo( Stereo,
    1168                 :             :                                                       pCS->LinearCTStereoCarb,
    1169                 :             :                                                       pCS->nLenLinearCTStereoCarb,
    1170                 :             :                                                       pCS->LinearCTStereoDble,
    1171                 :             :                                                       pCS->nLenLinearCTStereoDble,
    1172                 :             :                                                       pCanonOrd, pCanonRank,
    1173                 :             :                                                       at, 0 /* non-isotopic */,
    1174                 :             :                                                       pCS->LinearCTStereoCarbInv,
    1175                 :             :                                                       pCS->LinearCTStereoDbleInv,
    1176                 :             :                                                       pCanonOrdInv, pCanonRankInv );
    1177                 :             : 
    1178                 :             :         /* djb-rwth: fixing oss-fuzz issue #68271 */
    1179         [ -  + ]:          55 :         if (nErrorCode == 1)
    1180                 :             :         {
    1181                 :           0 :             nErrorCode = 0;
    1182                 :           0 :             ret = CT_OUT_OF_RAM;  /*   <BRKPT> */
    1183                 :           0 :             pINChI->nErrorCode = pINChI_Aux->nErrorCode = CT_OUT_OF_RAM;
    1184                 :           0 :             goto exit_function;
    1185                 :             :         }
    1186                 :             : 
    1187   [ +  -  +  - ]:          55 :         if (Stereo->t_parityInv && Stereo->nNumberInv)
    1188                 :             :         {
    1189         [ -  + ]:          55 :             if (nUserMode & REQ_MODE_RELATIVE_STEREO)
    1190                 :             :             {
    1191                 :           0 :                 pINChI->nFlags |= INCHI_FLAG_REL_STEREO;
    1192                 :             :             }
    1193         [ -  + ]:          55 :             if (nUserMode & REQ_MODE_RACEMIC_STEREO)
    1194                 :             :             {
    1195                 :           0 :                 pINChI->nFlags |= INCHI_FLAG_RAC_STEREO;
    1196                 :             :             }
    1197         [ +  + ]:          55 :             if (Stereo->nCompInv2Abs)
    1198                 :             :             {
    1199         [ +  + ]:          51 :                 if (Stereo->nCompInv2Abs == -1)
    1200                 :             :                 {
    1201                 :             :                     /* switch pointers in Stereo so that the stereo becomes the smallest (relative)  */
    1202                 :             :                     /* flag Stereo->nCompInv2Abs == -1 will keep track of this exchange */
    1203                 :          19 :                     AT_NUMB    *nNumberInv = Stereo->nNumberInv;
    1204                 :          19 :                     S_CHAR     *t_parityInv = Stereo->t_parityInv;
    1205                 :          19 :                     Stereo->nNumberInv = Stereo->nNumber;
    1206                 :          19 :                     Stereo->t_parityInv = Stereo->t_parity;
    1207                 :          19 :                     Stereo->nNumber = nNumberInv;
    1208                 :          19 :                     Stereo->t_parity = t_parityInv;
    1209                 :             :                     /* switch pointers to set rel. stereo to pINChI_Aux->nOrigAtNosInCanonOrd
    1210                 :             :                                        and inv. stereo to pINChI_Aux->nOrigAtNosInCanonOrdInv */
    1211                 :          19 :                     switch_ptrs( &pCanonRank, &pCanonRankInv );
    1212                 :          19 :                     switch_ptrs( &pCanonOrd, &pCanonOrdInv );
    1213                 :          19 :                     bUseNumberingInv = 1; /* use inverted stereo numbering instead of normal */
    1214                 :             :                 }
    1215                 :             :             }
    1216                 :             :         }
    1217                 :             : 
    1218                 :             :         LOG_NO_ARGS("************************** Canonical Ordering with Stereo (L1183:ichimak2.c) ***************************\n");
    1219         [ +  + ]:         611 :         for (i = 0; i < num_atoms; i++)
    1220                 :             :         {
    1221                 :         556 :             pINChI_Aux->nOrigAtNosInCanonOrdInv[i] = at[pCanonOrdInv[i]].orig_at_number;
    1222                 :         556 :             pINChI_Aux->nOrigAtNosInCanonOrd[i] = at[pCanonOrd[i]].orig_at_number;
    1223                 :             :             LOG_MULT_ARGS("Atom Nr: %d, Canonical Numbering Normal: %d, Element Name: %s\n", i + 1, at[pCanonOrd[i]].orig_at_number, at[i].elname);
    1224                 :             :         }
    1225                 :             : 
    1226                 :             :         LOG_NO_ARGS("\n******************************************************************************************************\n");
    1227                 :             : 
    1228         [ +  + ]:          55 :         if (bUseNumberingInv)
    1229                 :             :         {
    1230                 :             :             /* switch ptrs back to avoid confusion */
    1231                 :          19 :             switch_ptrs( &pCanonRank, &pCanonRankInv );
    1232                 :          19 :             switch_ptrs( &pCanonOrd, &pCanonOrdInv );
    1233                 :             :             /* save inverted stereo ranks & order because it represents the smallest (relative) */
    1234                 :          19 :             memcpy(pCanonRank, pCanonRankInv, num_at_tg * sizeof(pCanonRank[0]));
    1235                 :             :             /* change pCS->nCanonOrdStereo[] to inverted: */
    1236                 :          19 :             memcpy(pCanonOrd, pCanonOrdInv, num_at_tg * sizeof(pCanonOrd[0]));
    1237                 :             :         }
    1238                 :             : 
    1239                 :          55 :         pCanonRankInv = NULL;
    1240                 :          55 :         pCanonOrdInv = NULL;
    1241                 :          55 :         pOrigNosInCanonOrd = NULL;
    1242                 :             :     }
    1243                 :             :     else
    1244                 :             :     {
    1245                 :             :         /*------------------------------ no stereo */
    1246                 :         212 :         pCanonOrd = pCS->nLenCanonOrdStereo > 0 ? pCS->nCanonOrdStereo
    1247   [ +  +  +  - ]:         106 :                                                 : pCS->nLenCanonOrd > 0  ? pCS->nCanonOrd
    1248                 :             :                                                                          : NULL;
    1249                 :         106 :         pCanonRank = pCanonRankAtoms;
    1250                 :         106 :         pOrigNosInCanonOrd = pINChI_Aux->nOrigAtNosInCanonOrd;
    1251                 :             : 
    1252   [ +  -  +  - ]:         106 :         if (pCanonOrd && pCanonRank)
    1253                 :             :         {
    1254         [ +  + ]:         360 :             for (i = 0; i < num_atoms; i++)
    1255                 :             :             {
    1256                 :         254 :                 pCanonRank[pCanonOrd[i]] = (AT_NUMB) ( i + 1 );
    1257                 :         254 :                 pOrigNosInCanonOrd[i] = at[pCanonOrd[i]].orig_at_number;
    1258                 :             :             }
    1259         [ +  + ]:         118 :             for (; i < num_at_tg; i++)
    1260                 :             :             {
    1261                 :          12 :                 pCanonRank[pCanonOrd[i]] = (AT_NUMB) ( i + 1 );
    1262                 :             :             }
    1263                 :             :         }
    1264                 :             :     }
    1265                 :             :     /*pCanonOrdNonIso = pCanonOrd;*/  /* save for aux info */
    1266                 :             : 
    1267                 :             : 
    1268         [ +  - ]:         161 :     if (pINChI_Aux->OrigInfo)
    1269                 :             :     {
    1270                 :             :         /* charges, radicals, valences */
    1271         [ +  + ]:         971 :         for (i = 0; i < num_atoms; i++)
    1272                 :             :         {
    1273         [ +  - ]:         810 :             if (pCanonOrd) /* djb-rwth: fixing a NULL pointer dereference */
    1274                 :             :             {
    1275                 :         810 :                 ii = pCanonOrd[i]; 
    1276   [ +  +  +  + ]:         810 :                 if (norm_at[ii].valence || norm_at[ii].num_H)
    1277                 :             :                 {
    1278                 :         750 :                     pINChI_Aux->OrigInfo[i].cCharge = norm_at[ii].charge;
    1279                 :             : 
    1280         [ +  - ]:        1500 :                     pINChI_Aux->OrigInfo[i].cRadical = (norm_at[ii].radical == RADICAL_SINGLET) ? 0 :
    1281         [ +  - ]:         750 :                         (norm_at[ii].radical == RADICAL_DOUBLET) ? 1 :
    1282         [ +  - ]:         750 :                         (norm_at[ii].radical == RADICAL_TRIPLET) ? 2 :
    1283         [ -  + ]:         750 :                         norm_at[ii].radical ? 3 : 0;
    1284                 :             : 
    1285                 :         750 :                     pINChI_Aux->OrigInfo[i].cUnusualValence =
    1286                 :         750 :                         get_unusual_el_valence(norm_at[ii].el_number, norm_at[ii].charge, norm_at[ii].radical,
    1287                 :         750 :                             norm_at[ii].chem_bonds_valence, norm_at[ii].num_H, norm_at[ii].valence);
    1288                 :             :                 }
    1289                 :             :                 else
    1290                 :             :                 {
    1291                 :             :                     /* charge of a single atom component is in the INChI; valence = 0 is standard */
    1292         [ +  - ]:         120 :                     pINChI_Aux->OrigInfo[i].cRadical = (norm_at[ii].radical == RADICAL_SINGLET) ? 0 :
    1293         [ +  - ]:          60 :                         (norm_at[ii].radical == RADICAL_DOUBLET) ? 1 :
    1294         [ +  - ]:          60 :                         (norm_at[ii].radical == RADICAL_TRIPLET) ? 2 :
    1295         [ -  + ]:          60 :                         norm_at[ii].radical ? 3 : 0;
    1296                 :             :                 }
    1297                 :             :             }
    1298                 :             :         }
    1299                 :             :     }
    1300                 :             : 
    1301                 :             :     /* Non-isotopic canonical numbers and equivalence of atoms (Aux) */
    1302                 :         161 :     pConstitEquNumb = pINChI_Aux->nConstitEquNumbers;  /*  contitutional equivalence */
    1303                 :         161 :     pSymmRank = pCS->nSymmRank;
    1304                 :             : 
    1305   [ +  -  +  -  :         161 :     if (pCanonOrd && pCanonRank && pSymmRank && pConstitEquNumb)
             +  -  +  - ]
    1306                 :             :     {
    1307         [ +  + ]:         971 :         for (i = 0; i < num_atoms; i++)
    1308                 :             :         {
    1309                 :         810 :             pConstitEquNumb[i] = pSymmRank[pCanonOrd[i]]; /*  constit. equ. ranks in order of canonical numbers */
    1310                 :         810 :             pSortOrd[i] = i;
    1311                 :             :         }
    1312         [ +  + ]:         173 :         for (; i < num_at_tg; i++)
    1313                 :             :         {
    1314                 :          12 :             pSortOrd[i] = MAX_ATOMS; /* for debugging only */
    1315                 :             :         }
    1316                 :             : 
    1317                 :         161 :         pCG->m_pn_RankForSort = pConstitEquNumb;
    1318                 :         161 :         inchi_qsort( pCG, pSortOrd, num_atoms, sizeof( pSortOrd[0] ), CompRanksOrd );
    1319                 :             : 
    1320         [ +  + ]:         971 :         for (i = 0, nMinOrd = pSortOrd[0], j = 1; j <= num_atoms; j++)
    1321                 :             :         {
    1322   [ +  +  +  + ]:         810 :             if (j == num_atoms || pConstitEquNumb[pSortOrd[i]] != pConstitEquNumb[pSortOrd[j]])
    1323                 :             :             {
    1324                 :         711 :                 nMinOrd++;
    1325         [ +  + ]:         711 :                 if (j - i > 1)
    1326                 :             :                 {
    1327                 :             :                     /*  found a sequence of equivalent atoms: i..j-1 */
    1328         [ +  + ]:         235 :                     while (i < j)
    1329                 :             :                     {
    1330                 :         167 :                         pConstitEquNumb[pSortOrd[i++]] = nMinOrd; /*  = min. canon. rank in the group of equ. atoms */
    1331                 :             :                     }
    1332                 :             :                     /*  at this point j == i */
    1333                 :             :                 }
    1334                 :             :                 else
    1335                 :             :                 {
    1336                 :         643 :                     pConstitEquNumb[pSortOrd[i++]] = 0; /*  means the atom is not equivalent to any other */
    1337                 :             :                 }
    1338                 :         711 :                 nMinOrd = pSortOrd[j]; /*  at the end j = num_atoms */
    1339                 :             :             }
    1340                 :             :         }
    1341                 :             :     }
    1342                 :             : 
    1343                 :             :     else
    1344                 :             :     {
    1345                 :           0 :         nErrorCode |= ERR_NO_CANON_RESULTS;
    1346                 :           0 :         ret = -1;  /*  program error; no breakpoint here */
    1347                 :           0 :         goto exit_function;
    1348                 :             :     }
    1349                 :             : 
    1350                 :             : 
    1351                 :             :     /*  Atomic numbers from the Periodic Table */
    1352         [ +  + ]:         971 :     for (i = 0; i < num_atoms; i++)
    1353                 :             :     {
    1354                 :         810 :         pINChI->nAtom[i] = (int) at[pCanonOrd[i]].el_number;
    1355                 :             :     }
    1356                 :             : 
    1357                 :             : 
    1358                 :             :     /*  Connection table: atoms only (before 7-29-2003 pCS->LinearCT2 contained non-isotopic CT) */
    1359   [ +  -  +  -  :         161 :     if (pCS->nLenLinearCTAtOnly <= 0 || !pCS->LinearCT || !pINChI->nConnTable)
                   -  + ]
    1360                 :             :     {
    1361                 :           0 :         nErrorCode |= ERR_NO_CANON_RESULTS;
    1362                 :           0 :         ret = -2;
    1363                 :           0 :         goto exit_function;
    1364                 :             :     }
    1365                 :             : 
    1366                 :         161 :     memcpy(pINChI->nConnTable, pCS->LinearCT, sizeof(pINChI->nConnTable[0]) * pCS->nLenLinearCTAtOnly);
    1367                 :             : 
    1368                 :         161 :     pINChI->lenConnTable = pCS->nLenLinearCTAtOnly;
    1369                 :             : 
    1370                 :             :     /*  Tautomeric group(s) canonical representation */
    1371                 :         161 :     len = 0;
    1372   [ +  -  +  + ]:         161 :     if (bTautomeric && 0 < ( n = SortTautomerGroupsAndEndpoints(
    1373                 :             :         pCG, t_group_info,
    1374                 :             :         num_atoms, num_at_tg, pCanonRank ) ))
    1375                 :             :     {
    1376                 :             :         /* SortTautomerGroupsAndEndpoints() produces canonically ordered t-groups */
    1377                 :          14 :         pINChI->nFlags |=
    1378                 :           7 :             ( t_group_info->bTautFlagsDone & TG_FLAG_ALL_SALT_DONE ) ? INCHI_FLAG_ACID_TAUT
    1379         [ -  + ]:           7 :             : 0;
    1380                 :             : 
    1381                 :             :         /*  number of tautomeric groups */
    1382                 :           7 :         pINChI->nTautomer[len++] = (AT_NUMB) n;
    1383                 :             : 
    1384                 :             :         /* store each tautomeric group, one by one */
    1385         [ +  + ]:          19 :         for (i = 0; i < n; i++)
    1386                 :             :         {
    1387                 :          12 :             g = (int) t_group_info->tGroupNumber[i]; /* original group numbers in sorted order */
    1388                 :          12 :             t_group = t_group_info->t_group + g;    /* pointer to the tautomeric group */
    1389                 :             : 
    1390                 :             :             /*  NumAt+INCHI_T_NUM_MOVABLE (group length excluding this number) */
    1391                 :             : 
    1392                 :          12 :             pINChI->nTautomer[len++] = t_group->nNumEndpoints + INCHI_T_NUM_MOVABLE;
    1393                 :             : 
    1394                 :             :             /*  Num(H), Num(-) */
    1395                 :             : 
    1396         [ +  + ]:          36 :             for (j = 0; j < INCHI_T_NUM_MOVABLE; j++) /* djb-rwth: redundant condition; && j < T_NUM_NO_ISOTOPIC part should be checked; can INCHI_T_NUM_MOVABLE and T_NUM_NO_ISOTOPIC change values from 2? */
    1397                 :             :             {
    1398                 :          24 :                 pINChI->nTautomer[len++] = t_group->num[j];
    1399                 :             :             }
    1400                 :             :             
    1401                 :             :             
    1402                 :             :             /* djb-rwth: erroneous loop execution condition
    1403                 :             :             
    1404                 :             :             for (j = T_NUM_NO_ISOTOPIC; j < INCHI_T_NUM_MOVABLE; j++)
    1405                 :             :             {
    1406                 :             :                 pINChI->nTautomer[len++] = 0; // should not happen 
    1407                 :             :             }
    1408                 :             :             
    1409                 :             :             */
    1410                 :             : 
    1411                 :             :             /* tautomeric group endpoint canonical numbers, pre-sorted in ascending order */
    1412                 :             : 
    1413                 :          12 :             for (j = (int) t_group->nFirstEndpointAtNoPos,
    1414         [ +  + ]:          40 :                   m = j + (int) t_group->nNumEndpoints; j < m; j++)
    1415                 :             :             {
    1416                 :          28 :                 pINChI->nTautomer[len++] = pCanonRank[(int) t_group_info->nEndpointAtomNumber[j]]; /*  At[j] */
    1417                 :             :             }
    1418                 :             :         }
    1419                 :             : 
    1420                 :           7 :         pINChI->lenTautomer = len;
    1421                 :           7 :         pINChI_Aux->nNumberOfTGroups = n;
    1422                 :             :     }
    1423                 :             :     else
    1424                 :             :     {
    1425                 :         154 :         pINChI->lenTautomer = 0;
    1426                 :         154 :         pINChI_Aux->nNumberOfTGroups = 0;
    1427                 :             : 
    1428   [ +  -  +  + ]:         154 :         if (t_group_info && ( ( t_group_info->tni.bNormalizationFlags & FLAG_NORM_CONSIDER_TAUT ) ||
    1429         [ -  + ]:         147 :             (t_group_info->nNumIsotopicEndpoints > 1 &&
    1430         [ #  # ]:           0 :             ( t_group_info->bTautFlagsDone & ( TG_FLAG_FOUND_ISOTOPIC_H_DONE | TG_FLAG_FOUND_ISOTOPIC_ATOM_DONE ) )) )
    1431                 :             :            ) /* djb-rwth: addressing LLVM warning */
    1432                 :             :         {
    1433                 :             :             /* only protons (re)moved or added */
    1434                 :           7 :             pINChI->lenTautomer = 1;
    1435                 :           7 :             pINChI->nTautomer[0] = 0;
    1436                 :             :         }
    1437                 :             :     }
    1438                 :             : 
    1439                 :             :     /*  Number of H (excluding tautomeric) */
    1440         [ +  - ]:         161 :     if (pCS->nNum_H)
    1441                 :             :     {
    1442         [ +  + ]:         971 :         for (i = 0; i < num_atoms; i++)
    1443                 :             :         {
    1444                 :         810 :             pINChI->nNum_H[i] = pCS->nNum_H[i];
    1445                 :             :         }
    1446                 :             :     }
    1447                 :             : 
    1448                 :             : 
    1449                 :             :     /*  Number of fixed H (tautomeric H in non-tautomeric representation) */
    1450   [ +  -  +  + ]:         161 :     if (pCS->nNum_H_fixed && !pINChI->lenTautomer)
    1451                 :             :     {
    1452         [ +  + ]:         906 :         for (i = 0; i < num_atoms; i++)
    1453                 :             :         {
    1454                 :         759 :             pINChI->nNum_H_fixed[i] = pCS->nNum_H_fixed[i];
    1455                 :         759 :             pINChI->nNum_H[i] += pCS->nNum_H_fixed[i];
    1456                 :             :         }
    1457                 :             :     }
    1458                 :             : 
    1459                 :             : 
    1460                 :             :     /***********************************************************
    1461                 :             :      *  Tautomeric group(s) numbering and symmetry;
    1462                 :             :      *  should not depend on switching to rel. stereo numbering
    1463                 :             :      */
    1464   [ +  +  +  + ]:         161 :     if (pINChI->lenTautomer && ( n = pINChI_Aux->nNumberOfTGroups ))
    1465                 :             :     {
    1466         [ +  + ]:          12 :         pCanonOrdTaut = pCS->nLenCanonOrdStereoTaut > 0 ? pCS->nCanonOrdStereoTaut :
    1467         [ +  - ]:           5 :             pCS->nLenCanonOrdTaut > 0 ? pCS->nCanonOrdTaut : NULL;
    1468                 :           7 :         pConstitEquNumb = pINChI_Aux->nConstitEquTGroupNumbers;
    1469                 :           7 :         pSymmRank = pCS->nSymmRankTaut;
    1470                 :             : 
    1471   [ +  -  +  -  :           7 :         if (pCanonOrdTaut && pSymmRank && pConstitEquNumb)
                   +  - ]
    1472                 :             :         {
    1473         [ +  + ]:          19 :             for (i = 0; i < n; i++)
    1474                 :             :             {
    1475                 :          12 :                 pConstitEquNumb[i] = pSymmRank[pCanonOrdTaut[i]];
    1476                 :          12 :                 pSortOrd[i] = i;
    1477                 :             :             }
    1478                 :           7 :             pCG->m_pn_RankForSort = pConstitEquNumb;
    1479                 :           7 :             inchi_qsort( pCG, pSortOrd, n, sizeof( pSortOrd[0] ), CompRanksOrd );
    1480         [ +  + ]:          19 :             for (i = 0, nMinOrd = pSortOrd[0], j = 1; j <= n; j++)
    1481                 :             :             {
    1482   [ +  +  -  + ]:          12 :                 if (j == n || pConstitEquNumb[pSortOrd[i]] != pConstitEquNumb[pSortOrd[j]])
    1483                 :             :                 {
    1484                 :           7 :                     nMinOrd++; /* make is start from 1, not from zero */
    1485         [ +  + ]:           7 :                     if (j - i > 1)
    1486                 :             :                     {
    1487                 :             :                         /*  found a sequence of more than one equivalent t-groups: i..j-1 */
    1488         [ +  + ]:          11 :                         while (i < j)
    1489                 :             :                         {
    1490                 :           8 :                             pConstitEquNumb[pSortOrd[i++]] = nMinOrd;
    1491                 :             :                         }
    1492                 :             :                     }
    1493                 :             :                     else
    1494                 :             :                     {
    1495                 :           4 :                         pConstitEquNumb[pSortOrd[i++]] = 0;
    1496                 :             :                     }
    1497                 :           7 :                     nMinOrd = pSortOrd[j]; /*  at the end j == n */
    1498                 :             :                 }
    1499                 :             :             }
    1500                 :             :         }
    1501                 :             :     }
    1502                 :             : 
    1503                 :             : 
    1504                 :             :     /*  Allocate and fill Hill formula */
    1505                 :             : 
    1506                 :         161 :     pINChI->szHillFormula = AllocateAndFillHillFormula( pINChI );
    1507                 :             : 
    1508         [ -  + ]:         161 :     if (!pINChI->szHillFormula)
    1509                 :             :     {
    1510                 :           0 :         nErrorCode = 0;
    1511                 :           0 :         ret = CT_WRONG_FORMULA; /* CT_OUT_OF_RAM;*/  /*   <BRKPT> */
    1512                 :           0 :         pINChI->nErrorCode = pINChI_Aux->nErrorCode = ret;
    1513                 :           0 :         goto exit_function;
    1514                 :             :     }
    1515                 :             : 
    1516                 :         161 :     nStereoUnmarkMode = UnmarkAllUndefinedUnknownStereo( pINChI->Stereo, nUserMode );
    1517                 :             : 
    1518         [ +  + ]:         161 :     if (nStereoUnmarkMode)
    1519                 :             :     {
    1520                 :           4 :         pINChI->nFlags |=
    1521                 :             :             ( nStereoUnmarkMode & REQ_MODE_SC_IGN_ALL_UU ) ? INCHI_FLAG_SC_IGN_ALL_UU
    1522                 :           4 :             : 0;
    1523                 :           4 :         pINChI->nFlags |=
    1524                 :             :             ( nStereoUnmarkMode & REQ_MODE_SB_IGN_ALL_UU ) ? INCHI_FLAG_SB_IGN_ALL_UU
    1525                 :           4 :             : 0;
    1526                 :             : 
    1527         [ -  + ]:           4 :         if (( nStereoUnmarkMode & REQ_MODE_SC_IGN_ALL_UU ) ||
    1528         [ #  # ]:           0 :             ( nStereoUnmarkMode & REQ_MODE_SB_IGN_ALL_UU ))
    1529                 :             :         {
    1530         [ +  - ]:           4 :             if (!bNoWarnings)
    1531                 :             :             {
    1532                 :           4 :                 WarningMessage( pStrErrStruct, "Omitted undefined stereo" );
    1533                 :             :             }
    1534                 :             :         }
    1535                 :             :     }
    1536                 :             : 
    1537                 :             :     /*************************/
    1538                 :             :     /* Mark ambiguous stereo */
    1539                 :             :     /*************************/
    1540                 :             : 
    1541                 :         161 :     MarkAmbiguousStereo( at, norm_at, 0 /* non-isotopic */, pCanonOrd,
    1542                 :             :                          pCS->LinearCTStereoCarb, pCS->nLenLinearCTStereoCarb,
    1543                 :             :                          pCS->LinearCTStereoDble, pCS->nLenLinearCTStereoDble );
    1544                 :             : 
    1545                 :             : 
    1546                 :             :     /************************************************************************
    1547                 :             :      *
    1548                 :             :      *  Isotopic part
    1549                 :             :      */
    1550                 :             : 
    1551                 :             :     /* abs or rel stereo may establish one of two canonical numberings */
    1552                 :             : 
    1553   [ +  -  -  + ]:         161 :     if (( pCS->nLenLinearCTIsotopicStereoCarb > 0 || pCS->nLenLinearCTIsotopicStereoDble > 0 ) &&
    1554         [ #  # ]:           0 :           pCS->nLenCanonOrdIsotopicStereo > 0 &&
    1555   [ #  #  #  # ]:           0 :           ( (pCS->LinearCTIsotopicStereoCarb && pCS->LinearCTIsotopicStereoCarbInv) ||
    1556   [ #  #  #  # ]:           0 :               (pCS->LinearCTIsotopicStereoDble && pCS->LinearCTIsotopicStereoDbleInv) ) &&
    1557   [ #  #  #  # ]:           0 :           pCS->nCanonOrdIsotopicStereo && pCS->nCanonOrdIsotopicStereoInv
    1558                 :             :           ) /* djb-rwth: addressing LLVM warning */
    1559                 :             :     {
    1560                 :             :         /* found isotopic stereo */
    1561                 :             : 
    1562                 :           0 :         pCanonRank = pCanonRankAtoms;
    1563                 :           0 :         pCanonOrd = pCS->nCanonOrdIsotopicStereo;
    1564                 :           0 :         pCanonRankInv = pSortOrd;
    1565                 :           0 :         pCanonOrdInv = pCS->nCanonOrdIsotopicStereoInv;
    1566                 :           0 :         Stereo = pINChI->StereoIsotopic;
    1567                 :             : 
    1568         [ #  # ]:           0 :         for (i = 0; i < num_at_tg; i++)
    1569                 :             :         {
    1570                 :           0 :             pCanonRankInv[pCanonOrdInv[i]] =
    1571                 :           0 :                 pCanonRank[pCanonOrd[i]] = (AT_NUMB) ( i + 1 );
    1572                 :             :         }
    1573                 :             : 
    1574                 :             : 
    1575                 :             :         /********************************************************************/
    1576                 :             :         /* copy stereo bonds and stereo centers; compare Inv and Abs stereo */
    1577                 :             :         /********************************************************************/
    1578                 :             : 
    1579                 :           0 :         nErrorCode = CopyLinearCTStereoToINChIStereo( Stereo,
    1580                 :             :                                                       pCS->LinearCTIsotopicStereoCarb,
    1581                 :             :                                                       pCS->nLenLinearCTIsotopicStereoCarb,
    1582                 :             :                                                       pCS->LinearCTIsotopicStereoDble,
    1583                 :             :                                                       pCS->nLenLinearCTIsotopicStereoDble,
    1584                 :             :                                                       pCanonOrd, pCanonRank, at, 1 /* isotopic */,
    1585                 :             :                                                       pCS->LinearCTIsotopicStereoCarbInv,
    1586                 :             :                                                       pCS->LinearCTIsotopicStereoDbleInv,
    1587                 :             :                                                       pCanonOrdInv, pCanonRankInv );
    1588                 :             : 
    1589                 :             :         /* djb-rwth: fixing oss-fuzz issue #68271 */
    1590         [ #  # ]:           0 :         if (nErrorCode == 1)
    1591                 :             :         {
    1592                 :           0 :             nErrorCode = 0;
    1593                 :           0 :             ret = CT_OUT_OF_RAM;  /*   <BRKPT> */
    1594                 :           0 :             pINChI->nErrorCode = pINChI_Aux->nErrorCode = CT_OUT_OF_RAM;
    1595                 :           0 :             goto exit_function;
    1596                 :             :         }
    1597                 :             :         
    1598   [ #  #  #  # ]:           0 :         if (Stereo->t_parityInv && Stereo->nNumberInv)
    1599                 :             :         {
    1600         [ #  # ]:           0 :             if (nUserMode & REQ_MODE_RELATIVE_STEREO)
    1601                 :             :             {
    1602                 :           0 :                 pINChI->nFlags |= INCHI_FLAG_REL_STEREO;
    1603                 :             :             }
    1604                 :             : 
    1605         [ #  # ]:           0 :             if (nUserMode & REQ_MODE_RACEMIC_STEREO)
    1606                 :             :             {
    1607                 :           0 :                 pINChI->nFlags |= INCHI_FLAG_RAC_STEREO;
    1608                 :             :             }
    1609                 :             : 
    1610         [ #  # ]:           0 :             if (Stereo->nCompInv2Abs)
    1611                 :             :             {
    1612         [ #  # ]:           0 :                 if (Stereo->nCompInv2Abs == -1)
    1613                 :             :                 {
    1614                 :             :                     /* switch pointers so that the stereo becomes the smallest (relative)  */
    1615                 :             :                     /* flag Stereo->nCompInv2Abs == -1 will keep track of this exchange */
    1616                 :           0 :                     AT_NUMB    *nNumberInv = Stereo->nNumberInv;
    1617                 :           0 :                     S_CHAR     *t_parityInv = Stereo->t_parityInv;
    1618                 :           0 :                     Stereo->nNumberInv = Stereo->nNumber;
    1619                 :           0 :                     Stereo->t_parityInv = Stereo->t_parity;
    1620                 :           0 :                     Stereo->nNumber = nNumberInv;
    1621                 :           0 :                     Stereo->t_parity = t_parityInv;
    1622                 :           0 :                     switch_ptrs( &pCanonRank, &pCanonRankInv );
    1623                 :           0 :                     switch_ptrs( &pCanonOrd, &pCanonOrdInv );
    1624                 :           0 :                     bUseIsotopicNumberingInv = 1;
    1625                 :             :                 }
    1626                 :             :             }
    1627                 :             :         }
    1628                 :             : 
    1629         [ #  # ]:           0 :         for (i = 0; i < num_atoms; i++)
    1630                 :             :         {
    1631                 :           0 :             pINChI_Aux->nIsotopicOrigAtNosInCanonOrdInv[i] = at[pCanonOrdInv[i]].orig_at_number;
    1632                 :           0 :             pINChI_Aux->nIsotopicOrigAtNosInCanonOrd[i] = at[pCanonOrd[i]].orig_at_number;
    1633                 :             :         }
    1634                 :             : 
    1635         [ #  # ]:           0 :         if (bUseIsotopicNumberingInv)
    1636                 :             :         {
    1637                 :           0 :             switch_ptrs( &pCanonRank, &pCanonRankInv );
    1638                 :           0 :             switch_ptrs( &pCanonOrd, &pCanonOrdInv );
    1639                 :           0 :             memcpy(pCanonRank, pCanonRankInv, num_at_tg * sizeof(pCanonRank[0]));
    1640                 :           0 :             memcpy(pCanonOrd, pCanonOrdInv, num_at_tg * sizeof(pCanonOrd[0]));
    1641                 :             :         }
    1642                 :             : 
    1643                 :           0 :         pCanonRankInv = NULL;
    1644                 :           0 :         pCanonOrdInv = NULL;
    1645                 :           0 :         pOrigNosInCanonOrd = NULL;
    1646                 :             :     }
    1647                 :             :     else
    1648                 :             :     {
    1649                 :             :         /* no isotopic stereo */
    1650                 :             : 
    1651                 :         322 :         pCanonOrd = pCS->nLenCanonOrdIsotopicStereo > 0 ? pCS->nCanonOrdIsotopicStereo
    1652   [ -  +  -  + ]:         161 :             : pCS->nLenCanonOrdIsotopic > 0 ? pCS->nCanonOrdIsotopic
    1653                 :             :             : NULL;
    1654                 :         161 :         pCanonRank = pCanonRankAtoms;
    1655                 :         161 :         pOrigNosInCanonOrd = pINChI_Aux->nIsotopicOrigAtNosInCanonOrd;
    1656                 :             : 
    1657                 :             :         /* djb-rwth: fixing oss-fuzz issue #30496 */
    1658   [ -  +  -  -  :         161 :         if (pCanonOrd && pCanonRank && pOrigNosInCanonOrd)
                   -  - ]
    1659                 :             :         {
    1660         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    1661                 :             :             {
    1662                 :             :                 /* Fix13 -- out of bounds */
    1663                 :           0 :                 pCanonRank[pCanonOrd[i]] = (AT_NUMB) ( i + 1 );
    1664                 :           0 :                 pOrigNosInCanonOrd[i] = at[pCanonOrd[i]].orig_at_number;
    1665                 :             :             }
    1666         [ #  # ]:           0 :             for (; i < num_at_tg; i++)
    1667                 :             :             {
    1668                 :             :                 /* Fix13 -- out of bounds */
    1669                 :           0 :                 pCanonRank[pCanonOrd[i]] = (AT_NUMB) ( i + 1 );
    1670                 :             :             }
    1671                 :             :         }
    1672                 :             :     }
    1673                 :             :     /*pCanonOrdIso = pCanonOrd;*/
    1674                 :             : 
    1675                 :             : 
    1676                 :         161 :     pConstitEquNumb = pINChI_Aux->nConstitEquIsotopicNumbers;
    1677                 :         161 :     pSymmRank = pCS->nSymmRankIsotopic;
    1678                 :             : 
    1679   [ -  +  -  -  :         161 :     if (pCanonOrd && pCanonRank && pConstitEquNumb && pSymmRank)
             -  -  -  - ]
    1680                 :             :     {
    1681         [ #  # ]:           0 :         for (i = 0; i < num_atoms; i++)
    1682                 :             :         {
    1683                 :           0 :             pConstitEquNumb[i] = pSymmRank[pCanonOrd[i]];
    1684                 :           0 :             pSortOrd[i] = i;
    1685                 :             :         }
    1686                 :             : 
    1687         [ #  # ]:           0 :         for (; i < num_at_tg; i++)
    1688                 :             :         {
    1689                 :           0 :             pSortOrd[i] = i;
    1690                 :             :         }
    1691                 :             : 
    1692                 :           0 :         pCG->m_pn_RankForSort = pConstitEquNumb;
    1693                 :           0 :         inchi_qsort( pCG, pSortOrd, num_atoms, sizeof( pSortOrd[0] ), CompRanksOrd );
    1694                 :             : 
    1695         [ #  # ]:           0 :         for (i = 0, nMinOrd = pSortOrd[0], j = 1; j <= num_atoms; j++)
    1696                 :             :         {
    1697   [ #  #  #  # ]:           0 :             if (j == num_atoms || pConstitEquNumb[pSortOrd[i]] != pConstitEquNumb[pSortOrd[j]])
    1698                 :             :             {
    1699                 :           0 :                 nMinOrd++;
    1700                 :             : 
    1701         [ #  # ]:           0 :                 if (j - i > 1)
    1702                 :             :                 {
    1703                 :             :                     /*  found a sequence of equivalent atoms: i..j-1 */
    1704         [ #  # ]:           0 :                     while (i < j)
    1705                 :             :                     {
    1706                 :           0 :                         pConstitEquNumb[pSortOrd[i++]] = nMinOrd;
    1707                 :             :                     }
    1708                 :             :                 }
    1709                 :             :                 else
    1710                 :             :                 {
    1711                 :           0 :                     pConstitEquNumb[pSortOrd[i++]] = 0; /* nMinOrd; */
    1712                 :             :                 }
    1713                 :           0 :                 nMinOrd = pSortOrd[j];
    1714                 :             :             }
    1715                 :             :         }
    1716                 :             :     }
    1717                 :             :     else
    1718                 :             :     {
    1719                 :         161 :         goto exit_function; /*  no isotopic info available */
    1720                 :             :     }
    1721                 :             : 
    1722                 :             : 
    1723                 :             :     /*  Isotopic atoms */
    1724                 :             : 
    1725                 :           0 :     n = pINChI->nNumberOfIsotopicAtoms = pCS->nLenLinearCTIsotopic;
    1726                 :             : 
    1727         [ #  # ]:           0 :     for (i = 0; i < n; i++)
    1728                 :             :     {
    1729                 :           0 :         pINChI->IsotopicAtom[i].nAtomNumber = pCS->LinearCTIsotopic[i].at_num;
    1730                 :           0 :         pINChI->IsotopicAtom[i].nIsoDifference = pCS->LinearCTIsotopic[i].iso_atw_diff;
    1731                 :           0 :         pINChI->IsotopicAtom[i].nNum_H = pCS->LinearCTIsotopic[i].num_1H;
    1732                 :           0 :         pINChI->IsotopicAtom[i].nNum_D = pCS->LinearCTIsotopic[i].num_D;
    1733                 :           0 :         pINChI->IsotopicAtom[i].nNum_T = pCS->LinearCTIsotopic[i].num_T;
    1734                 :             :     }
    1735                 :             : 
    1736                 :             :     /*  Isotopic tautomeric groups */
    1737                 :             : 
    1738                 :           0 :     n = pINChI->nNumberOfIsotopicTGroups = pCS->nLenLinearCTIsotopicTautomer;
    1739                 :             : 
    1740         [ #  # ]:           0 :     for (i = 0; i < n; i++)
    1741                 :             :     {
    1742                 :           0 :         pINChI->IsotopicTGroup[i].nTGroupNumber = pCS->LinearCTIsotopicTautomer[i].tgroup_num;
    1743                 :           0 :         pINChI->IsotopicTGroup[i].nNum_H = pCS->LinearCTIsotopicTautomer[i].num[2];
    1744                 :           0 :         pINChI->IsotopicTGroup[i].nNum_D = pCS->LinearCTIsotopicTautomer[i].num[1];
    1745                 :           0 :         pINChI->IsotopicTGroup[i].nNum_T = pCS->LinearCTIsotopicTautomer[i].num[0];
    1746                 :             :     }
    1747                 :             : 
    1748                 :             :     /* Atoms that may exchange isotopic H-atoms */
    1749                 :             : 
    1750   [ #  #  #  # ]:           0 :     if (pCS->nExchgIsoH && pINChI->nPossibleLocationsOfIsotopicH)
    1751                 :             :     {
    1752         [ #  # ]:           0 :         for (i = 0, j = 1; i < num_atoms; i++)
    1753                 :             :         {
    1754         [ #  # ]:           0 :             if (pCS->nExchgIsoH[i])
    1755                 :             :             {
    1756                 :           0 :                 pINChI->nPossibleLocationsOfIsotopicH[j++] = (AT_NUMB) ( i + 1 ); /* canonical number */
    1757                 :             :             }
    1758                 :             :         }
    1759                 :           0 :         pINChI->nPossibleLocationsOfIsotopicH[0] = (AT_NUMB) j; /* length including the 0th element */
    1760                 :             :     }
    1761                 :             : 
    1762         [ #  # ]:           0 :     if ((nStereoUnmarkMode = UnmarkAllUndefinedUnknownStereo( pINChI->StereoIsotopic, nUserMode ))) /* djb-rwth: addressing LLVM warning */
    1763                 :             :     {
    1764                 :           0 :         pINChI->nFlags |=
    1765                 :             :             ( nStereoUnmarkMode & REQ_MODE_SC_IGN_ALL_UU ) ? INCHI_FLAG_SC_IGN_ALL_ISO_UU
    1766                 :           0 :             : 0;
    1767                 :           0 :         pINChI->nFlags |=
    1768                 :             :             ( nStereoUnmarkMode & REQ_MODE_SB_IGN_ALL_UU ) ? INCHI_FLAG_SC_IGN_ALL_ISO_UU
    1769                 :           0 :             : 0;
    1770         [ #  # ]:           0 :         if (( nStereoUnmarkMode & REQ_MODE_SC_IGN_ALL_UU ) ||
    1771         [ #  # ]:           0 :             ( nStereoUnmarkMode & REQ_MODE_SB_IGN_ALL_UU ))
    1772                 :             :         {
    1773         [ #  # ]:           0 :             if (!bNoWarnings)
    1774                 :             :             {
    1775                 :           0 :                 WarningMessage( pStrErrStruct, "Omitted undefined stereo" );
    1776                 :             :             }
    1777                 :             :         }
    1778                 :             :     }
    1779                 :             : 
    1780                 :             :     /* Mark ambiguous stereo */
    1781                 :             : 
    1782                 :           0 :     MarkAmbiguousStereo( at, norm_at, 1 /* isotopic */, pCanonOrd,
    1783                 :             :                          pCS->LinearCTIsotopicStereoCarb, pCS->nLenLinearCTIsotopicStereoCarb,
    1784                 :             :                          pCS->LinearCTIsotopicStereoDble, pCS->nLenLinearCTIsotopicStereoDble );
    1785                 :             : 
    1786                 :             : 
    1787                 :             :     /***********************************************************
    1788                 :             :      *  Isotopic tautomeric group(s) numbering and symmetry;
    1789                 :             :      *  should not depend on switching to rel. stereo numbering
    1790                 :             :      */
    1791                 :             : 
    1792         [ #  # ]:           0 :     if (pINChI->lenTautomer &&
    1793         [ #  # ]:           0 :          pINChI_Aux->nConstitEquIsotopicTGroupNumbers &&
    1794         [ #  # ]:           0 :          pCS->nSymmRankIsotopicTaut &&
    1795   [ #  #  #  #  :           0 :          ( pCS->nLenLinearCTIsotopic || pCS->nLenLinearCTIsotopicTautomer ) &&
                   #  # ]
    1796         [ #  # ]:           0 :          t_group_info && t_group_info->num_t_groups > 0)
    1797                 :             :     {
    1798                 :             : 
    1799                 :             :         /* djb-rwth: removing redundant code */
    1800                 :             : 
    1801                 :           0 :         pCanonOrdTaut =
    1802                 :           0 :             pCS->nLenCanonOrdIsotopicStereoTaut > 0 ? ( n = pCS->nLenCanonOrdIsotopicStereoTaut, pCS->nCanonOrdIsotopicStereoTaut )
    1803   [ #  #  #  # ]:           0 :             : pCS->nLenCanonOrdIsotopicTaut > 0 ? ( n = pCS->nLenCanonOrdIsotopicTaut, pCS->nCanonOrdIsotopicTaut )
    1804                 :           0 :             : ( n = 0, (AT_RANK*) NULL );
    1805                 :             : 
    1806                 :           0 :         pConstitEquNumb = pINChI_Aux->nConstitEquIsotopicTGroupNumbers;
    1807                 :             : 
    1808                 :           0 :         pSymmRank = pCS->nSymmRankIsotopicTaut;
    1809                 :             : 
    1810   [ #  #  #  #  :           0 :         if (pCanonOrdTaut && pSymmRank && pConstitEquNumb && n > 0)
             #  #  #  # ]
    1811                 :             :         {
    1812         [ #  # ]:           0 :             for (i = 0; i < n; i++)
    1813                 :             :             {
    1814                 :           0 :                 pConstitEquNumb[i] = pSymmRank[pCanonOrdTaut[i]];
    1815                 :           0 :                 pSortOrd[i] = i;
    1816                 :             :             }
    1817                 :             : 
    1818                 :           0 :             pCG->m_pn_RankForSort = pConstitEquNumb;
    1819                 :           0 :             inchi_qsort( pCG, pSortOrd, n, sizeof( pSortOrd[0] ), CompRanksOrd );
    1820         [ #  # ]:           0 :             for (i = 0, nMinOrd = pSortOrd[0], j = 1; j <= n; j++)
    1821                 :             :             {
    1822   [ #  #  #  # ]:           0 :                 if (j == n || pConstitEquNumb[pSortOrd[i]] != pConstitEquNumb[pSortOrd[j]])
    1823                 :             :                 {
    1824                 :           0 :                     nMinOrd++;
    1825         [ #  # ]:           0 :                     if (j - i > 1)
    1826                 :             :                     {
    1827                 :             :                         /*  found a sequence of equivalent t-groups: i..j-1 */
    1828         [ #  # ]:           0 :                         while (i < j)
    1829                 :             :                         {
    1830                 :           0 :                             pConstitEquNumb[pSortOrd[i++]] = nMinOrd;
    1831                 :             :                         }
    1832                 :             :                     }
    1833                 :             :                     else
    1834                 :             :                     {
    1835                 :           0 :                         pConstitEquNumb[pSortOrd[i++]] = 0; /*  nMinOrd; */
    1836                 :             :                     }
    1837                 :           0 :                     nMinOrd = pSortOrd[j]; /*  at the end j = n */
    1838                 :             :                 }
    1839                 :             :             }
    1840                 :             :         }
    1841                 :             :     }
    1842                 :             : 
    1843                 :             : 
    1844                 :           0 : exit_function:
    1845                 :             : 
    1846         [ +  - ]:         161 :     if (pCanonRankAtoms)
    1847                 :             :     {
    1848         [ +  - ]:         161 :         inchi_free( pCanonRankAtoms );
    1849                 :             :     }
    1850         [ +  - ]:         161 :     if (pSortOrd)
    1851                 :             :     {
    1852         [ +  - ]:         161 :         inchi_free( pSortOrd );
    1853                 :             :     }
    1854                 :             : 
    1855                 :         161 :     pINChI->nErrorCode |= nErrorCode;
    1856                 :         161 :     pINChI_Aux->nErrorCode |= nErrorCode;
    1857                 :             : 
    1858                 :         161 :     return ret;
    1859                 :             : }
        

Generated by: LCOV version 2.0-1