LCOV - code coverage report
Current view: top level - src - ichiprt2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 50.0 % 1013 507
Test Date: 2026-10-14 12:14:55 Functions: 75.0 % 32 24
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 38.7 % 995 385

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * SPDX-License-Identifier: MIT
       3                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
       4                 :             :  */
       5                 :             : 
       6                 :             : #include <stdlib.h>
       7                 :             : #include <string.h>
       8                 :             : #include <ctype.h>
       9                 :             : #include <limits.h>
      10                 :             : 
      11                 :             : #include "mode.h"
      12                 :             : #include "ichimain.h"
      13                 :             : #include "ichimake.h"
      14                 :             : #include "ichi_io.h"
      15                 :             : 
      16                 :             : #include "bcf_s.h"
      17                 :             : 
      18                 :             :  /****************************************************************************/
      19                 :          62 : int Eql_INChI_Stereo( INChI_Stereo  *s1,
      20                 :             :                       int           eql1,
      21                 :             :                       INChI_Stereo  *s2,
      22                 :             :                       int           eql2,
      23                 :             :                       int           bRelRac )
      24                 :             : {
      25                 :          62 :     int inv1 = 0, inv2 = 0, len;
      26                 :             : 
      27         [ -  + ]:          62 :     if (!s1)
      28                 :             :     {
      29                 :           0 :         return 0;
      30                 :             :     }
      31                 :             : #if ( REL_RAC_STEREO_IGN_1_SC == 1 )
      32                 :             : #else
      33                 :          62 :     bRelRac = 0;
      34                 :             : #endif
      35                 :             : 
      36         [ -  + ]:          62 :     if (EQL_SP2 == eql1)
      37                 :             :     {
      38   [ #  #  #  #  :           0 :         if (( len = s1->nNumberOfStereoBonds ) > 0 && s1->b_parity && s1->nBondAtom1 && s1->nBondAtom2)
             #  #  #  # ]
      39                 :             :         {
      40         [ #  # ]:           0 :             if (!s2)
      41                 :             :             {
      42         [ #  # ]:           0 :                 if (EQL_EXISTS == eql2)
      43                 :             :                 {
      44                 :             :                     /* find whether double bond stereo exists*/
      45                 :           0 :                     return 1;
      46                 :             :                 }
      47                 :           0 :                 return 0;
      48                 :             :             }
      49         [ #  # ]:           0 :             if (EQL_SP2 == eql2 &&
      50   [ #  #  #  #  :           0 :                  len == s2->nNumberOfStereoBonds && s2->b_parity && s2->nBondAtom1 && s2->nBondAtom2 &&
             #  #  #  # ]
      51         [ #  # ]:           0 :                  !memcmp( s1->nBondAtom1, s2->nBondAtom1, len * sizeof( s1->nBondAtom1[0] ) ) &&
      52         [ #  # ]:           0 :                  !memcmp( s1->nBondAtom2, s2->nBondAtom2, len * sizeof( s1->nBondAtom2[0] ) ) &&
      53         [ #  # ]:           0 :                  !memcmp( s1->b_parity, s2->b_parity, len * sizeof( s1->b_parity[0] ) ))
      54                 :             :             {
      55                 :           0 :                 return 1;
      56                 :             :             }
      57                 :             :         }
      58                 :           0 :         return 0;
      59                 :             :     }
      60                 :             : 
      61                 :             :     else
      62                 :             :     {
      63   [ +  +  +  - ]:          62 :         if (( eql1 == EQL_SP3 || ( inv1 = ( eql1 == EQL_SP3_INV ) ) ) &&
      64         [ +  + ]:          62 :             ( len = s1->nNumberOfStereoCenters ) > ( bRelRac ? 1 : 0 )) /* djb-rwth: addressing coverity ID #499484 -- bRelRac does not have to be 0 */
      65                 :             :         {
      66                 :             : 
      67                 :             :             S_CHAR  *t_parity1, *t_parity2;
      68                 :             :             AT_NUMB *nNumber1, *nNumber2;
      69         [ +  + ]:          60 :             if (inv1)
      70                 :             :             {
      71         [ +  - ]:          51 :                 if (s1->nCompInv2Abs)
      72                 :             :                 {
      73                 :          51 :                     t_parity1 = s1->t_parityInv;
      74                 :          51 :                     nNumber1 = s1->nNumberInv;
      75                 :             :                 }
      76                 :             :                 else
      77                 :             :                 {
      78                 :           0 :                     return 0;
      79                 :             :                 }
      80                 :             :             }
      81                 :             :             else
      82                 :             :             {
      83                 :           9 :                 t_parity1 = s1->t_parity;
      84                 :           9 :                 nNumber1 = s1->nNumber;
      85                 :             :             }
      86   [ +  -  +  - ]:          60 :             if (t_parity1 && nNumber1)
      87                 :             :             {
      88         [ -  + ]:          60 :                 if (!s2)
      89                 :             :                 {
      90   [ #  #  #  #  :           0 :                     if (EQL_EXISTS == eql2 && ( !inv1 || s1->nCompInv2Abs ))
                   #  # ]
      91                 :             :                     {
      92                 :             :                         /* the 1st sp3 (inverted if requested) stereo exists*/
      93                 :           0 :                         return 1;
      94                 :             :                     }
      95                 :           0 :                     return 0;  /* both sp3 do not exist */
      96                 :             :                 }
      97   [ -  +  -  - ]:          60 :                 if (( eql2 == EQL_SP3 || ( inv2 = ( eql2 == EQL_SP3_INV ) ) ) &&
      98         [ +  + ]:          60 :                     len == s2->nNumberOfStereoCenters)
      99                 :             :                 {
     100         [ -  + ]:          57 :                     if (inv2)
     101                 :             :                     {
     102   [ #  #  #  # ]:           0 :                         if (s2->nCompInv2Abs && s1->nCompInv2Abs)
     103                 :             :                         {
     104                 :           0 :                             t_parity2 = s2->t_parityInv;
     105                 :           0 :                             nNumber2 = s2->nNumberInv;
     106                 :             :                         }
     107                 :             :                         else
     108                 :             :                         {
     109                 :             :                             /* if one sp3 is inverted then another should have non-trivial inverted stereo */
     110                 :           0 :                             return 0;
     111                 :             :                         }
     112                 :             :                     }
     113                 :             :                     else
     114                 :             :                     {
     115   [ +  +  -  + ]:          57 :                         if (inv1 && !s2->nCompInv2Abs)
     116                 :             :                         {
     117                 :             :                             /* if one sp3 is inverted then another should have non-trivial inverted stereo */
     118                 :           0 :                             return 0;
     119                 :             :                         }
     120                 :          57 :                         t_parity2 = s2->t_parity;
     121                 :          57 :                         nNumber2 = s2->nNumber;
     122                 :             :                     }
     123   [ +  -  +  - ]:          57 :                     if (t_parity2 && nNumber2)
     124                 :             :                     {
     125         [ +  + ]:          57 :                         if (inv1 ^ inv2)
     126                 :             :                         {
     127                 :             :                             int i, num_inv;
     128         [ +  + ]:         187 :                             for (i = 0, num_inv = 0; i < len; i++)
     129                 :             :                             {
     130         [ -  + ]:         149 :                                 if (nNumber1[i] != nNumber2[i])
     131                 :           0 :                                     break;
     132   [ +  -  +  + ]:         149 :                                 if (ATOM_PARITY_WELL_DEF( t_parity1[i] ) &&
     133   [ +  -  +  - ]:         136 :                                      ATOM_PARITY_WELL_DEF( t_parity2[i] ))
     134                 :             :                                 {
     135         [ +  + ]:         136 :                                     if (3 == t_parity1[i] + t_parity2[i])
     136                 :             :                                     {
     137                 :         123 :                                         num_inv++;
     138                 :             :                                     }
     139                 :             :                                     else
     140                 :             :                                     {
     141                 :          13 :                                         break;
     142                 :             :                                     }
     143                 :             :                                 }
     144                 :             :                                 else
     145         [ -  + ]:          13 :                                     if (t_parity1[i] != t_parity2[i])
     146                 :             :                                     {
     147                 :           0 :                                         break;
     148                 :             :                                     }
     149                 :             :                             }
     150   [ +  +  +  - ]:          51 :                             return ( len == i && num_inv > 0 );
     151                 :             :                         }
     152                 :             :                         else
     153                 :             :                         {
     154         [ +  - ]:          12 :                             return !memcmp( t_parity1, t_parity2, len * sizeof( t_parity1[0] ) ) &&
     155         [ +  + ]:           6 :                                 !memcmp( nNumber1, nNumber2, len * sizeof( nNumber1[0] ) );
     156                 :             :                         }
     157                 :             :                     }
     158                 :             :                 }
     159                 :             :             }
     160                 :             :         }
     161                 :             :     }
     162                 :             : 
     163                 :           5 :     return 0;
     164                 :             : }
     165                 :             : 
     166                 :             : 
     167                 :             : /****************************************************************************/
     168                 :           0 : int Eql_INChI_Isotopic( INChI *i1, INChI *i2 )
     169                 :             : {
     170                 :           0 :     int eq = i1
     171         [ #  # ]:           0 :             && i2
     172         [ #  # ]:           0 :             && !i1->bDeleted
     173         [ #  # ]:           0 :             && !i2->bDeleted
     174   [ #  #  #  # ]:           0 :             && ( i1->nNumberOfIsotopicAtoms > 0 || i1->nNumberOfIsotopicTGroups > 0 )
     175         [ #  # ]:           0 :             && i1->nNumberOfIsotopicAtoms == i2->nNumberOfIsotopicAtoms
     176         [ #  # ]:           0 :             && i1->nNumberOfIsotopicTGroups == i2->nNumberOfIsotopicTGroups
     177         [ #  # ]:           0 :             && ( !i1->nNumberOfIsotopicAtoms ||
     178   [ #  #  #  # ]:           0 :                 (i1->IsotopicAtom && i2->IsotopicAtom &&
     179                 :           0 :                 !memcmp( i1->IsotopicAtom, i2->IsotopicAtom,
     180         [ #  # ]:           0 :                         i1->nNumberOfIsotopicAtoms * sizeof( i1->IsotopicAtom[0] ) )) )
     181   [ #  #  #  # ]:           0 :             && ( !i1->nNumberOfIsotopicTGroups ||
     182   [ #  #  #  # ]:           0 :                 (i1->IsotopicTGroup && i2->IsotopicTGroup &&
     183                 :           0 :                 !memcmp( i1->IsotopicTGroup, i2->IsotopicTGroup,
     184         [ #  # ]:           0 :                     i1->nNumberOfIsotopicTGroups * sizeof( i1->IsotopicAtom[0] )) )
     185                 :             :             ); /* djb-rwth: addressing LLVM warnings */
     186                 :             : 
     187                 :           0 :     return eq;
     188                 :             : }
     189                 :             : 
     190                 :             : 
     191                 :             : /****************************************************************************/
     192                 :          46 : int Eql_INChI_Aux_Equ( INChI_Aux *a1, int eql1, INChI_Aux *a2, int eql2 )
     193                 :             : {
     194                 :          46 :     int t1 = 0, t2 = 0, len = 0;
     195                 :          46 :     AT_NUMB *n1 = NULL, *n2 = NULL;
     196   [ +  +  -  + ]:          46 :     if (!a1 || !a2)
     197                 :             :     {
     198                 :          23 :         return 0;
     199                 :             :     }
     200                 :          23 :     t1 = ( eql1 & EQL_EQU_TG );
     201                 :          23 :     t2 = ( eql2 & EQL_EQU_TG );
     202   [ +  +  +  - ]:          23 :     if (t1 && t2)
     203                 :             :     {
     204   [ +  +  +  -  :           5 :         if (( len = a1->nNumberOfTGroups ) > 0 && len == a2->nNumberOfTGroups && !a1->bDeleted && !a2->bDeleted)
             +  -  +  - ]
     205                 :             :         {
     206         [ -  + ]:           1 :             if (eql1 & EQL_EQU_ISO)
     207                 :             :             {
     208         [ #  # ]:           0 :                 if (a1->bIsIsotopic)
     209                 :             :                 {
     210                 :           0 :                     n1 = a1->nConstitEquIsotopicTGroupNumbers;
     211                 :             :                 }
     212                 :             :             }
     213                 :             :             else
     214                 :             :             {
     215                 :           1 :                 n1 = a1->nConstitEquTGroupNumbers;
     216                 :             :             }
     217         [ -  + ]:           1 :             if (eql2 & EQL_EQU_ISO)
     218                 :             :             {
     219         [ #  # ]:           0 :                 if (a2->bIsIsotopic)
     220                 :             :                 {
     221                 :           0 :                     n2 = a2->nConstitEquIsotopicTGroupNumbers;
     222                 :             :                 }
     223                 :             :             }
     224                 :             :             else
     225                 :             :             {
     226                 :           1 :                 n2 = a2->nConstitEquTGroupNumbers;
     227                 :             :             }
     228                 :             :         }
     229                 :             :     }
     230                 :             :     else
     231   [ +  -  +  - ]:          18 :         if (!t1 && !t2)
     232                 :             :         {
     233   [ +  -  +  +  :          18 :             if (( len = a1->nNumberOfAtoms ) > 0 && len == a2->nNumberOfAtoms && !a1->bDeleted && !a2->bDeleted)
             +  -  +  - ]
     234                 :             :             {
     235         [ -  + ]:           7 :                 if (eql1 & EQL_EQU_ISO)
     236                 :             :                 {
     237         [ #  # ]:           0 :                     if (a1->bIsIsotopic)
     238                 :             :                     {
     239                 :           0 :                         n1 = a1->nConstitEquIsotopicNumbers;
     240                 :             :                     }
     241                 :             :                 }
     242                 :             :                 else
     243                 :             :                 {
     244                 :           7 :                     n1 = a1->nConstitEquNumbers;
     245                 :             :                 }
     246         [ -  + ]:           7 :                 if (eql2 & EQL_EQU_ISO)
     247                 :             :                 {
     248         [ #  # ]:           0 :                     if (a2->bIsIsotopic)
     249                 :             :                     {
     250                 :           0 :                         n2 = a2->nConstitEquIsotopicNumbers;
     251                 :             :                     }
     252                 :             :                 }
     253                 :             :                 else
     254                 :             :                 {
     255                 :           7 :                     n2 = a2->nConstitEquNumbers;
     256                 :             :                 }
     257                 :             :             }
     258                 :             :         }
     259   [ +  +  +  -  :          23 :     if (n1 && n2 && !memcmp( n1, n2, len * sizeof( n1[0] ) ) && bHasEquString( n1, len ))
             +  -  +  + ]
     260                 :             :     {
     261                 :           3 :         return 1;
     262                 :             :     }
     263                 :             : 
     264                 :          20 :     return 0;
     265                 :             : }
     266                 :             : 
     267                 :             : 
     268                 :             : 
     269                 :             : /****************************************************************************/
     270                 :           0 : int Eql_INChI_Aux_Num( INChI_Aux *a1, int eql1, INChI_Aux *a2, int eql2 )
     271                 :             : {
     272                 :             :     int len;
     273                 :           0 :     AT_NUMB *n1 = NULL, *n2 = NULL;
     274   [ #  #  #  # ]:           0 :     if (!a1 || !a2)
     275                 :             :     {
     276                 :           0 :         return 0;
     277                 :             :     }
     278   [ #  #  #  #  :           0 :     if (( len = a1->nNumberOfAtoms ) <= 0 || len != a2->nNumberOfAtoms || a1->bDeleted || a2->bDeleted)
             #  #  #  # ]
     279                 :             :     {
     280                 :           0 :         return 0;
     281                 :             :     }
     282   [ #  #  #  # ]:           0 :     if ((( eql1 & EQL_NUM_ISO ) && !a1->bIsIsotopic) ||
     283   [ #  #  #  # ]:           0 :         (( eql2 & EQL_NUM_ISO ) && !a2->bIsIsotopic)) /* djb-rwth: addressing LLVM warnings */
     284                 :             :     {
     285                 :           0 :         return 0;
     286                 :             :     }
     287                 :             : 
     288   [ #  #  #  #  :           0 :     switch (eql1)
                      # ]
     289                 :             :     {
     290                 :           0 :         case EQL_NUM:
     291                 :           0 :             n1 = a1->nOrigAtNosInCanonOrd;
     292                 :           0 :             break;
     293                 :           0 :         case EQL_NUM_ISO:
     294                 :           0 :             n1 = a1->nIsotopicOrigAtNosInCanonOrd;
     295                 :           0 :             break;
     296                 :           0 :         case EQL_NUM_INV:
     297                 :           0 :             n1 = a1->nOrigAtNosInCanonOrdInv;
     298                 :           0 :             break;
     299                 :           0 :         case ( EQL_NUM_INV | EQL_NUM_ISO ):
     300                 :           0 :             n1 = a1->nIsotopicOrigAtNosInCanonOrdInv;
     301                 :           0 :             break;
     302                 :           0 :         default:
     303                 :           0 :             return 0;
     304                 :             :     }
     305                 :             : 
     306   [ #  #  #  #  :           0 :     switch (eql2)
                      # ]
     307                 :             :     {
     308                 :           0 :         case EQL_NUM:
     309                 :           0 :             n2 = a2->nOrigAtNosInCanonOrd;
     310                 :           0 :             break;
     311                 :           0 :         case EQL_NUM_ISO:
     312                 :           0 :             n2 = a2->nIsotopicOrigAtNosInCanonOrd;
     313                 :           0 :             break;
     314                 :           0 :         case EQL_NUM_INV:
     315                 :           0 :             n2 = a2->nOrigAtNosInCanonOrdInv;
     316                 :           0 :             break;
     317                 :           0 :         case ( EQL_NUM_INV | EQL_NUM_ISO ):
     318                 :           0 :             n2 = a2->nIsotopicOrigAtNosInCanonOrdInv;
     319                 :           0 :             break;
     320                 :           0 :         default:
     321                 :           0 :             return 0;
     322                 :             :     }
     323                 :             : 
     324   [ #  #  #  #  :           0 :     if (n1 && n2 && !memcmp( n1, n2, len * sizeof( n1[0] ) ))
                   #  # ]
     325                 :             :     {
     326                 :           0 :         return 1;
     327                 :             :     }
     328                 :             : 
     329                 :           0 :     return 0;
     330                 :             : }
     331                 :             : 
     332                 :             : 
     333                 :             : /****************************************************************************/
     334                 :         185 : int bHasOrigInfo( ORIG_INFO *OrigInfo, int num_atoms )
     335                 :             : {
     336                 :         185 :     int i, bFound = 0;
     337   [ +  -  +  - ]:         185 :     if (OrigInfo && num_atoms > 0)
     338                 :             :     {
     339   [ +  +  +  + ]:        1054 :         for (i = 0; !bFound && i < num_atoms; i++)
     340                 :             :         {
     341                 :         869 :             bFound |= ( 0 != OrigInfo[i].cCharge ) ||
     342   [ +  +  +  - ]:        1726 :                 ( 0 != OrigInfo[i].cRadical ) ||
     343         [ +  + ]:         857 :                 ( 0 != OrigInfo[i].cUnusualValence );
     344                 :             :         }
     345                 :             :     }
     346                 :             : 
     347                 :         185 :     return bFound;
     348                 :             : }
     349                 :             : 
     350                 :             : 
     351                 :             : /****************************************************************************/
     352                 :          32 : int EqlOrigInfo( INChI_Aux *a1, INChI_Aux *a2 )
     353                 :             : {
     354   [ +  +  +  +  :          24 :     int ret = a1 && a2 && a1->nNumberOfAtoms == a2->nNumberOfAtoms &&
                   +  + ]
     355   [ +  +  +  - ]:          58 :         bHasOrigInfo( a1->OrigInfo, a1->nNumberOfAtoms ) && a2->OrigInfo &&
     356         [ -  + ]:           2 :         !memcmp( a1->OrigInfo, a2->OrigInfo, a1->nNumberOfAtoms * sizeof( a1->OrigInfo[0] ) );
     357                 :             : 
     358                 :          32 :     return ret;
     359                 :             : }
     360                 :             : 
     361                 :             : 
     362                 :             : /****************************************************************************/
     363                 :         222 : int bHasEquString( AT_NUMB *LinearCT, int nLenCT )
     364                 :             : {
     365                 :             :     /*  produce output string; */
     366                 :             :     int i, k;
     367         [ +  + ]:         222 :     if (!LinearCT)
     368                 :             :     {
     369                 :           7 :         return 0;
     370                 :             :     }
     371         [ +  + ]:         946 :     for (k = 0; k < nLenCT; k++)
     372                 :             :     {
     373                 :             :         /*  find the first equivalence number */
     374         [ +  + ]:         787 :         if (k != (int) LinearCT[k] - 1)
     375                 :             :         {
     376                 :         731 :             continue;
     377                 :             :         }
     378         [ +  - ]:         112 :         for (i = k; i < nLenCT; i++)
     379                 :             :         {
     380         [ -  + ]:         112 :             if (k != (int) LinearCT[i] - 1)
     381                 :             :             {
     382                 :           0 :                 continue;
     383                 :             :             }
     384         [ +  + ]:         112 :             if (k < i)
     385                 :             :             {
     386                 :          56 :                 return 1;
     387                 :             :             }
     388                 :             :         }
     389                 :             :     }
     390                 :             : 
     391                 :         159 :     return 0;
     392                 :             : }
     393                 :             : 
     394                 :             : 
     395                 :             : /****************************************************************************/
     396                 :         426 : int MakeMult( int mult,
     397                 :             :               const char       *szTailingDelim,
     398                 :             :               INCHI_IOS_STRING *buf,
     399                 :             :               int              nCtMode,
     400                 :             :               int              *bOverflow )
     401                 :             : {
     402                 :             :     char szValue[2048];
     403                 :         426 :     int  len = 0, len_delim, n;
     404                 :             : 
     405   [ +  +  -  + ]:         426 :     if (mult == 1 || *bOverflow)
     406                 :             :     {
     407                 :         387 :         return 0;
     408                 :             :     }
     409         [ -  + ]:          39 :     if (nCtMode & CT_MODE_ABC_NUMBERS)
     410                 :             :     {
     411                 :           0 :         len += MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, mult );
     412                 :             :     }
     413                 :             :     else
     414                 :             :     {
     415                 :          39 :         len += MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, mult );
     416                 :             :     }
     417                 :          39 :     len_delim = (int) strlen( szTailingDelim );
     418                 :             : 
     419         [ +  - ]:          39 :     if (len + len_delim < ( int )sizeof( szValue ))
     420                 :             :     {
     421                 :          39 :         strcpy(szValue + len, szTailingDelim);
     422                 :          39 :         n = inchi_strbuf_printf( buf, "%s", szValue );
     423         [ -  + ]:          39 :         if (-1 == n) *bOverflow |= 1;
     424                 :          39 :         return n;
     425                 :             :         /*
     426                 :             :         len += len_delim;
     427                 :             :         if ( len < nLen_szLinearCT )
     428                 :             :         {
     429                 :             :             strcpy( szLinearCT, szValue );
     430                 :             :             return len;
     431                 :             :         }*/
     432                 :             :     }
     433                 :             : 
     434                 :           0 :     *bOverflow |= 1;
     435                 :             : 
     436                 :           0 :     return 0;
     437                 :             : }
     438                 :             : 
     439                 :             : /**
     440                 :             :  * @brief Adds the number to the string buffer.
     441                 :             :  *
     442                 :             :  * @param number Input number to be added
     443                 :             :  * @param szTailingDelim Pointer to the trailing delimiter string
     444                 :             :  * @param buf Pointer to the output string buffer
     445                 :             :  * @param nCtMode Mode flag for string representation
     446                 :             :  * @param bOverflow Pointer to overflow flag
     447                 :             :  * @return Returns the number of characters added to the buffer
     448                 :             :  */
     449                 :         163 : int MakeNumber_EnhStereo( int number,
     450                 :             :                           const char       *szTailingDelim,
     451                 :             :                           INCHI_IOS_STRING *buf,
     452                 :             :                           int              nCtMode,
     453                 :             :                           int              *bOverflow )
     454                 :             : {
     455                 :             :     char szValue[2048];
     456                 :         163 :     int  len = 0;
     457                 :             :     int len_delim;
     458                 :             :     int n;
     459                 :             : 
     460         [ -  + ]:         163 :     if (*bOverflow)
     461                 :             :     {
     462                 :           0 :         return 0;
     463                 :             :     }
     464         [ -  + ]:         163 :     if (nCtMode & CT_MODE_ABC_NUMBERS)
     465                 :             :     {
     466                 :           0 :         len += MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, number );
     467                 :             :     }
     468                 :             :     else
     469                 :             :     {
     470                 :         163 :         len += MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, number );
     471                 :             :     }
     472                 :         163 :     len_delim = (int) strlen( szTailingDelim );
     473                 :             : 
     474         [ +  - ]:         163 :     if (len + len_delim < ( int )sizeof( szValue ))
     475                 :             :     {
     476                 :         163 :         strcpy(szValue + len, szTailingDelim);
     477                 :         163 :         n = inchi_strbuf_printf( buf, "%s", szValue );
     478         [ -  + ]:         163 :         if (-1 == n) *bOverflow |= 1;
     479                 :         163 :         return n;
     480                 :             :     }
     481                 :             : 
     482                 :           0 :     *bOverflow |= 1;
     483                 :             : 
     484                 :           0 :     return 0;
     485                 :             : }
     486                 :             : 
     487                 :             : 
     488                 :             : /****************************************************************************/
     489                 :             : /**
     490                 :             :  * @brief Adds the delimiter to the string buffer if it is not empty and there is no overflow.
     491                 :             :  *
     492                 :             :  * @param szTailingDelim Pointer to the trailing delimiter string
     493                 :             :  * @param buf Pointer to the output string buffer
     494                 :             :  * @param bOverflow Pointer to overflow flag
     495                 :             :  * @return Returns the number of characters added to the buffer, or 0 if the delimiter is empty or there is an overflow
     496                 :             :  */
     497                 :         613 : int MakeDelim( const char       *szTailingDelim,
     498                 :             :                INCHI_IOS_STRING *buf,
     499                 :             :                int              *bOverflow )
     500                 :             : {
     501                 :             :     int n;
     502   [ +  -  +  -  :         613 :     if (!szTailingDelim || !*szTailingDelim || *bOverflow)
                   -  + ]
     503                 :             :     {
     504                 :           0 :         return 0;
     505                 :             :     }
     506                 :             : 
     507                 :         613 :     n = inchi_strbuf_printf( buf, szTailingDelim );
     508         [ -  + ]:         613 :     if (-1 == n)
     509                 :             :     {
     510                 :           0 :         *bOverflow |= 1;
     511                 :             :     }
     512                 :             : 
     513                 :         613 :     return n;
     514                 :             :     /*
     515                 :             :     len_delim = (int) strlen(szTailingDelim);
     516                 :             :     if ( len_delim < nLen_szLinearCT ) {
     517                 :             :     strcpy( szLinearCT, szTailingDelim );
     518                 :             :     return len_delim;
     519                 :             :     }
     520                 :             :     *bOverflow |= 1;
     521                 :             :     return 0;
     522                 :             :     */
     523                 :             : }
     524                 :             : 
     525                 :             : 
     526                 :             : /****************************************************************************/
     527                 :          35 : int MakeEqStr( const char       *szTailingDelim,
     528                 :             :                int              mult,
     529                 :             :                INCHI_IOS_STRING *buf,
     530                 :             :                int              *bOverflow )
     531                 :             : {
     532                 :          35 :     int  n = 0, n0;
     533                 :             :     char szValue[2048];
     534                 :             : 
     535   [ +  -  +  -  :          35 :     if (!szTailingDelim || !*szTailingDelim || *bOverflow)
                   -  + ]
     536                 :             :     {
     537                 :           0 :         return 0;
     538                 :             :     }
     539                 :             : 
     540                 :          35 :     n0 = buf->nUsedLength;
     541                 :             : 
     542         [ +  + ]:          35 :     if (mult != 1)
     543                 :             :     {
     544                 :           3 :         n = MakeDecNumber( szValue, ( int )sizeof( szValue ), NULL, mult );
     545         [ -  + ]:           3 :         if (-1 == n)
     546                 :             :         {
     547                 :           0 :             *bOverflow |= 1;
     548                 :           0 :             return -1;
     549                 :             :         }
     550                 :             :     }
     551         [ +  + ]:          35 :     if (n > 0)
     552                 :             :     {
     553                 :           3 :         n = inchi_strbuf_printf( buf, "%-s", szValue );
     554         [ -  + ]:           3 :         if (-1 == n) *bOverflow |= 1;
     555                 :             :     }
     556                 :          35 :     n = inchi_strbuf_printf( buf, "%-s", szTailingDelim );
     557         [ -  + ]:          35 :     if (-1 == n)
     558                 :             :     {
     559                 :           0 :         *bOverflow |= 1;
     560                 :             :     }
     561                 :             : 
     562                 :          35 :     return ( buf->nUsedLength - n0 );
     563                 :             : }
     564                 :             : 
     565                 :             : 
     566                 :             : /****************************************************************************
     567                 :             : Prepare InChI atomic numbers substring (connections, for InChI)
     568                 :             :     nCtMode =    0: full
     569                 :             :                 1: censored CT (no orphans)
     570                 :             :                 2: compressed CT (Abs numbers)
     571                 :             : ****************************************************************************/
     572                 :          70 : int MakeCtStringNew( CANON_GLOBALS    *pCG,
     573                 :             :                      AT_NUMB          *LinearCT,
     574                 :             :                      int              nLenCT,
     575                 :             :                      int              bAddDelim,
     576                 :             :                      S_CHAR           *nNum_H,
     577                 :             :                      int              num_atoms,
     578                 :             :                      INCHI_IOS_STRING *strbuf,
     579                 :             :                      int              nCtMode,
     580                 :             :                      int              *bOverflow )
     581                 :             : {
     582                 :             :     /*  produce output string; */
     583                 :          70 :     int nUsedLength0 = 0, nLen = 0, len, i, bOvfl = *bOverflow;
     584                 :             :     char szValue[2048];
     585                 :             :     int   nValue, nDelim, num_H;
     586                 :          70 :     AT_NUMB *nDfsOrderCT = NULL;
     587                 :          70 :     int      bNoNum_H = ( NULL == nNum_H );
     588                 :             :     int      nNumRingClosures;
     589                 :          70 :     int      bAbcNumbers = ( 0 != ( nCtMode & CT_MODE_ABC_NUMBERS ) );
     590                 :          70 :     int      bPredecessors = ( 0 != ( nCtMode & CT_MODE_PREDECESSORS ) );
     591   [ -  +  -  -  :          70 :     int      bCountRingClosures = bAbcNumbers && bPredecessors && ( nCtMode & CT_MODE_ABC_NUM_CLOSURES );
                   -  - ]
     592                 :             : 
     593         [ -  + ]:          70 :     if (nLenCT <= 1)
     594                 :             :     {
     595                 :           0 :         return 0;  /*  no atoms or a single atom: no connection table */
     596                 :             :     }
     597                 :             : 
     598                 :          70 :     nUsedLength0 = strbuf->nUsedLength;
     599                 :             : 
     600                 :             :     /*  make array containing connection string data */
     601         [ -  + ]:          70 :     if (!( nDfsOrderCT = GetDfsOrder4CT( pCG, LinearCT, nLenCT,
     602                 :             :         nNum_H, num_atoms, nCtMode ) ))
     603                 :             :     {
     604                 :           0 :         ( *bOverflow )++;
     605                 :           0 :         return 0;
     606                 :             :     }
     607                 :             : 
     608                 :             :     /*  add connection table string */
     609   [ +  -  -  + ]:          70 :     if (!bOvfl && bAddDelim)
     610                 :             :     {
     611                 :           0 :         inchi_strbuf_printf( strbuf, "," );
     612                 :             :     }
     613                 :             : 
     614         [ +  - ]:          70 :     if (!bOvfl)
     615                 :             :     {
     616                 :          70 :         nNumRingClosures = 0;
     617         [ +  + ]:         727 :         for (i = 0; nDfsOrderCT[i]/* && nLen < nLen_szLinearCT*/; i += 3)
     618                 :             :         {
     619         [ +  - ]:         657 :             nValue = ( nDfsOrderCT[i] > MAX_ATOMS ) ? 0 : nDfsOrderCT[i];
     620         [ -  + ]:         657 :             num_H = nDfsOrderCT[i + 1] ? nDfsOrderCT[i + 1] - 16 : 0;
     621                 :         657 :             nDelim = nDfsOrderCT[i + 2];
     622                 :         657 :             len = 0;
     623                 :             :             /*  delimiter */
     624         [ -  + ]:         657 :             if (bPredecessors)
     625                 :             :             {
     626         [ #  # ]:           0 :                 if (bCountRingClosures)
     627                 :             :                 {
     628   [ #  #  #  #  :           0 :                     if (nDelim == '-' && i > 3 && bNoNum_H)
                   #  # ]
     629                 :             :                     {
     630         [ #  # ]:           0 :                         if (!nNumRingClosures)
     631                 :             :                         {
     632                 :             :                             int j;
     633   [ #  #  #  # ]:           0 :                             for (j = i; nDfsOrderCT[j] && '-' == nDfsOrderCT[j + 2]; j += 3)
     634                 :             :                             {
     635                 :           0 :                                 nNumRingClosures++;
     636                 :             :                             }
     637         [ #  # ]:           0 :                             if (nNumRingClosures)
     638                 :             :                             {
     639                 :           0 :                                 len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nNumRingClosures );
     640                 :             :                             }
     641                 :           0 :                             nNumRingClosures--;
     642                 :             :                         }
     643                 :             :                         else
     644                 :             :                         {
     645                 :           0 :                             nNumRingClosures--;
     646                 :             :                         }
     647                 :             :                     }
     648                 :             :                     else
     649                 :             :                     {
     650                 :           0 :                         nNumRingClosures = 0;
     651                 :             :                     }
     652                 :             :                 }
     653   [ #  #  #  #  :           0 :                 else if (nDelim && !( bAbcNumbers && nDelim == ',' ))
                   #  # ]
     654                 :             :                 {
     655   [ #  #  #  # ]:           0 :                     if (nNum_H || i > 3)
     656                 :             :                     {
     657                 :           0 :                         szValue[len++] = nDelim;
     658                 :             :                     }
     659                 :             :                 }
     660                 :             :             }
     661                 :             :             else
     662                 :             :             {
     663   [ +  +  -  +  :         657 :                 if (nDelim && !( bAbcNumbers && nDelim == '-' ))
                   -  - ]
     664                 :             :                 {
     665                 :         587 :                     szValue[len++] = nDelim;
     666                 :             :                 }
     667                 :             :             }
     668         [ -  + ]:         657 :             if (bAbcNumbers)
     669                 :             :             {
     670   [ #  #  #  # ]:           0 :                 if (nValue || i)
     671                 :             :                 {
     672                 :             :                     /* the 1st value may be zero in case of presdecessor list */
     673                 :           0 :                     len += MakeAbcNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nValue );
     674                 :             :                 }
     675         [ #  # ]:           0 :                 if (num_H)
     676                 :             :                 {
     677                 :           0 :                     len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, num_H );
     678                 :             :                 }
     679                 :             :             }
     680                 :             :             else
     681                 :             :             {
     682   [ -  +  -  - ]:         657 :                 if (nValue || i)
     683                 :             :                 {
     684                 :             :                     /* the 1st value may be zero in case of presdecessor list */
     685                 :         657 :                     len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nValue );
     686                 :             :                 }
     687         [ -  + ]:         657 :                 if (num_H)
     688                 :             :                 {
     689                 :           0 :                     szValue[len] = 'H';
     690                 :           0 :                     len++;
     691         [ #  # ]:           0 :                     if (num_H > 1)
     692                 :             :                     {
     693                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, num_H );
     694                 :             :                     }
     695                 :             :                 }
     696                 :             :             }
     697                 :             : 
     698         [ +  - ]:         657 :             if (len > 0)
     699                 :             :             {
     700                 :         657 :                 inchi_strbuf_printf( strbuf, "%s", szValue );
     701                 :             :             }
     702                 :             :         }
     703                 :             :     }
     704                 :             : 
     705                 :          70 :     *bOverflow |= bOvfl;
     706         [ +  - ]:          70 :     if (nDfsOrderCT)
     707                 :             :     {
     708         [ +  - ]:          70 :         inchi_free( nDfsOrderCT );
     709                 :             :     }
     710                 :             : 
     711                 :          70 :     nLen = strbuf->nUsedLength - nUsedLength0;
     712                 :             : 
     713                 :          70 :     return nLen;
     714                 :             : }
     715                 :             : 
     716                 :             : 
     717                 :             : /****************************************************************************
     718                 :             :     Prepare InChI atomic numbers substring (for AuxInfo)
     719                 :             : 
     720                 :             :     nCtMode =    0: full
     721                 :             :                 1: censored CT (no orphans)
     722                 :             :                 2: compressed CT (Abs numbers)
     723                 :             : ****************************************************************************/
     724                 :         163 : int MakeCtStringOld( AT_NUMB          *LinearCT,
     725                 :             :                      int              nLenCT,
     726                 :             :                      int              bAddDelim,
     727                 :             :                      INCHI_IOS_STRING *strbuf,
     728                 :             :                      int              nCtMode,
     729                 :             :                      int              *bOverflow )
     730                 :             : {
     731                 :             :     /*  produce output string; */
     732                 :         163 :     int nUsedLength0 = 0, nLen = 0, len, i, bLessThanPrev, bOvfl = *bOverflow;
     733                 :         163 :     AT_NUMB nMax = 0;
     734                 :             :     char szValue[2048];
     735                 :         163 :     int   nValue, bNext = 0;
     736                 :             : 
     737                 :         163 :     nUsedLength0 = strbuf->nUsedLength;
     738                 :             : 
     739                 :             :     /*  add connection table string */
     740   [ +  -  +  -  :         163 :     if (!( nCtMode & CT_MODE_ABC_NUMBERS ) && !bOvfl && bAddDelim)
                   -  + ]
     741                 :             :     {
     742                 :           0 :         inchi_strbuf_printf( strbuf, "," );
     743                 :             :                                         /*
     744                 :             :                                         if ( nLen_szLinearCT > 1 ) {
     745                 :             :                                             strcpy( szLinearCT, "," );
     746                 :             :                                             nLen ++;
     747                 :             :                                         } else {
     748                 :             :                                             bOvfl = 1;
     749                 :             :                                         }*/
     750                 :             :     }
     751         [ +  - ]:         163 :     if (!bOvfl)
     752                 :             :     {
     753         [ +  + ]:         983 :         for (i = 0; i < nLenCT/* && nLen < nLen_szLinearCT*/; i++)
     754                 :             :         {
     755                 :         820 :             bLessThanPrev = 0;
     756   [ -  +  -  - ]:         820 :             if (!( nCtMode & CT_MODE_NO_ORPHANS ) || ( ( bLessThanPrev = LinearCT[i] < nMax ) ||
     757   [ #  #  #  # ]:           0 :                 (i + 1 < nLenCT && LinearCT[i + 1] < ( nMax = LinearCT[i] )) )) /* djb-rwth: addressing LLVM warning */
     758                 :             :             {
     759                 :         820 :                 nValue = LinearCT[i];
     760         [ -  + ]:         820 :                 if (nCtMode & CT_MODE_ABC_NUMBERS)
     761                 :             :                 {
     762   [ #  #  #  # ]:           0 :                     len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), ( !bNext && bAddDelim ) ? ITEM_DELIMETER : NULL, nValue );
     763                 :             :                 }
     764                 :             :                 else
     765                 :             :                 {
     766         [ -  + ]:         820 :                     if (nCtMode & CT_MODE_NO_ORPHANS)
     767                 :             :                     {
     768                 :             :                         /*  censored CT */
     769                 :             :                         /*  output '-' as a delimiter to show a bonding for decimal output of the connection table */
     770         [ #  # ]:           0 :                         len = MakeDecNumber( szValue, ( int )sizeof( szValue ), bLessThanPrev ? "-" : ITEM_DELIMETER, nValue );
     771                 :             :                     }
     772                 :             :                     else
     773                 :             :                     {
     774         [ +  + ]:         820 :                         len = MakeDecNumber( szValue, ( int )sizeof( szValue ), i ? ITEM_DELIMETER : NULL, nValue );
     775                 :             :                     }
     776                 :             :                 }
     777         [ +  - ]:         820 :                 if (len > 0)
     778                 :             :                 {
     779                 :         820 :                     inchi_strbuf_printf( strbuf, "%s", szValue );
     780                 :         820 :                     bNext++;
     781                 :             :                 }
     782                 :             : 
     783                 :             :                 /*if ( 0 <= len && nLen+len < nLen_szLinearCT) {
     784                 :             :                     if ( len ) {
     785                 :             :                         strcpy( szLinearCT+nLen, szValue );
     786                 :             :                         nLen += len;
     787                 :             :                         bNext ++;
     788                 :             :                     }
     789                 :             :                     } else {
     790                 :             :                         bOvfl = 1;
     791                 :             :                         break;
     792                 :             :                     }*/
     793                 :             :             }
     794                 :             :         }
     795                 :             :     }
     796                 :         163 :     *bOverflow |= bOvfl;
     797                 :             : 
     798                 :         163 :     nLen = strbuf->nUsedLength - nUsedLength0;
     799                 :             : 
     800                 :         163 :     return nLen;
     801                 :             : }
     802                 :             : 
     803                 :             : 
     804                 :             : /****************************************************************************
     805                 :             :     MakeHString( ... )
     806                 :             : 
     807                 :             :     nCtMode =   0: decimal
     808                 :             :                 2: compressed CT (Abc numbers)
     809                 :             : ****************************************************************************/
     810                 :          89 : int MakeHString( int              bAddDelim,
     811                 :             :                  S_CHAR           *LinearCT,
     812                 :             :                  int              nLenCT,
     813                 :             :                  INCHI_IOS_STRING *strbuf,
     814                 :             :                  int              nCtMode,
     815                 :             :                  int              *bOverflow )
     816                 :             : {
     817                 :             : #define INIT_MIN_NUM_H (-4)
     818                 :             : #define INIT_MAX_NUM_H 16
     819                 :             : #define INIT_LEN_NUM_H (INIT_MAX_NUM_H - INIT_MIN_NUM_H + 1)
     820                 :             : 
     821                 :             :     /*  produce output string; */
     822                 :          89 :     int nUsedLength0 = 0, nLen = 0, len, i, iFirst, nVal, bOvfl = *bOverflow;
     823                 :             :     char szValue[2048];
     824                 :             :     const char *pH;
     825                 :          89 :     int  bNext = 0;
     826                 :             : 
     827                 :          89 :     nUsedLength0 = strbuf->nUsedLength;
     828                 :             : 
     829                 :             :     /*  add connection table string */
     830   [ +  -  +  -  :          89 :     if (!( nCtMode & CT_MODE_ABC_NUMBERS ) && !bOvfl && bAddDelim)
                   -  + ]
     831                 :             :     {
     832                 :           0 :         inchi_strbuf_printf( strbuf, "," );
     833                 :             :                             /*if ( nLen_szLinearCT > 1 ) {
     834                 :             :                                 strcpy( szLinearCT, "," );
     835                 :             :                                 nLen ++;
     836                 :             :                                 } else {
     837                 :             :                                     bOvfl = 1;
     838                 :             :                             }*/
     839                 :             :     }
     840   [ +  -  +  -  :          89 :     if (!bOvfl && 0 < nLenCT && LinearCT)
                   +  - ]
     841                 :             :     {
     842         [ +  - ]:          89 :         if (nCtMode & CT_MODE_EQL_H_TOGETHER)
     843                 :             :         {
     844                 :          89 :             int  curMinH = INIT_MIN_NUM_H;
     845                 :          89 :             int  curMaxH = INIT_MAX_NUM_H;
     846                 :          89 :             int  curLenH = INIT_LEN_NUM_H;
     847                 :             :             int  nInitNumH[INIT_LEN_NUM_H];
     848                 :          89 :             int *nNumH = nInitNumH;
     849                 :             :             int  numAt, curNumH;
     850                 :             :             int      j, bOutOfRange, tot_num_no_H;
     851                 :             :             /* count atoms H */
     852                 :             :             do
     853                 :             :             {
     854                 :          89 :                 bOutOfRange = 0;
     855                 :          89 :                 tot_num_no_H = 0; /* number of atoms that have no H */
     856                 :          89 :                 memset( nNumH, 0, curLenH * sizeof( nNumH[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     857         [ +  + ]:         729 :                 for (i = 0; i < nLenCT; i++)
     858                 :             :                 {
     859                 :         640 :                     curNumH = LinearCT[i];
     860         [ -  + ]:         640 :                     if (curNumH < curMinH)
     861                 :             :                     {
     862                 :           0 :                         curMinH = curNumH;
     863                 :           0 :                         bOutOfRange++;
     864                 :             :                     }
     865                 :             :                     else
     866                 :             :                     {
     867         [ -  + ]:         640 :                         if (curNumH > curMaxH)
     868                 :             :                         {
     869                 :           0 :                             curMaxH = curNumH;
     870                 :           0 :                             bOutOfRange++;
     871                 :             :                         }
     872                 :             :                         else
     873         [ +  - ]:         640 :                             if (!bOutOfRange)
     874                 :             :                             {
     875                 :         640 :                                 nNumH[curNumH - curMinH] ++;
     876                 :             :                             }
     877                 :             :                     }
     878                 :         640 :                     tot_num_no_H += !curNumH;
     879                 :             :                 }
     880         [ +  + ]:          89 :                 if (tot_num_no_H == nLenCT)
     881                 :             :                 {
     882                 :           5 :                     return nLen; /* empty string */
     883                 :             :                 }
     884         [ -  + ]:          84 :                 if (bOutOfRange)
     885                 :             :                 {
     886                 :             :                     /* for debug only */
     887         [ #  # ]:           0 :                     if (nNumH != nInitNumH)
     888                 :             :                     {
     889                 :           0 :                         *bOverflow |= 1;
     890         [ #  # ]:           0 :                         inchi_free( nNumH );
     891                 :           0 :                         return nLen;
     892                 :             :                     }
     893                 :             :                     /* end debug */
     894                 :           0 :                     curLenH = curMaxH - curMinH + 1;
     895                 :           0 :                     nNumH = (int*) inchi_malloc( curLenH * sizeof( nNumH[0] ) );
     896         [ #  # ]:           0 :                     if (!nNumH)
     897                 :             :                     {
     898                 :           0 :                         *bOverflow |= 1;
     899                 :           0 :                         return nLen;
     900                 :             :                     }
     901                 :             :                 }
     902                 :             :             }
     903         [ -  + ]:          84 :             while (bOutOfRange); /* the loop may be executed 1 or 2 times only */
     904                 :             : 
     905         [ +  + ]:        1848 :             for (curNumH = curMinH; curNumH <= curMaxH; curNumH++)
     906                 :             :             {
     907                 :        1764 :                 numAt = nNumH[curNumH - curMinH]; /* number of atoms that have curNumH atoms H */
     908   [ +  +  +  + ]:        1764 :                 if (!numAt || !curNumH)
     909                 :             :                 {
     910                 :        1595 :                     continue; /* no atom has this number of H or number of H = 0 */
     911                 :             :                 }
     912                 :         169 :                 j = 0;
     913   [ +  +  +  + ]:         726 :                 while (j < nLenCT && numAt)
     914                 :             :                 {
     915         [ +  + ]:         557 :                     if (curNumH == LinearCT[j])
     916                 :             :                     {
     917                 :         207 :                         iFirst = ++j;
     918                 :         207 :                         numAt--;
     919   [ +  +  +  +  :         491 :                         for (; j < nLenCT && curNumH == LinearCT[j] && numAt; j++)
                   +  - ]
     920                 :             :                         {
     921                 :         284 :                             numAt--;
     922                 :             :                         }
     923         [ -  + ]:         207 :                         if (nCtMode & CT_MODE_ABC_NUMBERS)
     924                 :             :                         {
     925                 :           0 :                             len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, iFirst );
     926                 :             :                         }
     927                 :             :                         else
     928                 :             :                         {
     929         [ +  + ]:         207 :                             len = MakeDecNumber( szValue, ( int )sizeof( szValue ), bNext ? ITEM_DELIMETER : NULL, iFirst );
     930                 :         207 :                             bNext++; /* add a delimiter (comma) before all except the first */
     931                 :             :                         }
     932         [ +  + ]:         207 :                         if (iFirst < j)
     933                 :             :                         {
     934                 :             :                             /* output last canonical number */
     935         [ -  + ]:         112 :                             if (nCtMode & CT_MODE_ABC_NUMBERS)
     936                 :             :                             {
     937                 :           0 :                                 len += MakeAbcNumber( szValue + len, ( int )sizeof( szValue ), NULL, j );
     938                 :             :                             }
     939                 :             :                             else
     940                 :             :                             {
     941                 :         112 :                                 len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, "-", j );
     942                 :             :                             }
     943                 :             :                         }
     944   [ +  +  -  + ]:         207 :                         if (!numAt || ( nCtMode & CT_MODE_ABC_NUMBERS ))
     945                 :             :                         {
     946                 :             :                             /* add number of H */
     947                 :             :                             /* output number of H */
     948                 :         169 :                             nVal = curNumH;
     949         [ -  + ]:         169 :                             if (nCtMode & CT_MODE_ABC_NUMBERS)
     950                 :             :                             {
     951                 :           0 :                                 len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nVal );
     952                 :             :                             }
     953                 :             :                             else
     954                 :             :                             {
     955         [ +  - ]:         169 :                                 pH = nVal > 0 ? "H" : "h";
     956                 :         169 :                                 nVal = abs( nVal );
     957         [ +  + ]:         169 :                                 if (nVal > 1)
     958                 :             :                                 {
     959                 :         106 :                                     len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, pH, nVal );
     960                 :             :                                 }
     961                 :             :                                 else
     962                 :             :                                 {
     963                 :          63 :                                     strcpy(szValue + len, pH);
     964                 :          63 :                                     len++;
     965                 :             :                                 }
     966                 :             :                             }
     967                 :             :                         }
     968                 :             :                         /* add to the output */
     969         [ +  - ]:         207 :                         if (len > 0)
     970                 :             :                         {
     971                 :         207 :                             inchi_strbuf_printf( strbuf, "%-s", szValue );
     972                 :         207 :                             bNext++;
     973                 :             :                         }
     974                 :             :                         /*
     975                 :             :                         if ( 0 <= len && nLen+len < nLen_szLinearCT ) {
     976                 :             :                             if ( len ) {
     977                 :             :                                 strcpy( szLinearCT+nLen, szValue );
     978                 :             :                                 nLen += len;
     979                 :             :                                 bNext ++;
     980                 :             :                             }
     981                 :             :                         } else {
     982                 :             :                             bOvfl = 1;
     983                 :             :                             break;
     984                 :             :                         }*/
     985                 :             :                     }
     986                 :             :                     else
     987                 :             :                     {
     988                 :         350 :                         j++;
     989                 :             :                     }
     990                 :             :                 }
     991                 :             :             }
     992         [ -  + ]:          84 :             if (nNumH != nInitNumH)
     993                 :             :             {
     994         [ #  # ]:           0 :                 inchi_free( nNumH );
     995                 :             :             }
     996                 :             :         }
     997                 :             :         else
     998                 :             :         {
     999                 :           0 :             iFirst = 0;
    1000         [ #  # ]:           0 :             for (i = iFirst + 1; i <= nLenCT/* && nLen < nLen_szLinearCT*/; i++)
    1001                 :             :             {
    1002   [ #  #  #  # ]:           0 :                 if (i < nLenCT && LinearCT[i] == LinearCT[iFirst])
    1003                 :             :                 {
    1004                 :           0 :                     continue;
    1005                 :             :                 }
    1006                 :             :                 /* output identical values located at i = iFirst..i-1 */
    1007         [ #  # ]:           0 :                 if (LinearCT[iFirst])
    1008                 :             :                 { /* output only non-zero values */
    1009                 :             :                   /* first canonical number */
    1010                 :           0 :                     nVal = LinearCT[iFirst];
    1011                 :           0 :                     iFirst++;
    1012         [ #  # ]:           0 :                     if (nCtMode & CT_MODE_ABC_NUMBERS)
    1013                 :             :                     {
    1014                 :           0 :                         len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, iFirst );
    1015                 :             :                     }
    1016                 :             :                     else
    1017                 :             :                     {
    1018         [ #  # ]:           0 :                         len = MakeDecNumber( szValue, ( int )sizeof( szValue ), bNext ? ITEM_DELIMETER : NULL, iFirst );
    1019                 :             :                     }
    1020         [ #  # ]:           0 :                     if (iFirst < i)
    1021                 :             :                     {
    1022                 :             :                         /* output last canonical number */
    1023         [ #  # ]:           0 :                         if (nCtMode & CT_MODE_ABC_NUMBERS)
    1024                 :             :                         {
    1025                 :           0 :                             len += MakeAbcNumber( szValue + len, ( int )sizeof( szValue ), NULL, i );
    1026                 :             :                         }
    1027                 :             :                         else
    1028                 :             :                         {
    1029                 :           0 :                             len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, "-", i );
    1030                 :             :                         }
    1031                 :             :                     }
    1032                 :             :                     /* output number of H */
    1033         [ #  # ]:           0 :                     if (nCtMode & CT_MODE_ABC_NUMBERS)
    1034                 :             :                     {
    1035                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, nVal );
    1036                 :             :                     }
    1037                 :             :                     else
    1038                 :             :                     {
    1039         [ #  # ]:           0 :                         pH = nVal > 0 ? "H" : "h";
    1040                 :           0 :                         nVal = abs( nVal );
    1041         [ #  # ]:           0 :                         if (nVal > 1)
    1042                 :             :                         {
    1043                 :           0 :                             len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, pH, nVal );
    1044                 :             :                         }
    1045                 :             :                         else
    1046                 :             :                         {
    1047                 :           0 :                             strcpy(szValue + len, pH); /* djb-rwth: GCC 14 false positive */
    1048                 :           0 :                             len++;
    1049                 :             :                         }
    1050                 :             :                     }
    1051         [ #  # ]:           0 :                     if (0 <= len/* && nLen+len < nLen_szLinearCT*/)
    1052                 :             :                     {
    1053         [ #  # ]:           0 :                         if (len)
    1054                 :             :                         {
    1055                 :           0 :                             inchi_strbuf_printf( strbuf, "%-s", szValue );
    1056                 :             :                                         /*strcpy( szLinearCT+nLen, szValue );
    1057                 :             :                                         nLen += len;*/
    1058                 :           0 :                             bNext++;
    1059                 :             :                         }
    1060                 :             :                     }
    1061                 :             :                     else
    1062                 :             :                     {
    1063                 :           0 :                         bOvfl = 1;
    1064                 :           0 :                         break;
    1065                 :             :                     }
    1066                 :             :                 }
    1067                 :           0 :                 iFirst = i;
    1068                 :             :             }
    1069                 :             :         }
    1070                 :             :     }
    1071                 :          84 :     *bOverflow |= bOvfl;
    1072                 :             : 
    1073                 :          84 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1074                 :          84 :     return nLen;
    1075                 :             : 
    1076                 :             : #undef INIT_MIN_NUM_H
    1077                 :             : #undef INIT_MAX_NUM_H
    1078                 :             : #undef INIT_LEN_NUM_H
    1079                 :             : }
    1080                 :             : 
    1081                 :             : 
    1082                 :             : /****************************************************************************
    1083                 :             :     Prepare InChI atomic numbers substring
    1084                 :             : 
    1085                 :             :     nCtMode =    0: full
    1086                 :             :                 1: censored CT (no orphans, that CT should
    1087                 :             :                    have only atoms with neighbors)
    1088                 :             :                 2: compressed CT (Abc numbers)
    1089                 :             :  ****************************************************************************/
    1090                 :         163 : int MakeCtString( CANON_GLOBALS    *pCG,
    1091                 :             :                   AT_NUMB          *LinearCT,
    1092                 :             :                   int              nLenCT,
    1093                 :             :                   int              bAddDelim,
    1094                 :             :                   S_CHAR           *nNum_H,
    1095                 :             :                   int              num_atoms,
    1096                 :             :                   INCHI_IOS_STRING *strbuf,
    1097                 :             :                   int              nCtMode,
    1098                 :             :                   int              *bOverflow )
    1099                 :             : {
    1100                 :             : 
    1101   [ -  +  -  - ]:         163 :     if (!nNum_H || !( nCtMode & CT_MODE_NO_ORPHANS ))
    1102                 :             :     {
    1103                 :         163 :         return MakeCtStringOld( LinearCT, nLenCT, bAddDelim, strbuf, nCtMode, bOverflow );
    1104                 :             :     }
    1105                 :             :     else
    1106                 :             :     {
    1107                 :           0 :         return MakeCtStringNew( pCG, LinearCT, nLenCT, bAddDelim, nNum_H,
    1108                 :             :                                 num_atoms, strbuf, nCtMode, bOverflow );
    1109                 :             :     }
    1110                 :             : }
    1111                 :             : 
    1112                 :             : 
    1113                 :             : /****************************************************************************
    1114                 :             :     MakeTautString(  )
    1115                 :             : 
    1116                 :             :     nCtMode =    0: full: decimal-only, with parentheses around t-groups
    1117                 :             :                 2: compressed CT:    do not add comma before the output string if bAddDelim != 0
    1118                 :             :                                     do not add parentheses around t-groups
    1119                 :             :                                     atom canon numbers an Abc
    1120                 :             :     LinearCT format:
    1121                 :             :         N      = number of tautomeric groups
    1122                 :             :         n      = number of endpoints + 1 in a tautomeric group #1
    1123                 :             :         next INCHI_T_NUM_MOVABLE lines (any after the first non-zero):
    1124                 :             :         h      = number of hydrogen atoms in the tautomeric group
    1125                 :             :         m      = number of negative charges
    1126                 :             :         ...    (the rest of the INCHI_T_NUM_MOVABLE has not been established, ignore them)
    1127                 :             :         c(1)   = canonical number of the first atom in the t-group
    1128                 :             :         ...
    1129                 :             :         c(n-1) = canonical number of the last atom in the t-group
    1130                 :             : 
    1131                 :             : ****************************************************************************/
    1132                 :          89 : int MakeTautString( AT_NUMB          *LinearCT,
    1133                 :             :                     int              nLenCT,
    1134                 :             :                     int              bAddDelim,
    1135                 :             :                     INCHI_IOS_STRING *strbuf,
    1136                 :             :                     int              nCtMode,
    1137                 :             :                     int              *bOverflow )
    1138                 :             : {
    1139                 :             :     /*  produce output string; */
    1140                 :          89 :     int nUsedLength0 = 0, nLen = 0, len, i, bOvfl = *bOverflow;
    1141                 :             :     char szValue[2048];
    1142                 :             :     const char *p;
    1143                 :             :     int   nValue, nGroupLen, iGroupOutputCount, bCompressed;
    1144                 :             :     /*  make tautomer string */
    1145   [ +  +  +  -  :          89 :     if (!nLenCT || !LinearCT || !*LinearCT)
                   +  + ]
    1146                 :             :     {
    1147                 :          83 :         return nLen;
    1148                 :             :     }
    1149                 :             : 
    1150                 :           6 :     nUsedLength0 = strbuf->nUsedLength;
    1151                 :             : 
    1152                 :           6 :     bCompressed = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1153   [ +  -  +  -  :           6 :     if (!bCompressed && !bOvfl && bAddDelim)
                   +  + ]
    1154                 :             :     {
    1155                 :           1 :         inchi_strbuf_printf( strbuf, "%s", COMMA_EXTRA_SPACE );
    1156                 :             :         /*if ( nLen_szLinearCT > 1+LEN_EXTRA_SPACE ) {
    1157                 :             :             strcpy( szLinearCT, COMMA_EXTRA_SPACE);
    1158                 :             :             nLen += 1+LEN_EXTRA_SPACE;
    1159                 :             :         } else {
    1160                 :             :             bOvfl = 1;
    1161                 :             :         }*/
    1162                 :             :     }
    1163                 :           6 :     LinearCT++; /*  bypass number of tautomeric groups */
    1164                 :           6 :     nLenCT--;
    1165                 :             : 
    1166         [ +  - ]:           6 :     if (!bOvfl)
    1167                 :             :     {
    1168         [ +  + ]:          55 :         for (i = nGroupLen = iGroupOutputCount = 0; i < nLenCT/* && nLen < nLen_szLinearCT*/; i++)
    1169                 :             :         {
    1170                 :          49 :             nValue = (int) LinearCT[i];
    1171         [ +  + ]:          49 :             if (nGroupLen == iGroupOutputCount)
    1172                 :             :             {
    1173                 :           9 :                 nGroupLen = nValue;
    1174                 :           9 :                 iGroupOutputCount = 0;
    1175                 :             :                 /* group delimiter (uncompressed) */
    1176         [ +  - ]:           9 :                 if (!bCompressed)
    1177                 :             :                 {
    1178         [ +  + ]:           9 :                     if (!i)
    1179                 :             :                     {
    1180                 :           6 :                         strcpy( szValue, "(" );
    1181                 :           6 :                         len = 1;
    1182                 :             :                     }
    1183                 :             :                     else
    1184                 :             :                     {
    1185                 :           3 :                         strcpy( szValue, ")(" );
    1186                 :           3 :                         len = 2;
    1187                 :             :                     }
    1188                 :             :                 }
    1189                 :             :                 else
    1190                 :             :                 {
    1191                 :           0 :                     len = 0;
    1192                 :             :                 }
    1193                 :             :             }
    1194                 :             :             else
    1195                 :             :             {
    1196   [ -  +  -  - ]:          40 :                 if (bCompressed && iGroupOutputCount >= INCHI_T_NUM_MOVABLE)
    1197                 :             :                 {
    1198                 :             :                     /*  compressed canon number in Abc */
    1199                 :           0 :                     len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, nValue );
    1200                 :           0 :                     iGroupOutputCount++;
    1201                 :             :                 }
    1202                 :             :                 else
    1203                 :             :                 {
    1204                 :             :                     /*  always output number of hydrogen atoms as a decimal */
    1205                 :             :                     /*  output leading space if: */
    1206                 :             :                     /*  (a) this is the first output value in compressed mode (i==1 && bCompressed) */
    1207                 :             :                     /*  (b) this is not the first output value in non-compressed mode ( iGroupOutputCount && !bCompressed) */
    1208         [ -  + ]:          40 :                     if (bCompressed)
    1209                 :             :                     {
    1210                 :           0 :                         p = NULL;
    1211                 :           0 :                         len = 0;
    1212   [ #  #  #  # ]:           0 :                         switch (iGroupOutputCount)
    1213                 :             :                         {
    1214                 :           0 :                             case 0:
    1215         [ #  # ]:           0 :                                 len = MakeDecNumber( szValue, ( int )sizeof( szValue ), ( i == 1 ) ? ITEM_DELIMETER : NULL, nValue );
    1216                 :           0 :                                 break;
    1217                 :           0 :                             case 1:
    1218                 :           0 :                                 p = "-";
    1219                 :           0 :                                 break;
    1220                 :           0 :                             case 2:
    1221                 :           0 :                                 p = "+";
    1222                 :           0 :                                 break;
    1223                 :             :                         }
    1224         [ #  # ]:           0 :                         if (p)
    1225                 :             :                         {
    1226      [ #  #  # ]:           0 :                             switch (nValue)
    1227                 :             :                             {
    1228                 :           0 :                                 case 0:
    1229                 :           0 :                                     len = 0;
    1230                 :           0 :                                     break;
    1231                 :           0 :                                 case 1:
    1232                 :           0 :                                     strcpy(szValue, p);
    1233                 :           0 :                                     len = (int) strlen( szValue );
    1234                 :           0 :                                     break;
    1235                 :           0 :                                 default:
    1236                 :           0 :                                     len = MakeDecNumber( szValue, ( int )sizeof( szValue ), p, nValue );
    1237                 :           0 :                                     break;
    1238                 :             :                             }
    1239                 :             :                         }
    1240                 :             :                     }
    1241                 :             :                     else
    1242                 :             :                     {
    1243         [ +  + ]:          40 :                         if (iGroupOutputCount >= INCHI_T_NUM_MOVABLE)
    1244                 :             :                         {
    1245                 :             :                             /*  canonical number of the atom in the tautomeric group */
    1246                 :          22 :                             len = MakeDecNumber( szValue, ( int )sizeof( szValue ), ITEM_DELIMETER, nValue );
    1247                 :             :                         }
    1248                 :             :                         else
    1249                 :             :                         {
    1250                 :          18 :                             p = NULL;
    1251                 :          18 :                             len = 0;
    1252         [ +  + ]:          18 :                             if (nValue)
    1253                 :             :                             {
    1254   [ +  -  -  - ]:           9 :                                 switch (iGroupOutputCount)
    1255                 :             :                                 {
    1256                 :           9 :                                     case 0:
    1257                 :           9 :                                         p = "H";
    1258                 :           9 :                                         break;
    1259                 :           0 :                                     case 1:
    1260                 :           0 :                                         p = "-";
    1261                 :           0 :                                         break;
    1262                 :           0 :                                     case 2:
    1263                 :           0 :                                         p = "+";
    1264                 :           0 :                                         break;
    1265                 :             :                                 }
    1266         [ +  - ]:           9 :                                 if (p)
    1267                 :             :                                 {
    1268                 :             :                                     /*  number of hydrogens */
    1269         [ +  + ]:           9 :                                     if (nValue == 1)
    1270                 :             :                                     {
    1271                 :           7 :                                         strcpy(szValue, p);
    1272                 :           7 :                                         len = (int) strlen( szValue );
    1273                 :             :                                     }
    1274                 :             :                                     else
    1275                 :             :                                     {
    1276                 :           2 :                                         len = MakeDecNumber( szValue, ( int )sizeof( szValue ), p, nValue );
    1277                 :             :                                     }
    1278                 :             :                                 }
    1279                 :             :                             }
    1280                 :             :                         }
    1281                 :             :                     }
    1282                 :          40 :                     iGroupOutputCount++;
    1283                 :             :                 }
    1284                 :             :             }
    1285                 :             : 
    1286         [ +  + ]:          49 :             if (len > 0)
    1287                 :             :             {
    1288                 :          40 :                 inchi_strbuf_printf( strbuf, "%s", szValue );
    1289                 :             :             }
    1290                 :             :             /*if ( 0 <= len && nLen+len < nLen_szLinearCT ) {
    1291                 :             :                 if ( len ) {
    1292                 :             :                     strcpy( szLinearCT+nLen, szValue );
    1293                 :             :                     nLen += len;
    1294                 :             :                 }
    1295                 :             :             } else {
    1296                 :             :                 bOvfl = 1;
    1297                 :             :                 break;
    1298                 :             :             }*/
    1299                 :             :         }
    1300                 :             : 
    1301   [ +  -  +  -  :           6 :         if (!bOvfl && !bCompressed && i)
                   +  - ]
    1302                 :             :         {
    1303                 :           6 :             inchi_strbuf_printf( strbuf, ")" );
    1304                 :             :             /*if ( nLen + 1 < nLen_szLinearCT ) {
    1305                 :             :                 strcpy( szLinearCT+nLen, ")" );
    1306                 :             :                 nLen ++;
    1307                 :             :             } else {
    1308                 :             :                 bOvfl = 1;
    1309                 :             :             }*/
    1310                 :             :         }
    1311                 :             :     }
    1312                 :           6 :     *bOverflow |= bOvfl;
    1313                 :             : 
    1314                 :           6 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1315                 :             : 
    1316                 :           6 :     return nLen;
    1317                 :             : }
    1318                 :             : 
    1319                 :             : 
    1320                 :             : /****************************************************************************
    1321                 :             :     MakeCRVString( ... )
    1322                 :             : 
    1323                 :             :     nCtMode =    0: full
    1324                 :             :                 2: compressed CT
    1325                 :             :                 22+3s3:  22=canon. number; +3=charge; s=singlet (d=doublet, t=triplet, s is omitted if valence=0), 3 = valence
    1326                 :             :                 22+3.3, (charge, valence) 22.3 (valence) 22t3 (triplet, valence)
    1327                 :             :                 Ab+3t4:  Ab=canon. number; +3=charge or "." t=triplet (or s, d), 4=valence
    1328                 :             : ****************************************************************************/
    1329                 :          12 : int MakeCRVString( ORIG_INFO        *OrigInfo,
    1330                 :             :                    int              nLenCT,
    1331                 :             :                    int              bAddDelim,
    1332                 :             :                    INCHI_IOS_STRING *strbuf,
    1333                 :             :                    int              nCtMode,
    1334                 :             :                    int              *bOverflow )
    1335                 :             : {
    1336                 :             :     /*  produce output string; */
    1337                 :          12 :     int nUsedLength0 = 0, nLen = 0, len, k, bAbcNumbers;
    1338                 :          12 :     int bOvfl = *bOverflow;
    1339                 :          12 :     char szValue[2048] = { 0 };
    1340                 :          12 :     int  bNext = 0;
    1341                 :          12 :     bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1342                 :             : 
    1343                 :          12 :     nUsedLength0 = strbuf->nUsedLength;
    1344                 :             : 
    1345                 :             :     /*  add connection table string */
    1346   [ +  -  -  + ]:          12 :     if (!bOvfl && bAddDelim)
    1347                 :             :     {
    1348                 :           0 :         inchi_strbuf_printf( strbuf, ", " );
    1349                 :             :         /*if ( nLen_szLinearCT > 2 ) {
    1350                 :             :             strcpy( szLinearCT, ", " );
    1351                 :             :             nLen += 2;
    1352                 :             :         } else {
    1353                 :             :             bOvfl = 1;
    1354                 :             :         }*/
    1355                 :             :     }
    1356                 :             : 
    1357   [ +  -  +  + ]:         101 :     for (k = 0; !bOvfl && k < nLenCT/* && nLen < nLen_szLinearCT*/; k++)
    1358                 :             :     {
    1359                 :             :         /*  find the next non-empty entry */
    1360   [ +  +  +  -  :          89 :         if (OrigInfo[k].cCharge || OrigInfo[k].cRadical || OrigInfo[k].cUnusualValence)
                   +  + ]
    1361                 :             :         {
    1362         [ -  + ]:          15 :             if (bAbcNumbers)
    1363                 :             :             {
    1364                 :             :                 /*
    1365                 :             :                 3 items: Ad+3d4 (canon. numb=Ad, charge=+3, doublet, valence = 4
    1366                 :             :                 2 items: Ad.d4  Ad+3.4  Ad+3d
    1367                 :             :                 1 item:  Ad+3   Ad.d     Ad4
    1368                 :             : 
    1369                 :             :                 dot output before radical: no charge, radical is present
    1370                 :             :                 dot before valence:        charge is present, no radical, valence is present
    1371                 :             :                 */
    1372                 :           0 :                 len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), NULL, k + 1 );
    1373                 :             : 
    1374                 :             :                 /* charge */
    1375         [ #  # ]:           0 :                 if (OrigInfo[k].cCharge)
    1376                 :             :                 {
    1377         [ #  # ]:           0 :                     if (OrigInfo[k].cCharge > 0)
    1378                 :             :                     {
    1379                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, "+", OrigInfo[k].cCharge );
    1380                 :             :                     }
    1381                 :             :                     else
    1382                 :             :                     {
    1383                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, OrigInfo[k].cCharge );
    1384                 :             :                     }
    1385                 :             :                 }
    1386                 :             :                 /* radical */
    1387         [ #  # ]:           0 :                 if (OrigInfo[k].cRadical)
    1388                 :             :                 {
    1389         [ #  # ]:           0 :                     if (!OrigInfo[k].cCharge)
    1390                 :             :                     {
    1391         [ #  # ]:           0 :                         if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1392                 :             :                         {
    1393                 :           0 :                             len = 2047;
    1394                 :           0 :                             goto early_break;
    1395                 :             :                         }
    1396         [ #  # ]:           0 :                         else if (len < 0) /* djb-rwth: fixing coverity ID #500400 */
    1397                 :             :                         {
    1398                 :           0 :                             len = 0;
    1399                 :           0 :                             goto early_break;
    1400                 :             :                         }
    1401                 :             :                         else
    1402                 :             :                         {
    1403                 :           0 :                             szValue[len] = '.';
    1404                 :           0 :                             len++;
    1405                 :             :                         }
    1406                 :             :                     }
    1407         [ #  # ]:           0 :                     if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1408                 :             :                     {
    1409                 :           0 :                         len = 2047;
    1410                 :           0 :                         goto early_break;
    1411                 :             :                     }
    1412         [ #  # ]:           0 :                     else if (len < 0) /* djb-rwth: fixing coverity ID #500382 */
    1413                 :             :                     {
    1414                 :           0 :                         len = 0;
    1415                 :           0 :                         goto early_break;
    1416                 :             :                     }
    1417                 :             :                     else
    1418                 :             :                     {
    1419      [ #  #  # ]:           0 :                         switch (OrigInfo[k].cRadical)
    1420                 :             :                         {
    1421                 :           0 :                             case 1:
    1422                 :             :                                 /* djb-rwth: fixing coverity ID #499515 -- false positive, len tested for overflow */
    1423                 :           0 :                                 szValue[len] = 'd';
    1424                 :           0 :                                 len++;
    1425                 :           0 :                                 break;
    1426                 :           0 :                             case 2:
    1427                 :           0 :                                 szValue[len] = 't';
    1428                 :           0 :                                 len++;
    1429                 :           0 :                                 break;
    1430                 :           0 :                             default:
    1431                 :           0 :                                 szValue[len] = 'u';
    1432                 :           0 :                                 len++;
    1433                 :           0 :                                 break;
    1434                 :             :                         }
    1435                 :             :                     }
    1436                 :             :                 }
    1437                 :             :                 /* valence */
    1438         [ #  # ]:           0 :                 if (OrigInfo[k].cUnusualValence)
    1439                 :             :                 {
    1440   [ #  #  #  # ]:           0 :                     if (OrigInfo[k].cCharge && !OrigInfo[k].cRadical)
    1441                 :             :                     {
    1442         [ #  # ]:           0 :                         if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1443                 :             :                         {
    1444                 :           0 :                             len = 2047;
    1445                 :           0 :                             goto early_break;
    1446                 :             :                         }
    1447         [ #  # ]:           0 :                         else if (len < 0) /* djb-rwth: fixing coverity ID #500382 */
    1448                 :             :                         {
    1449                 :           0 :                             len = 0;
    1450                 :           0 :                             goto early_break;
    1451                 :             :                         }
    1452                 :             :                         else
    1453                 :             :                         {
    1454                 :           0 :                             szValue[len] = '.';
    1455                 :           0 :                             len++;
    1456                 :             :                         }
    1457                 :             :                     }
    1458                 :           0 :                     len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, OrigInfo[k].cUnusualValence );
    1459                 :             :                 }
    1460                 :             :             }
    1461                 :             :             else
    1462                 :             :             {
    1463                 :             :                 /*
    1464                 :             :                     3 items: 22+3d4 (canon. numb=22, charge=+3, doublet, valence = 4
    1465                 :             :                     2 items: 22d4  22+3.4  22+3d
    1466                 :             :                     1 item:  22+3  22d     22.4
    1467                 :             : 
    1468                 :             :                     dot output before valence:
    1469                 :             :                                 (a) charge,    no radical, valence
    1470                 :             :                                 (b) no charge, no radical, valence
    1471                 :             :                     that is, whenever valence is present and no radical
    1472                 :             :                 */
    1473         [ +  + ]:          15 :                 len = MakeDecNumber( szValue, ( int )sizeof( szValue ), bNext ? ITEM_DELIMETER : NULL, k + 1 );
    1474                 :             :                 /* charge */
    1475         [ +  + ]:          15 :                 if (OrigInfo[k].cCharge)
    1476                 :             :                 {
    1477         [ -  + ]:           6 :                     if (OrigInfo[k].cCharge > 0)
    1478                 :             :                     {
    1479                 :           0 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, "+", OrigInfo[k].cCharge );
    1480                 :             :                     }
    1481                 :             :                     else
    1482                 :             :                     {
    1483                 :           6 :                         len += MakeDecNumber( szValue + len, ( int )sizeof( szValue ) - len, NULL, OrigInfo[k].cCharge );
    1484                 :             :                     }
    1485                 :             :                 }
    1486                 :             :                 /* radical */
    1487         [ -  + ]:          15 :                 if (OrigInfo[k].cRadical)
    1488                 :             :                 {
    1489         [ #  # ]:           0 :                     if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1490                 :             :                     {
    1491                 :           0 :                         len = 2047;
    1492                 :           0 :                         goto early_break;
    1493                 :             :                     }
    1494         [ #  # ]:           0 :                     else if (len < 0) /* djb-rwth: fixing coverity ID #500382 */
    1495                 :             :                     {
    1496                 :           0 :                         len = 0;
    1497                 :           0 :                         goto early_break;
    1498                 :             :                     }
    1499                 :             :                     else
    1500                 :             :                     {
    1501      [ #  #  # ]:           0 :                         switch (OrigInfo[k].cRadical)
    1502                 :             :                         {
    1503                 :           0 :                             case 1:
    1504                 :           0 :                                 szValue[len] = 'd'; /* djb-rwth: GCC 14 false positive */
    1505                 :           0 :                                 len++;
    1506                 :           0 :                                 break;
    1507                 :           0 :                             case 2:
    1508                 :           0 :                                 szValue[len] = 't';
    1509                 :           0 :                                 len++;
    1510                 :           0 :                                 break;
    1511                 :           0 :                             default:
    1512                 :           0 :                                 szValue[len] = 'u';
    1513                 :           0 :                                 len++;
    1514                 :           0 :                                 break;
    1515                 :             :                         }
    1516                 :             :                     }
    1517                 :             :                 }
    1518                 :             :                 /* valence */
    1519         [ +  + ]:          15 :                 if (OrigInfo[k].cUnusualValence)
    1520                 :             :                 {
    1521         [ +  - ]:           9 :                     if (!OrigInfo[k].cRadical)
    1522                 :             :                     {
    1523         [ -  + ]:           9 :                         if (len >= 2047) /* djb-rwth: fixing coverity ID #499515 */
    1524                 :             :                         {
    1525                 :           0 :                             len = 2047;
    1526                 :           0 :                             goto early_break;
    1527                 :             :                         }
    1528         [ -  + ]:           9 :                         else if (len < 0) /* djb-rwth: fixing coverity ID #500382 */
    1529                 :             :                         {
    1530                 :           0 :                             len = 0;
    1531                 :           0 :                             goto early_break;
    1532                 :             :                         }
    1533                 :             :                         else
    1534                 :             :                         {
    1535                 :           9 :                             szValue[len] = '.';
    1536                 :           9 :                             len++;
    1537                 :             :                         }
    1538                 :             :                     }
    1539                 :           9 :                     len += MakeDecNumber(szValue + len, (int)sizeof(szValue) - len, NULL, OrigInfo[k].cUnusualValence);
    1540                 :             :                 }
    1541                 :             :             }
    1542                 :             :         }
    1543                 :             :         else
    1544                 :             :         {
    1545                 :          74 :             len = 0;
    1546                 :             :         }
    1547                 :             : 
    1548                 :          89 : early_break:
    1549         [ +  + ]:          89 :         if (len)
    1550                 :             :         {
    1551                 :          15 :             szValue[len] = '\0';
    1552                 :          15 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    1553                 :          15 :             bNext++;
    1554                 :          15 :             szValue[0] = '\0';
    1555                 :             :         }
    1556                 :             :         /*if ( len && nLen+len < nLen_szLinearCT ) {
    1557                 :             :             strcpy( szLinearCT+nLen, szValue );
    1558                 :             :             nLen += len;
    1559                 :             :             bNext ++;
    1560                 :             :         } else
    1561                 :             :         if ( len ) {
    1562                 :             :             bOvfl = 1;
    1563                 :             :             break;
    1564                 :             :         }*/
    1565                 :             :     }
    1566                 :          12 :     *bOverflow |= bOvfl;
    1567                 :             : 
    1568                 :          12 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1569                 :             : 
    1570                 :          12 :     return nLen;
    1571                 :             : }
    1572                 :             : 
    1573                 :             : 
    1574                 :             : /****************************************************************************
    1575                 :             :     MakeEquString( ... )
    1576                 :             : 
    1577                 :             :     nCtMode =   0: full
    1578                 :             :                 2: compressed CT
    1579                 :             : ****************************************************************************/
    1580                 :          25 : int MakeEquString( AT_NUMB          *LinearCT,
    1581                 :             :                    int              nLenCT,
    1582                 :             :                    int              bAddDelim,
    1583                 :             :                    INCHI_IOS_STRING *strbuf,
    1584                 :             :                    int              nCtMode,
    1585                 :             :                    int              *bOverflow )
    1586                 :             : {
    1587                 :             :     /*  produce output string; */
    1588                 :          25 :     int nUsedLength0 = 0, nLen = 0, len, i, k, bAbcNumbers; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1589                 :          25 :     int bOvfl = *bOverflow;
    1590                 :             :     char szValue[2048];
    1591                 :          25 :     int  bNext = 0;
    1592                 :             : 
    1593                 :          25 :     nUsedLength0 = strbuf->nUsedLength;
    1594                 :             : 
    1595                 :          25 :     bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1596                 :             :     /*  add connection table string */
    1597   [ +  -  -  + ]:          25 :     if (!bOvfl && bAddDelim)
    1598                 :             :     {
    1599                 :           0 :         inchi_strbuf_printf( strbuf, ", " );
    1600                 :             :         /*if ( nLen_szLinearCT > 2 ) {
    1601                 :             :             strcpy( szLinearCT, ", " );
    1602                 :             :             nLen += 2;
    1603                 :             :         } else {
    1604                 :             :             bOvfl = 1;
    1605                 :             :         }*/
    1606                 :             :     }
    1607   [ +  -  +  + ]:         241 :     for (k = 0; !bOvfl && k < nLenCT/* && nLen < nLen_szLinearCT*/; k++)
    1608                 :             :     {
    1609                 :             :         /*  find the first equivalence number */
    1610         [ +  + ]:         216 :         if (k != (int) LinearCT[k] - 1)
    1611                 :             :         {
    1612                 :         149 :             continue;
    1613                 :             :         }
    1614         [ +  + ]:         882 :         for (i = k; i < nLenCT/* && nLen < nLen_szLinearCT*/; i++)
    1615                 :             :         {
    1616         [ +  + ]:         815 :             if (k != (int) LinearCT[i] - 1)
    1617                 :             :             {
    1618                 :         657 :                 continue;
    1619                 :             :             }
    1620                 :             :             /*  equivalence number: a minimal canon_number out of a group of equivalent atoms */
    1621                 :             :             /*  is at canon_number-1 position of each equivalent atom.  */
    1622         [ -  + ]:         158 :             if (bAbcNumbers)
    1623                 :             :             {
    1624   [ #  #  #  # ]:           0 :                 len = MakeAbcNumber( szValue, ( int )sizeof( szValue ), ( i == k && bNext ) ? ITEM_DELIMETER : NULL, i + 1 ); /* djb-rwth: ignoring LLVM warning: possible presence of global variables */
    1625                 :             :             }
    1626                 :             :             else
    1627                 :             :             {
    1628         [ +  + ]:         158 :                 len = MakeDecNumber( szValue, ( int )sizeof( szValue ), ( i == k ) ? "(" : ITEM_DELIMETER, i + 1 ); /* djb-rwth: ignoring LLVM warning: possible presence of global variables */
    1629                 :             :             }
    1630                 :         158 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    1631                 :         158 :             bNext++;
    1632                 :             :             /*if ( 0 <= len && nLen+len < nLen_szLinearCT ) {
    1633                 :             :                 strcpy( szLinearCT+nLen, szValue );
    1634                 :             :                 nLen += len;
    1635                 :             :                 bNext ++;
    1636                 :             :             } else
    1637                 :             :             if ( 0 > len ) {
    1638                 :             :                 bOvfl = 1;
    1639                 :             :                 break;
    1640                 :             :             }*/
    1641                 :             :         }
    1642                 :          67 :         inchi_strbuf_printf( strbuf, ")" );
    1643                 :             :         /*if ( !bOvfl && !bAbcNumbers ) {
    1644                 :             :             if ( nLen + 2 < nLen_szLinearCT ) {
    1645                 :             :                 strcpy( szLinearCT+nLen, ")" );
    1646                 :             :                 nLen ++;
    1647                 :             :             } else {
    1648                 :             :                 bOvfl = 1;
    1649                 :             :             }
    1650                 :             :         }*/
    1651                 :             :     }
    1652                 :          25 :     *bOverflow |= bOvfl;
    1653                 :             : 
    1654                 :          25 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1655                 :             : 
    1656                 :          25 :     return nLen;
    1657                 :             : }
    1658                 :             : 
    1659                 :             : 
    1660                 :             : /****************************************************************************
    1661                 :             :     MakeIsoAtomString( ... )
    1662                 :             : 
    1663                 :             :     nCtMode =    0: full
    1664                 :             :                  2: compressed CT
    1665                 :             : ****************************************************************************/
    1666                 :           0 : int MakeIsoAtomString( INChI_IsotopicAtom *IsotopicAtom,
    1667                 :             :                        int                nNumberOfIsotopicAtoms,
    1668                 :             :                        INCHI_IOS_STRING   *strbuf,
    1669                 :             :                        int                nCtMode,
    1670                 :             :                        int                *bOverflow )
    1671                 :             : {
    1672                 :             :     /*  produce output string; */
    1673                 :           0 :     int nUsedLength0 = 0, nLen = 0, len, tot_len, ret, i, j, bOvfl = *bOverflow;
    1674                 :             :     char szValue[2048];
    1675                 :             :     char *p;
    1676                 :             :     int   nValue;
    1677                 :           0 :     int   bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1678                 :             :     static const char letter[] = "itdh";
    1679                 :             :     static const char *h[] = { "T", "D", "H" };
    1680                 :             :     static const char *sign[] = { "-", "+" };
    1681                 :             : 
    1682                 :           0 :     nUsedLength0 = strbuf->nUsedLength;
    1683                 :             : 
    1684         [ #  # ]:           0 :     if (!bOvfl)
    1685                 :             :     {
    1686         [ #  # ]:           0 :         for (i = 0; i < nNumberOfIsotopicAtoms/* && nLen < nLen_szLinearCT*/; i++)
    1687                 :             :         {
    1688                 :           0 :             p = szValue;
    1689                 :           0 :             tot_len = 0;
    1690         [ #  # ]:           0 :             for (j = 0; j < 5; j++)
    1691                 :             :             {
    1692                 :           0 :                 len = 0;
    1693   [ #  #  #  #  :           0 :                 switch (j)
                   #  # ]
    1694                 :             :                 {
    1695                 :           0 :                     case 0:
    1696                 :           0 :                         nValue = (int) IsotopicAtom[i].nAtomNumber;
    1697                 :           0 :                         break;
    1698                 :           0 :                     case 1:
    1699                 :           0 :                         nValue = (int) IsotopicAtom[i].nIsoDifference;
    1700                 :           0 :                         break;
    1701                 :           0 :                     case 2:
    1702                 :           0 :                         nValue = (int) IsotopicAtom[i].nNum_T;
    1703                 :           0 :                         break;
    1704                 :           0 :                     case 3:
    1705                 :           0 :                         nValue = (int) IsotopicAtom[i].nNum_D;
    1706                 :           0 :                         break;
    1707                 :           0 :                     case 4:
    1708                 :           0 :                         nValue = (int) IsotopicAtom[i].nNum_H;
    1709                 :           0 :                         break;
    1710                 :             :                 }
    1711         [ #  # ]:           0 :                 if (!j)
    1712                 :             :                 {
    1713                 :             :                     /*  atom canonical number */
    1714   [ #  #  #  # ]:           0 :                     len = ( bAbcNumbers ? MakeAbcNumber : MakeDecNumber )
    1715                 :             :                         ( p, ( int )sizeof( szValue ) - tot_len,
    1716         [ #  # ]:           0 :                           bAbcNumbers ? NULL : ( i ? ITEM_DELIMETER : EXTRA_SPACE ), nValue
    1717                 :             :                         );
    1718                 :             :                 }
    1719                 :             :                 else
    1720                 :             :                 {
    1721         [ #  # ]:           0 :                     if (bAbcNumbers)
    1722                 :             :                     {
    1723                 :             :                         /*  Abc output */
    1724      [ #  #  # ]:           0 :                         switch (j)
    1725                 :             :                         {
    1726                 :           0 :                             case 1: /* nIsoDifference */
    1727                 :           0 :                                 len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, NULL, nValue );
    1728                 :           0 :                                 break;
    1729                 :           0 :                             case 2: /* nNum_T */
    1730                 :             :                             case 3: /* nNum_D */
    1731                 :             :                             case 4: /* nNum_H */
    1732         [ #  # ]:           0 :                                 if (nValue)
    1733                 :             :                                 {
    1734         [ #  # ]:           0 :                                     if (( int )sizeof( szValue ) - tot_len > 1)
    1735                 :             :                                     {
    1736                 :           0 :                                         p[len++] = letter[j - 1];
    1737         [ #  # ]:           0 :                                         if (1 == nValue)
    1738                 :             :                                         {
    1739                 :           0 :                                             p[len] = '\0';
    1740                 :             :                                         }
    1741                 :             :                                         else
    1742                 :             :                                         {
    1743                 :           0 :                                             ret = MakeDecNumber( p + len, ( int )sizeof( szValue ) - tot_len - len, NULL, nValue );
    1744         [ #  # ]:           0 :                                             len = ( ret >= 0 ) ? len + ret : ret;
    1745                 :             :                                         }
    1746                 :             :                                     }
    1747                 :             :                                     else
    1748                 :             :                                     {
    1749                 :           0 :                                         len = -1; /* overflow */
    1750                 :             :                                     }
    1751                 :             :                                 }
    1752                 :             :                         }
    1753                 :             :                     }
    1754                 :             :                     else
    1755                 :             :                     {
    1756         [ #  # ]:           0 :                         if (nValue)
    1757                 :             :                         {
    1758         [ #  # ]:           0 :                             if (j == 1)
    1759                 :             :                             {
    1760                 :             :                                 /*  Decimal output */
    1761                 :             :                                 /*  signed isotopic mass difference */
    1762                 :           0 :                                 int subtract = ( nValue > 0 );
    1763                 :             :                                 /*  (n = mass difference) > 0 corresponds to nValue = n+1 */
    1764                 :             :                                 /*  subtract 1 from it so that mass difference for 35Cl or 12C is zero */
    1765                 :           0 :                                 len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, sign[nValue >= 0], abs( nValue - subtract ) );
    1766                 :             :                             }
    1767                 :             :                             else
    1768                 :             :                             {
    1769                 :             :                                 /*  hydrogen isotope */
    1770         [ #  # ]:           0 :                                 if (nValue != 1)
    1771                 :             :                                 {
    1772                 :           0 :                                     len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, h[j - 2], nValue );
    1773                 :             :                                 }
    1774                 :             :                                 else
    1775                 :             :                                 {
    1776         [ #  # ]:           0 :                                     if (( int )sizeof( szValue ) - tot_len > 1)
    1777                 :             :                                     {
    1778                 :           0 :                                         strcpy(p, h[j - 2]);
    1779                 :           0 :                                         len = 1;
    1780                 :             :                                     }
    1781                 :             :                                     else
    1782                 :             :                                     {
    1783                 :           0 :                                         len = -1; /*  overflow */
    1784                 :             :                                     }
    1785                 :             :                                 }
    1786                 :             :                             }
    1787                 :             :                         }
    1788                 :             :                         else
    1789                 :             :                         {
    1790                 :           0 :                             continue; /*  do not write zeroes */
    1791                 :             :                         }
    1792                 :             :                     }
    1793                 :             :                 }
    1794         [ #  # ]:           0 :                 if (len < 0)
    1795                 :             :                 {
    1796                 :           0 :                     bOvfl = 1;
    1797                 :           0 :                     break;
    1798                 :             :                 }
    1799                 :           0 :                 tot_len += len;
    1800                 :           0 :                 p += len;
    1801                 :             :             }
    1802                 :           0 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    1803                 :             :             /*if ( nLen+tot_len < nLen_szLinearCT )
    1804                 :             :             {
    1805                 :             :                 memcpy( szLinearCT+nLen, szValue, tot_len+1 );
    1806                 :             :                 nLen += tot_len;
    1807                 :             :             }
    1808                 :             :             else
    1809                 :             :             {
    1810                 :             :                 bOvfl = 1;
    1811                 :             :                 break;
    1812                 :             :             }*/
    1813                 :             :         }
    1814                 :             :     }
    1815                 :           0 :     *bOverflow |= bOvfl;
    1816                 :             : 
    1817                 :           0 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1818                 :             : 
    1819                 :           0 :     return nLen;
    1820                 :             : }
    1821                 :             : 
    1822                 :             : 
    1823                 :             : /****************************************************************************/
    1824                 :           0 : int MakeIsoTautString( INChI_IsotopicTGroup *IsotopicTGroup,
    1825                 :             :                        int                  nNumberOfIsotopicTGroups,
    1826                 :             :                        INCHI_IOS_STRING     *strbuf,
    1827                 :             :                        int                  nCtMode,
    1828                 :             :                        int                  *bOverflow )
    1829                 :             : {
    1830                 :             :     /*  produce output string; */
    1831                 :           0 :     int nUsedLength0 = 0, nLen = 0, len, tot_len, i, j, bOvfl = *bOverflow;
    1832                 :             :     /* djb-rwth: removing redundant variables */
    1833                 :             :     char szValue[2048];
    1834                 :             :     char *p;
    1835                 :             :     int   nValue;
    1836                 :           0 :     int   bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1837                 :             :     static const char letter[] = "tdh";
    1838                 :             :     static const char *h[] = { "T", "D", "H" };
    1839                 :             : 
    1840                 :           0 :     nUsedLength0 = strbuf->nUsedLength;
    1841                 :             : 
    1842                 :             :     /*  add connection table string */
    1843                 :             :     /* djb-rwth: removing redundant code */
    1844         [ #  # ]:           0 :     if (!bOvfl)
    1845                 :             :     {
    1846         [ #  # ]:           0 :         for (i = 0; i < nNumberOfIsotopicTGroups/* && nLen < nLen_szLinearCT*/; i++)
    1847                 :             :         {
    1848                 :           0 :             p = szValue;
    1849                 :           0 :             tot_len = 0;
    1850         [ #  # ]:           0 :             for (j = 0; j < 4; j++)
    1851                 :             :             {
    1852   [ #  #  #  #  :           0 :                 switch (j)
                      # ]
    1853                 :             :                 {
    1854                 :           0 :                     case 0:
    1855                 :           0 :                         nValue = (int) IsotopicTGroup[i].nTGroupNumber;
    1856                 :           0 :                         break;
    1857                 :           0 :                     case 1:
    1858                 :           0 :                         nValue = (int) IsotopicTGroup[i].nNum_T;
    1859                 :           0 :                         break;
    1860                 :           0 :                     case 2:
    1861                 :           0 :                         nValue = (int) IsotopicTGroup[i].nNum_D;
    1862                 :           0 :                         break;
    1863                 :           0 :                     case 3:
    1864                 :           0 :                         nValue = (int) IsotopicTGroup[i].nNum_H;
    1865                 :           0 :                         break;
    1866                 :             :                 }
    1867         [ #  # ]:           0 :                 if (!j)
    1868                 :             :                 {
    1869                 :             :                     /*  atom canonical number */
    1870   [ #  #  #  # ]:           0 :                     len = ( bAbcNumbers ? MakeAbcNumber : MakeDecNumber )
    1871                 :             :                         ( p, ( int )sizeof( szValue ) - tot_len,
    1872         [ #  # ]:           0 :                           bAbcNumbers ? NULL : ( i ? ITEM_DELIMETER : EXTRA_SPACE ),
    1873                 :             :                           nValue
    1874                 :             :                         );
    1875                 :             :                 }
    1876                 :             :                 else
    1877         [ #  # ]:           0 :                     if (nValue)
    1878                 :             :                     {
    1879         [ #  # ]:           0 :                         if (bAbcNumbers)
    1880                 :             :                         {
    1881                 :           0 :                             len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, NULL, nValue );
    1882         [ #  # ]:           0 :                             if (len > 0)
    1883                 :             :                             { /*  make sure overflow has not happened */
    1884         [ #  # ]:           0 :                                 if (( int )sizeof( szValue ) - tot_len - len > 1)
    1885                 :             :                                 {
    1886                 :           0 :                                     p[len++] = letter[j - 1];
    1887                 :           0 :                                     p[len] = '\0';
    1888                 :             :                                 }
    1889                 :             :                                 else
    1890                 :             :                                 {
    1891                 :           0 :                                     len = -1; /*  overflow */
    1892                 :             :                                 }
    1893                 :             :                             }
    1894                 :             :                         }
    1895                 :             :                         else
    1896                 :             :                         {
    1897                 :             :                             /*  hydrogen isotope */
    1898         [ #  # ]:           0 :                             if (nValue != 1)
    1899                 :             :                             {
    1900                 :           0 :                                 len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, h[j - 1], nValue );
    1901                 :             :                             }
    1902                 :             :                             else
    1903         [ #  # ]:           0 :                                 if (( int )sizeof( szValue ) - tot_len > 1)
    1904                 :             :                                 {
    1905                 :           0 :                                     strcpy(p, h[j - 1]);
    1906                 :           0 :                                     len = 1;
    1907                 :             :                                 }
    1908                 :             :                                 else
    1909                 :             :                                 {
    1910                 :           0 :                                     len = -1; /*  overflow */
    1911                 :             :                                 }
    1912                 :             :                         }
    1913                 :             :                     }
    1914                 :             :                     else
    1915                 :             :                     {
    1916                 :           0 :                         continue; /*  do not write zeroes */
    1917                 :             :                     }
    1918         [ #  # ]:           0 :                 if (len < 0)
    1919                 :             :                 {
    1920                 :           0 :                     bOvfl = 1;
    1921                 :           0 :                     break;
    1922                 :             :                 }
    1923                 :           0 :                 p += len;
    1924                 :           0 :                 tot_len += len;
    1925                 :             :             }
    1926                 :           0 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    1927                 :             :             /*if ( nLen+tot_len < nLen_szLinearCT ) {
    1928                 :             :                 memcpy( szLinearCT+nLen, szValue, tot_len+1 );
    1929                 :             :                 nLen += tot_len;
    1930                 :             :             } else {
    1931                 :             :                 bOvfl = 1;
    1932                 :             :                 break;
    1933                 :             :             }*/
    1934                 :             :         }
    1935                 :             :     }
    1936                 :           0 :     *bOverflow |= bOvfl;
    1937                 :             : 
    1938                 :           0 :     nLen = strbuf->nUsedLength - nUsedLength0;
    1939                 :             : 
    1940                 :           0 :     return nLen;
    1941                 :             : }
    1942                 :             : 
    1943                 :             : 
    1944                 :             : /****************************************************************************/
    1945                 :           0 : int MakeIsoHString( int              num_iso_H[],
    1946                 :             :                     INCHI_IOS_STRING *strbuf,
    1947                 :             :                     int              nCtMode,
    1948                 :             :                     int              *bOverflow )
    1949                 :             : {
    1950                 :             :     /*  produce output string; */
    1951                 :           0 :     int nUsedLength0 = 0, nLen = 0, len, tot_len, j, bOvfl = *bOverflow;
    1952                 :             :     /* djb-rwth: removing redundant variables */
    1953                 :             :     char szValue[2048];
    1954                 :             :     char *p;
    1955                 :             :     int   nValue;
    1956                 :           0 :     int   bAbcNumbers = ( nCtMode & CT_MODE_ABC_NUMBERS );
    1957                 :             :     static const char letter[] = "tdh";
    1958                 :             :     static const char *h[] = { "T", "D", "H" };
    1959                 :             : 
    1960                 :           0 :     nUsedLength0 = strbuf->nUsedLength;
    1961                 :             : 
    1962                 :             :     /*  add connection table string */
    1963                 :             :     /* djb-rwth: removing redundant code */
    1964         [ #  # ]:           0 :     if (!bOvfl)
    1965                 :             :     {
    1966                 :           0 :         p = szValue;
    1967                 :           0 :         tot_len = 0;
    1968         [ #  # ]:           0 :         for (j = 1; j < 4; j++)
    1969                 :             :         {
    1970                 :           0 :             nValue = num_iso_H[NUM_H_ISOTOPES - j];/* j: 1=>T, 2=>D, 3=>1H */
    1971         [ #  # ]:           0 :             if (nValue)
    1972                 :             :             {
    1973         [ #  # ]:           0 :                 if (bAbcNumbers)
    1974                 :             :                 {
    1975                 :           0 :                     len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, NULL, nValue );
    1976         [ #  # ]:           0 :                     if (len > 0)
    1977                 :             :                     {
    1978                 :             :                         /*  make sure overflow has not happened */
    1979         [ #  # ]:           0 :                         if (( int )sizeof( szValue ) - tot_len - len > 1)
    1980                 :             :                         {
    1981                 :           0 :                             p[len++] = letter[j - 1];
    1982                 :           0 :                             p[len] = '\0';
    1983                 :             :                         }
    1984                 :             :                         else
    1985                 :             :                         {
    1986                 :           0 :                             len = -1; /*  overflow */
    1987                 :             :                         }
    1988                 :             :                     }
    1989                 :             :                 }
    1990                 :             :                 else
    1991                 :             :                 {
    1992                 :             :                     /*  hydrogen isotope */
    1993         [ #  # ]:           0 :                     if (nValue != 1)
    1994                 :             :                     {
    1995                 :           0 :                         len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, h[j - 1], nValue );
    1996                 :             :                     }
    1997                 :             :                     else
    1998                 :             :                     {
    1999         [ #  # ]:           0 :                         if (( int )sizeof( szValue ) - tot_len > 1)
    2000                 :             :                         {
    2001                 :           0 :                             strcpy(p, h[j - 1]);
    2002                 :           0 :                             len = 1;
    2003                 :             :                         }
    2004                 :             :                         else
    2005                 :             :                         {
    2006                 :           0 :                             len = -1; /*  overflow */
    2007                 :             :                         }
    2008                 :             :                     }
    2009                 :             :                 }
    2010                 :             :             }
    2011                 :             :             else
    2012                 :             :             {
    2013                 :           0 :                 continue; /*  do not write zeroes */
    2014                 :             :             }
    2015         [ #  # ]:           0 :             if (len < 0)
    2016                 :             :             {
    2017                 :           0 :                 bOvfl = 1;
    2018                 :           0 :                 break;
    2019                 :             :             }
    2020                 :           0 :             p += len;
    2021                 :           0 :             tot_len += len;
    2022                 :             :         }
    2023                 :           0 :         inchi_strbuf_printf( strbuf, "%s", szValue );
    2024                 :             :         /*if ( nLen+tot_len < nLen_szLinearCT ) {
    2025                 :             :             memcpy( szLinearCT+nLen, szValue, tot_len+1 );
    2026                 :             :             nLen += tot_len;
    2027                 :             :         } else {
    2028                 :             :             bOvfl = 1;
    2029                 :             :         }*/
    2030                 :             :     }
    2031                 :           0 :     *bOverflow |= bOvfl;
    2032                 :             : 
    2033                 :           0 :     nLen = strbuf->nUsedLength - nUsedLength0;
    2034                 :             : 
    2035                 :           0 :     return nLen;
    2036                 :             : }
    2037                 :             : 
    2038                 :             : 
    2039                 :             : /****************************************************************************/
    2040                 :          59 : int MakeStereoString( AT_NUMB          *at1,
    2041                 :             :                       AT_NUMB          *at2,
    2042                 :             :                       S_CHAR           *parity,
    2043                 :             :                       int              bAddDelim,
    2044                 :             :                       int              nLenCT,
    2045                 :             :                       INCHI_IOS_STRING *strbuf,
    2046                 :             :                       int              nCtMode,
    2047                 :             :                       int              *bOverflow )
    2048                 :             : {
    2049                 :             :     /*  produce output string; */
    2050                 :          59 :     int nUsedLength0 = 0, nLen = 0, len, tot_len, i, j, bOvfl = *bOverflow;
    2051                 :             :     char szValue[2048];
    2052                 :             :     char *p;
    2053                 :             :     int   nValue;
    2054                 :             :     static const char parity_char[] = "!-+u?";
    2055                 :             : 
    2056                 :          59 :     nUsedLength0 = strbuf->nUsedLength;
    2057                 :          59 :     bAddDelim = 0;
    2058                 :             : 
    2059         [ +  - ]:          59 :     if (!bOvfl)
    2060                 :             :     {
    2061         [ +  + ]:         274 :         for (i = 0; i < nLenCT/* && nLen < nLen_szLinearCT*/; i++)
    2062                 :             :         {
    2063                 :         215 :             p = szValue;
    2064                 :         215 :             tot_len = 0;
    2065         [ +  + ]:         860 :             for (j = 0; j < 3; j++)
    2066                 :             :             {
    2067   [ +  +  +  - ]:         645 :                 if (j == 0 && at1)
    2068                 :             :                 {
    2069                 :         215 :                     nValue = (int) at1[i];
    2070                 :             :                 }
    2071                 :             :                 else
    2072                 :             :                 {
    2073   [ +  +  -  + ]:         430 :                     if (j == 1 && at2)
    2074                 :             :                     {
    2075                 :           0 :                         nValue = (int) at2[i];
    2076                 :             :                     }
    2077                 :             :                     else
    2078                 :             :                     {
    2079   [ +  +  +  - ]:         430 :                         if (j == 2 && parity)
    2080                 :             :                         {
    2081                 :         215 :                             nValue = (int) parity[i];
    2082                 :             :                         }
    2083                 :             :                         else
    2084                 :             :                         {
    2085                 :         215 :                             continue;
    2086                 :             :                         }
    2087                 :             :                     }
    2088                 :             :                 }
    2089         [ -  + ]:         430 :                 if (nCtMode & CT_MODE_ABC_NUMBERS)
    2090                 :             :                 {
    2091         [ #  # ]:           0 :                     len = ( j == 2 ? MakeDecNumber : MakeAbcNumber )( p, ( int )sizeof( szValue ) - tot_len, NULL, nValue );
    2092                 :             :                 }
    2093                 :             :                 else
    2094                 :             :                 {
    2095         [ +  + ]:         430 :                     if (j < 2)
    2096                 :             :                     {
    2097   [ +  -  +  +  :         215 :                         len = MakeDecNumber( p, ( int )sizeof( szValue ) - tot_len, tot_len ? "-" : ( i || bAddDelim ) ? ITEM_DELIMETER : NULL, nValue );
                   -  + ]
    2098                 :             :                     }
    2099                 :             :                     else
    2100                 :             :                     {
    2101         [ +  - ]:         215 :                         if (tot_len + 1 < ( int )sizeof( szValue ))
    2102                 :             :                         {
    2103   [ +  -  +  - ]:         215 :                             *p++ = ( 0 <= nValue && nValue <= 4 ) ? parity_char[nValue] : parity_char[0];
    2104                 :         215 :                             *p = '\0';
    2105                 :         215 :                             len = 1;
    2106                 :             :                         }
    2107                 :             :                         else
    2108                 :             :                         {
    2109                 :           0 :                             len = -1; /*  Overflow */
    2110                 :             :                         }
    2111                 :             :                     }
    2112                 :             :                 }
    2113         [ -  + ]:         430 :                 if (len < 0)
    2114                 :             :                 {
    2115                 :           0 :                     bOvfl = 1;
    2116                 :           0 :                     break;
    2117                 :             :                 }
    2118                 :         430 :                 p += len;
    2119                 :         430 :                 tot_len += len;
    2120                 :             :             }
    2121                 :             : 
    2122                 :         215 :             inchi_strbuf_printf( strbuf, "%s", szValue );
    2123                 :             :             /*
    2124                 :             :             if ( nLen+tot_len < nLen_szLinearCT ) {
    2125                 :             :                 memcpy(  szLinearCT+nLen, szValue, tot_len+1 );
    2126                 :             :                 nLen += tot_len;
    2127                 :             :             } else {
    2128                 :             :                 bOvfl = 1;
    2129                 :             :                 break;
    2130                 :             :             }*/
    2131                 :             :         }
    2132                 :             :     }
    2133                 :          59 :     *bOverflow |= bOvfl;
    2134                 :             : 
    2135                 :          59 :     nLen = strbuf->nUsedLength - nUsedLength0;
    2136                 :             : 
    2137                 :          59 :     return nLen;
    2138                 :             : }
    2139                 :             : 
    2140                 :             : /**
    2141                 :             :  * @brief Compares two integers for qsort.
    2142                 :             :  *
    2143                 :             :  * @param a First integer pointer.
    2144                 :             :  * @param b Second integer pointer.
    2145                 :             :  * @return Returns negative, zero, or positive value based on comparison.
    2146                 :             :  */
    2147                 :         207 : int compare_ints(const void *a, const void *b) {
    2148                 :         207 :     int arg1 = *(const int *)a;
    2149                 :         207 :     int arg2 = *(const int *)b;
    2150                 :         207 :     return (arg1 > arg2) - (arg1 < arg2);
    2151                 :             : }
    2152                 :             : 
    2153                 :             : /**
    2154                 :             :  * @brief Compares the third value of two integer arrays for qsort. Used to sort enhanced stereochemistry groups based on the canonical atom number of the first atom in the group.
    2155                 :             :  *
    2156                 :             :  * @param a First integer array pointer.
    2157                 :             :  * @param b Second integer array pointer.
    2158                 :             :  * @return Returns negative, zero, or positive value based on comparison.
    2159                 :             :  */
    2160                 :         113 : int compare_third_value(const void *a, const void *b) {
    2161                 :         113 :     const int *arr1 = *(const int **)a;
    2162                 :         113 :     const int *arr2 = *(const int **)b;
    2163                 :         113 :     return arr1[2] - arr2[2];
    2164                 :             : }
    2165                 :             : 
    2166                 :             : /**
    2167                 :             :  * @brief Creates the enhanced stereochemistry string for the s - layer.
    2168                 :             :  *
    2169                 :             :  * @param pAux Pointer to the INCHI_AUX structure.
    2170                 :             :  * @param conf_stereo_string Pointer to the configuration stereochemistry string (abs, rel, rac).
    2171                 :             :  * @param enh_stereo Pointer to list of enhanced stereochemistry groups.
    2172                 :             :  * @param nof_stereo_groups Number of enhanced stereochemistry groups.
    2173                 :             :  * @param strbuf Pointer to the output string buffer.
    2174                 :             :  * @param nCtMode Mode flag for string representation.
    2175                 :             :  * @param bOverflow Pointer to overflow flag.
    2176                 :             :  * @return Returns the length of the created string.
    2177                 :             :  */
    2178                 :         138 : int MakeEnhStereoString( INChI_Aux        *pAux,
    2179                 :             :                          INCHI_IOS_STRING *strbuf,
    2180                 :             :                          const char*      conf_stereo_string,
    2181                 :             :                          int              **enh_stereo,
    2182                 :             :                          int              nof_stereo_groups,
    2183                 :             :                          int              nCtMode,
    2184                 :             :                          int              *bOverflow )
    2185                 :             : {
    2186                 :         138 :     int tot_len = 0;
    2187                 :         138 :     int count_added = 0;
    2188                 :             : 
    2189         [ -  + ]:         138 :     if (pAux == NULL) {
    2190                 :           0 :         return 0;
    2191                 :             :     }
    2192                 :             : 
    2193         [ +  + ]:         138 :     if (enh_stereo == NULL) {
    2194                 :          46 :         return 0;
    2195                 :             :     }
    2196                 :             : 
    2197         [ -  + ]:          92 :     if (nof_stereo_groups < 1) {
    2198                 :           0 :         return 0;
    2199                 :             :     }
    2200                 :             : 
    2201                 :          92 :     tot_len += MakeDelim( conf_stereo_string, strbuf, bOverflow );
    2202                 :             : 
    2203                 :          92 :     int **enh_stereo_canon = (int**)inchi_calloc(nof_stereo_groups, sizeof(int*));
    2204                 :             : 
    2205                 :             :     // Converts the original atom numbers in the enhanced stereochemistry groups to canonical atom numbers
    2206                 :             :     // and sorts the atoms within each group based on their canonical atom numbers. This ensures that the order of
    2207                 :             :     // atoms in the string representation is consistent and does not depend on the order of atoms in the input data.
    2208                 :             :     // enh_stereo_canon is a 2D array where each row corresponds to an enhanced stereochemistry group. The first element
    2209                 :             :     // of each row (index 0) stores the number of atoms in the group, the second element (index 1) stores the count of found
    2210                 :             :     // atoms, and the remaining elements (starting from index 2) store the canonical atom numbers of the atoms in the group.
    2211         [ +  + ]:         267 :     for (int i = 0; i < nof_stereo_groups; i++) {
    2212                 :         175 :         const int *atom_numbers = &enh_stereo[i][2];
    2213                 :         175 :         int count_found_atoms = 0;
    2214                 :         175 :         int nof_atoms = enh_stereo[i][1];
    2215                 :             : 
    2216                 :         175 :         enh_stereo_canon[i] = (int*)inchi_calloc(nof_atoms + 2, sizeof(int));
    2217                 :         175 :         enh_stereo_canon[i][0] = nof_atoms;
    2218         [ +  + ]:         507 :         for (int j = 0; j < nof_atoms; j++)  {
    2219                 :             : 
    2220                 :         332 :             int orig_atom_num = atom_numbers[j];
    2221                 :         332 :             int canon_atom_num = get_canonical_atom_number(pAux, orig_atom_num);
    2222         [ +  + ]:         332 :             if (canon_atom_num != -1) {
    2223                 :         163 :                 count_found_atoms++;
    2224                 :             :             } else {
    2225                 :         169 :                 canon_atom_num = INT_MAX;
    2226                 :             :             }
    2227                 :             : 
    2228                 :         332 :             enh_stereo_canon[i][j + 2] = canon_atom_num;
    2229                 :             :         }
    2230                 :         175 :         enh_stereo_canon[i][1] = count_found_atoms;
    2231                 :             : 
    2232         [ +  + ]:         175 :         if (nof_atoms > 1) {
    2233                 :          92 :             qsort(&enh_stereo_canon[i][2], nof_atoms, sizeof(int), compare_ints);
    2234                 :             :         }
    2235                 :             :     }
    2236                 :             : 
    2237                 :             :     // Sorts the enhanced stereochemistry groups based on the canonical atom number of the first atom in the group.
    2238                 :             :     // This ensures that the groups are always in a consistent order in the string representation, regardless of the
    2239                 :             :     // order they were added to the input data (e.g. AND1, AND2, ... or OR1, OR2, ...).
    2240                 :          92 :     qsort(enh_stereo_canon, nof_stereo_groups, sizeof(int*), compare_third_value);
    2241                 :             : 
    2242                 :             :     // Creates the string for the stereo group based on the canonical atom numbers of the atoms in the group. If no
    2243                 :             :     // atoms were found for the group, it will not be added to the string.
    2244         [ +  + ]:         267 :     for (int i = 0; i < nof_stereo_groups; i++) {
    2245                 :         175 :         int nof_atoms = enh_stereo_canon[i][0];
    2246                 :         175 :         int nof_found_atoms = enh_stereo_canon[i][1];
    2247                 :             : 
    2248         [ +  + ]:         175 :         if (nof_found_atoms > 0) {
    2249                 :         114 :             tot_len += MakeDelim( "(", strbuf, bOverflow );
    2250         [ +  + ]:         277 :             for (int j = 0; j < nof_found_atoms; j++)  {
    2251                 :         163 :                 tot_len += MakeNumber_EnhStereo( enh_stereo_canon[i][j + 2], "", strbuf, nCtMode, bOverflow );
    2252                 :         163 :                 count_added++;
    2253                 :             : 
    2254         [ +  + ]:         163 :                 if ((j + 1) < nof_found_atoms) {
    2255                 :          49 :                     tot_len += MakeDelim( ",", strbuf, bOverflow );
    2256                 :             :                 }
    2257                 :             :             }
    2258                 :         114 :             tot_len += MakeDelim( ")", strbuf, bOverflow );
    2259                 :             :         }
    2260                 :             :     }
    2261                 :             : 
    2262         [ +  + ]:         267 :     for (int i = 0; i < nof_stereo_groups; i++) {
    2263         [ +  - ]:         175 :         inchi_free(enh_stereo_canon[i]);
    2264                 :             :     }
    2265         [ +  - ]:          92 :     inchi_free(enh_stereo_canon);
    2266                 :             : 
    2267                 :             :     // Removes the last value for the stereo group (1,2,3) if no atoms were added to the string
    2268         [ +  + ]:          92 :     if (count_added == 0) {
    2269   [ +  -  +  - ]:           8 :         if (strbuf && strbuf->nUsedLength > 0) {
    2270                 :           8 :             strbuf->nUsedLength--;
    2271                 :           8 :             strbuf->pStr[strbuf->nUsedLength] = '\0';
    2272                 :             :         }
    2273                 :             : 
    2274                 :           8 :         tot_len = tot_len - 1;
    2275                 :             :     }
    2276                 :             : 
    2277                 :          92 :     return tot_len;
    2278                 :             : }
    2279                 :             : 
    2280                 :             : /**
    2281                 :             :  * @brief Creates the string for the s - layer based on the enhanced stereochemistry information.
    2282                 :             :  *
    2283                 :             :  * @param orig_inp_data Pointer to the original atom data.
    2284                 :             :  * @param pINChISort Pointer to the INCHI_SORT structure.
    2285                 :             :  * @param bOutType Output type flag.
    2286                 :             :  * @param num_components Number of components in the molecule.
    2287                 :             :  * @param strbuf Pointer to the output string buffer.
    2288                 :             :  * @param nCtMode Mode flag for string representation.
    2289                 :             :  * @param bOverflow Pointer to overflow flag.
    2290                 :             :  * @return Returns the length of the created string.
    2291                 :             :  */
    2292                 :          36 : int MakeSlayerString( ORIG_ATOM_DATA   *orig_inp_data,
    2293                 :             :                       INCHI_SORT       *pINChISort,
    2294                 :             :                       INCHI_IOS_STRING *strbuf,
    2295                 :             :                       int              bOutType,
    2296                 :             :                       int              num_components,
    2297                 :             :                       int              nCtMode,
    2298                 :             :                       int              *bOverflow )
    2299                 :             : {
    2300                 :             : 
    2301                 :          36 :     int tot_len = 0;
    2302                 :             :     int          ii;
    2303                 :             : 
    2304                 :          36 :     const char* x_abs = "1";
    2305                 :          36 :     const char* x_rel = "2";
    2306                 :          36 :     const char* x_rac = "3";
    2307                 :             : 
    2308                 :          36 :     const INCHI_SORT   *is = NULL;
    2309                 :          36 :     const INCHI_SORT  *is0 = pINChISort;
    2310                 :             : 
    2311                 :             :     // INChI        *pINChI = NULL;
    2312                 :          36 :     INChI_Aux    *pAux = NULL;
    2313                 :             : 
    2314                 :          36 :     char **dictionary = (char**)inchi_calloc(ENH_STEREO_DICT_SIZE, sizeof(char*));
    2315                 :          36 :     int *counts = (int*)inchi_calloc(ENH_STEREO_DICT_SIZE, sizeof(int));
    2316                 :             : 
    2317         [ +  + ]:        3636 :     for (int i = 0; i < ENH_STEREO_DICT_SIZE; i++) {
    2318                 :        3600 :         dictionary[i] = NULL;
    2319                 :        3600 :         counts[i] = 0;
    2320                 :             :     }
    2321                 :             : 
    2322                 :          36 :     INCHI_IOS_STRING tmpbuf  = {0};
    2323                 :             : 
    2324   [ +  -  +  + ]:          82 :     for (int cur_c = 0; !*bOverflow && cur_c < num_components; cur_c++)
    2325                 :             :     {
    2326                 :             : 
    2327                 :          46 :         is = is0 + cur_c;
    2328                 :             :         // pINChI = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI[ii] : NULL;
    2329   [ -  +  -  -  :          46 :         pAux = ( 0 <= ( ii = GET_II( bOutType, is ) ) ) ? is->pINChI_Aux[ii] : NULL;
          -  -  -  -  -  
          -  -  -  -  -  
          +  -  +  -  +  
          -  -  +  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
          -  -  -  -  -  
                   +  - ]
    2330                 :             : 
    2331                 :          46 :         inchi_strbuf_init(&tmpbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT);
    2332                 :             : 
    2333                 :             :         // s1
    2334                 :          92 :         tot_len += MakeEnhStereoString( pAux,
    2335                 :             :                                         &tmpbuf,
    2336                 :             :                                         x_abs,
    2337                 :          46 :                                         orig_inp_data->v3000->lists_steabs,
    2338                 :          46 :                                         orig_inp_data->v3000->n_steabs,
    2339                 :             :                                         nCtMode,
    2340                 :             :                                         bOverflow);
    2341                 :             : 
    2342                 :             :         // s2
    2343                 :          92 :         tot_len += MakeEnhStereoString( pAux,
    2344                 :             :                                         &tmpbuf,
    2345                 :             :                                         x_rel,
    2346                 :          46 :                                         orig_inp_data->v3000->lists_sterel,
    2347                 :          46 :                                         orig_inp_data->v3000->n_sterel,
    2348                 :             :                                         nCtMode,
    2349                 :             :                                         bOverflow);
    2350                 :             : 
    2351                 :             :         // s3
    2352                 :          92 :         tot_len += MakeEnhStereoString( pAux,
    2353                 :             :                                         &tmpbuf,
    2354                 :             :                                         x_rac,
    2355                 :          46 :                                         orig_inp_data->v3000->lists_sterac,
    2356                 :          46 :                                         orig_inp_data->v3000->n_sterac,
    2357                 :             :                                         nCtMode,
    2358                 :             :                                         bOverflow);
    2359                 :             : 
    2360                 :          46 :         int found = 0;
    2361         [ +  + ]:        4147 :         for (int i = 0; i < ENH_STEREO_DICT_SIZE; i++) {
    2362   [ +  +  +  + ]:        4106 :             if (dictionary[i] && strcmp(tmpbuf.pStr, dictionary[i]) == 0) {
    2363                 :           5 :                 counts[i]++;
    2364                 :           5 :                 found = 1;
    2365                 :           5 :                 break;
    2366                 :             :             }
    2367                 :             :         }
    2368         [ +  + ]:          46 :         if (!found) {
    2369         [ +  - ]:          47 :             for (int i = 0; i < ENH_STEREO_DICT_SIZE; i++) {
    2370         [ +  + ]:          47 :                 if (dictionary[i] == NULL) {
    2371                 :          41 :                     dictionary[i] = strdup(tmpbuf.pStr);
    2372                 :          41 :                     counts[i] = 1;
    2373                 :          41 :                     break;
    2374                 :             :                 }
    2375                 :             :             }
    2376                 :             :         }
    2377                 :          46 :         inchi_strbuf_close(&tmpbuf);
    2378                 :             :     }
    2379                 :             : 
    2380                 :             :     // String deduplication based on dictionary and counts
    2381                 :          36 :     int count = 0;
    2382         [ +  + ]:        3636 :     for (int i = 0; i < ENH_STEREO_DICT_SIZE; i++) {
    2383         [ +  + ]:        3600 :         if (dictionary[i]) {
    2384         [ +  + ]:          41 :             if (count > 0) {
    2385                 :           5 :                 tot_len += MakeDelim( ";", strbuf, bOverflow );
    2386                 :             :             }
    2387         [ +  + ]:          41 :             if (counts[i] > 1) {
    2388                 :           5 :                 tot_len = inchi_strbuf_printf(strbuf, "%d*%s", counts[i], dictionary[i]);
    2389                 :             :             } else {
    2390                 :          36 :                 tot_len = inchi_strbuf_printf(strbuf, "%s", dictionary[i]);
    2391                 :             :             }
    2392         [ +  - ]:          41 :             inchi_free(dictionary[i]);
    2393                 :          41 :             count++;
    2394                 :             :         }
    2395                 :             :     }
    2396                 :             : 
    2397         [ +  - ]:          36 :     inchi_free(dictionary);
    2398         [ +  - ]:          36 :     inchi_free(counts);
    2399                 :             : 
    2400                 :          36 :     return tot_len;
    2401                 :             : }
    2402                 :             : 
    2403                 :             : #ifdef ALPHA_BASE
    2404                 :             : #if ( ALPHA_BASE != 27 )
    2405                 :             : #error ALPHA_BASE definitions mismatch
    2406                 :             : #endif
    2407                 :             : #else
    2408                 :             : #define ALPHA_BASE     27
    2409                 :             : #endif
    2410                 :             : 
    2411                 :             : #define ALPHA_MINUS    '-'
    2412                 :             : #define ALPHA_ZERO_VAL '.'
    2413                 :             : #define ALPHA_ONE      'a'
    2414                 :             : #define ALPHA_ZERO     '@'
    2415                 :             : 
    2416                 :             : 
    2417                 :             : /****************************************************************************
    2418                 :             :   MakeAbcNumber( ... )
    2419                 :             : 
    2420                 :             :     Produce an "Alphabetic" number, base 27 (27 digits: 0, a, b, ..., z)
    2421                 :             :     The leading "digit" uppercase, the rest -- lowercase
    2422                 :             :     szString length nStringLen includes 1 byte for zero termination
    2423                 :             :     Return Value: length without zero termination; -1 means not enough room
    2424                 :             :     Note: ASCII-encoding specific implementation
    2425                 :             : ****************************************************************************/
    2426                 :           0 : int MakeAbcNumber( char      *szString,
    2427                 :             :                   int        nStringLen,
    2428                 :             :                   const char *szLeadingDelim,
    2429                 :             :                   int        nValue )
    2430                 :             : {
    2431                 :           0 :     char *p = szString;
    2432                 :             :     char *q;
    2433                 :             :     int  nChar;
    2434                 :             : 
    2435         [ #  # ]:           0 :     if (nStringLen < 2)
    2436                 :           0 :         return -1;
    2437   [ #  #  #  #  :           0 :     while (szLeadingDelim && *szLeadingDelim && --nStringLen)
                   #  # ]
    2438                 :             :     {
    2439                 :           0 :         *p++ = *szLeadingDelim++;
    2440                 :             :     }
    2441         [ #  # ]:           0 :     if (nStringLen < 2)
    2442                 :           0 :         return -1;
    2443         [ #  # ]:           0 :     if (!nValue)
    2444                 :             :     {
    2445                 :           0 :         *p++ = ALPHA_ZERO_VAL;  /*  zero value (cannot use 0) */
    2446                 :           0 :         *p = '\0';
    2447                 :           0 :         return 1;
    2448                 :             :     }
    2449         [ #  # ]:           0 :     if (nValue < 0)
    2450                 :             :     {
    2451                 :           0 :         *p++ = ALPHA_MINUS;
    2452                 :           0 :         nStringLen--;
    2453                 :           0 :         nValue = -nValue;
    2454                 :             :     }
    2455   [ #  #  #  # ]:           0 :     for (q = p; nValue && --nStringLen; nValue /= ALPHA_BASE)
    2456                 :             :     {
    2457         [ #  # ]:           0 :         if ((nChar = nValue % ALPHA_BASE)) /* djb-rwth: addressing LLVM warning */
    2458                 :             :         {
    2459                 :           0 :             nChar = ALPHA_ONE + nChar - 1;
    2460                 :             :         }
    2461                 :             :         else
    2462                 :             :         {
    2463                 :           0 :             nChar = ALPHA_ZERO;
    2464                 :             :         }
    2465                 :           0 :         *q++ = nChar;
    2466                 :             :     }
    2467         [ #  # ]:           0 :     if (nStringLen <= 0)
    2468                 :           0 :         return -1;
    2469                 :           0 :     *q = '\0';
    2470                 :           0 :     mystrrev( p );
    2471                 :           0 :     p[0] = toupper( p[0] );
    2472                 :             : 
    2473                 :           0 :     return (int) ( q - szString );
    2474                 :             : }
    2475                 :             : 
    2476                 :             : 
    2477                 :             : #if 1 /* ( READ_INCHI_STRING == 1 ) */
    2478                 :             : 
    2479                 :             : 
    2480                 :             : static long abctol( const char *szString, char **q );   /* keep compiler happy */
    2481                 :             : 
    2482                 :             : 
    2483                 :             : /****************************************************************************
    2484                 :             : abctol( ... ) - analog of strtol() dealing with 'compressed InChI' input strings
    2485                 :             : ****************************************************************************/
    2486                 :           0 : long abctol( const char *szString, char **q )
    2487                 :             : {
    2488                 :             : #define __MYTOLOWER(c) ( ((c) >= 'A') && ((c) <= 'Z') ? ((c) - 'A' + 'a') : (c) )
    2489                 :             : 
    2490                 :           0 :     long        val = 0;
    2491                 :             :     /* djb-rwth: removing redundant variables */
    2492                 :           0 :     const char *p = szString, *pp = szString;
    2493                 :           0 :     long treshold = ( LONG_MAX - 1 ) / ALPHA_BASE;
    2494                 :             : 
    2495         [ #  # ]:           0 :     if (*p == ALPHA_MINUS)
    2496                 :             :     {
    2497                 :           0 :         p++;
    2498                 :             :         /* djb-rwth: removing redundant code */
    2499                 :             :     }
    2500         [ #  # ]:           0 :     if (*p == ALPHA_ZERO)
    2501                 :             :     {
    2502                 :           0 :         p++;
    2503                 :           0 :         goto exit_function;
    2504                 :             :     }
    2505         [ #  # ]:           0 :     if (!isupper( UCINT *p ))
    2506                 :             :     {
    2507                 :           0 :         p = szString;
    2508                 :           0 :         goto exit_function; /* not an abc-number */
    2509                 :             :     }
    2510   [ #  #  #  # ]:           0 :     val = __MYTOLOWER( *p ) - ALPHA_ONE + 1;
    2511                 :           0 :     p++;
    2512         [ #  # ]:           0 :     while (*p)
    2513                 :             :     {
    2514         [ #  # ]:           0 :         if (islower( UCINT *p ))
    2515                 :             :         {
    2516                 :           0 :             val *= ALPHA_BASE;
    2517                 :           0 :             val += *p - ALPHA_ONE + 1;
    2518                 :             :         }
    2519                 :             :         else
    2520         [ #  # ]:           0 :             if (*p == ALPHA_ZERO)
    2521                 :             :             {
    2522                 :             :                 /*^^^ 1.06 */
    2523         [ #  # ]:           0 :                 if (val > treshold)
    2524                 :             :                 {
    2525                 :           0 :                     p = pp;
    2526                 :           0 :                     val = 0;
    2527                 :           0 :                     goto exit_function;
    2528                 :             :                 }
    2529                 :             :                 else
    2530                 :             :                 /* Software version 1.07 ^^^*/
    2531                 :           0 :                     val *= ALPHA_BASE;  /* @1.06 fuzz testing caused overflow here! */
    2532                 :             :             }
    2533                 :             :             else
    2534                 :             :             {
    2535                 :           0 :                 break;
    2536                 :             :             }
    2537                 :           0 :         p++;
    2538                 :             :     }
    2539                 :             : 
    2540                 :           0 : exit_function:
    2541         [ #  # ]:           0 :     if (q)
    2542                 :             :     {
    2543                 :           0 :         *q = (char *) p;  /* cast deliberately discards const qualifier */
    2544                 :             :     }
    2545                 :             : 
    2546                 :           0 :     return val;
    2547                 :             : #undef __MYTOLOWER
    2548                 :             : }
    2549                 :             : 
    2550                 :             : 
    2551                 :             : /********************************************************/
    2552                 :           7 : long inchi_strtol(const char *str, const char **p, int base)
    2553                 :             : {
    2554         [ -  + ]:           7 :     if (base == ALPHA_BASE) {
    2555                 :           0 :         return abctol(str, (char **)p); /* cast deliberately discards const qualifier */
    2556                 :             :     }
    2557                 :             :     else {
    2558                 :           7 :         return strtol(str, (char **)p, base); /* cast deliberately discards const qualifier */
    2559                 :             :     }
    2560                 :             : }
    2561                 :             : #endif /* #if ( READ_INCHI_STRING == 1 ) */
    2562                 :             : 
    2563                 :             : #undef ALPHA_BASE
    2564                 :             : #undef ALPHA_MINUS
    2565                 :             : #undef ALPHA_ZERO_VAL
    2566                 :             : #undef ALPHA_ONE
    2567                 :             : #undef ALPHA_ZERO
    2568                 :             : 
    2569                 :             : 
    2570                 :             : /****************************************************************************/
    2571                 :           0 : double inchi_strtod(const char *str, const char **p)
    2572                 :             : {
    2573                 :           0 :     return strtod( str, (char **) p );
    2574                 :             : }
    2575                 :             : 
    2576                 :             : 
    2577                 :             : /****************************************************************************
    2578                 :             :   MakeDecNumber( ... )
    2579                 :             : 
    2580                 :             :     Produce a decimal number
    2581                 :             : 
    2582                 :             :     szString length nStringLen includes 1 byte for zero termination
    2583                 :             :     Return Value: length without zero termination; -1 means not enough room
    2584                 :             : ****************************************************************************/
    2585                 :        2534 : int MakeDecNumber( char        *szString,
    2586                 :             :                    int         nStringLen,
    2587                 :             :                    const char  *szLeadingDelim,
    2588                 :             :                    int         nValue )
    2589                 :             : {
    2590                 :             : #define DECIMAL_BASE     10
    2591                 :             : #define DECIMAL_MINUS    '-'
    2592                 :             : #define DECIMAL_ZERO_VAL '0'
    2593                 :             : #define DECIMAL_ONE      '1'
    2594                 :             : #define DECIMAL_ZERO     '0'
    2595                 :             : 
    2596                 :        2534 :     char *p = szString;
    2597                 :             :     char *q;
    2598                 :             :     int  nChar;
    2599                 :             : 
    2600         [ -  + ]:        2534 :     if (nStringLen < 2)
    2601                 :             :     {
    2602                 :           0 :         return -1;
    2603                 :             :     }
    2604   [ +  +  +  +  :        3873 :     while (szLeadingDelim && *szLeadingDelim && --nStringLen)
                   +  - ]
    2605                 :             :     {
    2606                 :        1339 :         *p++ = *szLeadingDelim++; /* djb-rwth: GCC 14 false positive */
    2607                 :             :     }
    2608         [ -  + ]:        2534 :     if (nStringLen < 2)
    2609                 :             :     {
    2610                 :           0 :         return -1;
    2611                 :             :     }
    2612         [ -  + ]:        2534 :     if (!nValue)
    2613                 :             :     {
    2614                 :           0 :         *p++ = DECIMAL_ZERO_VAL;  /*  zero value (cannot use 0) */
    2615                 :           0 :         *p = '\0';
    2616                 :           0 :         return (int) ( p - szString );
    2617                 :             :     }
    2618         [ +  + ]:        2534 :     if (nValue < 0)
    2619                 :             :     {
    2620                 :           6 :         *p++ = DECIMAL_MINUS;
    2621                 :           6 :         nStringLen--;
    2622                 :           6 :         nValue = -nValue;
    2623                 :             :     }
    2624   [ +  +  +  - ]:        5539 :     for (q = p; nValue && --nStringLen; nValue /= DECIMAL_BASE)
    2625                 :             :     {
    2626         [ +  + ]:        3005 :         if ((nChar = nValue % DECIMAL_BASE)) /* djb-rwth: addressing LLVM warning */
    2627                 :             :         {
    2628                 :        2915 :             nChar = DECIMAL_ONE + nChar - 1;
    2629                 :             :         }
    2630                 :             :         else
    2631                 :             :         {
    2632                 :          90 :             nChar = DECIMAL_ZERO;
    2633                 :             :         }
    2634                 :        3005 :         *q++ = nChar;
    2635                 :             :     }
    2636         [ -  + ]:        2534 :     if (nStringLen <= 0)
    2637                 :             :     {
    2638                 :           0 :         return -1;
    2639                 :             :     }
    2640                 :        2534 :     *q = '\0';
    2641                 :        2534 :     mystrrev( p );
    2642                 :             : 
    2643                 :        2534 :     return (int) ( q - szString );
    2644                 :             : 
    2645                 :             : #undef DECIMAL_BASE
    2646                 :             : #undef DECIMAL_MINUS
    2647                 :             : #undef DECIMAL_ZERO_VAL
    2648                 :             : #undef DECIMAL_ONE
    2649                 :             : #undef DECIMAL_ZERO
    2650                 :             : }
    2651                 :             : 
    2652                 :             : 
    2653                 :             : /****************************************************************************
    2654                 :             :   Print out num[0..n-1] separated with commas
    2655                 :             :     For shortness, compress consecutive numbers (>2 members in a series)
    2656                 :             :     to a range:
    2657                 :             :     '1,2,5, 7-10' means 1,2,5,7,8,9,10'
    2658                 :             : ****************************************************************************/
    2659                 :           4 : void print_sequence_of_nums_compressing_ranges( int n,
    2660                 :             :                                                 int *num,
    2661                 :             :                                                 INCHI_IOS_STRING *strbuf )
    2662                 :             : {
    2663                 :             :     int k, range;
    2664                 :             : 
    2665                 :           4 :     range = 0;
    2666         [ +  + ]:          12 :     for (k = 0; k < n - 1; k++)
    2667                 :             :     {
    2668         [ +  + ]:           8 :         if (num[k + 1] == num[k] + 1)
    2669                 :             :         {
    2670         [ -  + ]:           2 :             if (range)
    2671                 :             :             {
    2672                 :           0 :                 range++;
    2673                 :             :             }
    2674                 :             :             else
    2675                 :             :             {
    2676                 :           2 :                 inchi_strbuf_printf( strbuf, "%d-", num[k] );
    2677                 :           2 :                 range = 1;
    2678                 :             :             }
    2679                 :             :         }
    2680                 :             :         else
    2681                 :             :         {
    2682         [ +  + ]:           6 :             if (range)
    2683                 :             :             {
    2684                 :           2 :                 range = 0;
    2685                 :             :             }
    2686                 :           6 :             inchi_strbuf_printf( strbuf, "%d,", num[k] );
    2687                 :             :         }
    2688                 :             :     }
    2689                 :           4 :     inchi_strbuf_printf( strbuf, "%d", num[n - 1] );
    2690                 :             : 
    2691                 :           4 :     return;
    2692                 :             : }
        

Generated by: LCOV version 2.0-1