LCOV - code coverage report
Current view: top level - src - ichimak2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 51.6 % 645 333
Test Date: 2026-05-04 07:05:02 Functions: 83.3 % 12 10
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 38.7 % 622 241

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

Generated by: LCOV version 2.0-1