LCOV - code coverage report
Current view: top level - src - mol_fmt4.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 11.8 % 608 72
Test Date: 2026-05-04 07:05:02 Functions: 33.3 % 27 9
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 5.2 % 735 38

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * International Chemical Identifier (InChI)
       3                 :             :  * Version 1
       4                 :             :  * Software version 1.07
       5                 :             :  * April 30, 2024
       6                 :             :  *
       7                 :             :  * MIT License
       8                 :             :  *
       9                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
      10                 :             :  *
      11                 :             :  * Permission is hereby granted, free of charge, to any person obtaining a copy
      12                 :             :  * of this software and associated documentation files (the "Software"), to deal
      13                 :             :  * in the Software without restriction, including without limitation the rights
      14                 :             :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      15                 :             :  * copies of the Software, and to permit persons to whom the Software is
      16                 :             :  * furnished to do so, subject to the following conditions:
      17                 :             :  *
      18                 :             :  * The above copyright notice and this permission notice shall be included in all
      19                 :             :  * copies or substantial portions of the Software.
      20                 :             :  *
      21                 :             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      22                 :             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      24                 :             :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      26                 :             :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      27                 :             :  * SOFTWARE.
      28                 :             :  *
      29                 :             :  * The InChI library and programs are free software developed under the
      30                 :             :  * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
      31                 :             :  * Originally developed at NIST.
      32                 :             :  * Modifications and additions by IUPAC and the InChI Trust.
      33                 :             :  * Some portions of code were developed/changed by external contributors
      34                 :             :  * (either contractor or volunteer) which are listed in the file
      35                 :             :  * 'External-contributors' included in this distribution.
      36                 :             :  *
      37                 :             :  * info@inchi-trust.org
      38                 :             :  *
      39                 :             :  */
      40                 :             : 
      41                 :             : #include <stdlib.h>
      42                 :             : #include <ctype.h>
      43                 :             : #include <string.h>
      44                 :             : #include <math.h>
      45                 :             : #include <float.h>
      46                 :             : #include <limits.h>
      47                 :             : 
      48                 :             : #include "mode.h"
      49                 :             : #include "mol_fmt.h"
      50                 :             : 
      51                 :             : #include "ichierr.h"
      52                 :             : #include "util.h"
      53                 :             : #include "ichi_io.h"
      54                 :             : #include "ichimain.h"
      55                 :             : 
      56                 :             : #include "bcf_s.h"
      57                 :             : 
      58                 :             : /*
      59                 :             :     SDFile related procedures
      60                 :             : 
      61                 :             : */
      62                 :             : 
      63                 :             : #define ALIASED_AT(i) (0 < NUM_ISO_H(at, i))
      64                 :             : #define IS_DEUTERIUM(i) (!strcmp(at[i].elname, "D") || at[i].iso_atw_diff == 2 && !strcmp(at[i].elname, "H"))
      65                 :             : #define IS_TRITIUM(i)   (!strcmp(at[i].elname, "T") || at[i].iso_atw_diff == 3 && !strcmp(at[i].elname, "H"))
      66                 :             : 
      67                 :             : #define ABNORMAL_ISO(i) (at[i].iso_atw_diff == 1 || at[i].iso_atw_diff < -3 || at[i].iso_atw_diff > 5)
      68                 :             : #define ABNORMAL_CHG(i) (abs(at[i].charge) > 3)
      69                 :             : #define ABNORMAL_RAD(i) (RADICAL_SINGLET <= at[i].radical && at[i].radical <= RADICAL_TRIPLET)
      70                 :             : 
      71                 :             : #define ANY_ISO(i, X)   ((X)? (at[i].iso_atw_diff && !IS_DEUTERIUM(i) && !IS_TRITIUM(i)) :\
      72                 :             :                           (at[i].iso_atw_diff ||  IS_DEUTERIUM(i) ||  IS_TRITIUM(i)))
      73                 :             : #define ANY_CHG(i)      (0 != at[i].charge)
      74                 :             : #define ANY_RAD(i)      (RADICAL_SINGLET <= at[i].radical && at[i].radical <= RADICAL_TRIPLET)
      75                 :             : 
      76                 :             : #define NORMAL_ISO(i, X)   (ANY_ISO(i, X) && !ABNORMAL_ISO(i))
      77                 :             : 
      78                 :             : /* needs additional M  CHG. M  RAD, M  ISO line */
      79                 :             : /* due to ISIS/Draw feature always include M  RAD for any radical */
      80                 :             : #define ABNORMAL_AT(i) (at[i].radical || abs(at[i].charge) > 3 || \
      81                 :             :                         ABNORMAL_ISO(i))
      82                 :             : 
      83                 :             : /* always add M  ISO, M  RAD, M  CHG; Except: (bAtomsDT && D or T) */
      84                 :             : #define ADD_LINE_AT(i) (at[i].charge ||  \
      85                 :             :                         at[i].radical || \
      86                 :             :                         at[i].iso_atw_diff && (bAtomsDT ? (at[i].iso_atw_diff != 1 || strcmp(at[i].elname, "H")) : 1))
      87                 :             : 
      88                 :             : /* Local */
      89                 :             : 
      90                 :             : static const char sdf_data_hdr_name[] = "NAME";
      91                 :             : static const char sdf_data_hdr_comm[] = "COMMENT";
      92                 :             : 
      93                 :             : enum
      94                 :             : {
      95                 :             :     SDF_START,
      96                 :             :     SDF_DATA_HEADER,
      97                 :             :     SDF_DATA_HEADER_NAME,
      98                 :             :     SDF_DATA_HEADER_COMMENT,
      99                 :             :     SDF_DATA_HEADER_CAS,
     100                 :             :     SDF_DATA_HEADER_USER,
     101                 :             :     SDF_DATA_LINE,
     102                 :             :     SD_FMT_END_OF_DATA_ITEM,
     103                 :             :     SDF_EMPTY_LINE,
     104                 :             :     SD_FMT_END_OF_DATA_BLOCK
     105                 :             : };
     106                 :             : 
     107                 :             : int OrigAtData_WriteToSDfileHeaderAndCountThings(const ORIG_ATOM_DATA *inp_at_data,
     108                 :             :                                                  INCHI_IOSTREAM *fcb,
     109                 :             :                                                  const char *name,
     110                 :             :                                                  const char *comment,
     111                 :             :                                                  int bChiralFlag,
     112                 :             :                                                  int bAtomsDT,
     113                 :             :                                                  const char *szLabel,
     114                 :             :                                                  const char *szValue,
     115                 :             :                                                  int *nNumAliasLines,
     116                 :             :                                                  int *nNumChargeLines,
     117                 :             :                                                  int *nNumRadicalLines,
     118                 :             :                                                  int *nNumIsoLines,
     119                 :             :                                                  int *nNumAddLines,
     120                 :             :                                                  int *num_bonds);
     121                 :             : int OrigAtData_WriteToSDfileAtomsBlock(const ORIG_ATOM_DATA *inp_at_data,
     122                 :             :                                        INCHI_IOSTREAM *fcb,
     123                 :             :                                        const char *name,
     124                 :             :                                        const char *comment,
     125                 :             :                                        int bAtomsDT,
     126                 :             :                                        const char *szLabel,
     127                 :             :                                        const char *szValue);
     128                 :             : 
     129                 :             : int OrigAtData_WriteToSDfileBondsBlock(const ORIG_ATOM_DATA *inp_at_data,
     130                 :             :                                        INCHI_IOSTREAM *fcb,
     131                 :             :                                        const char *name,
     132                 :             :                                        const char *comment,
     133                 :             :                                        const char *szLabel,
     134                 :             :                                        const char *szValue,
     135                 :             :                                        INT_ARRAY *written_bond_ends);
     136                 :             : 
     137                 :             : int OrigAtData_WriteToSDfileAdditionalLines(const ORIG_ATOM_DATA *inp_at_data,
     138                 :             :                                             INCHI_IOSTREAM *fcb,
     139                 :             :                                             const char *name,
     140                 :             :                                             const char *comment,
     141                 :             :                                             int bAtomsDT,
     142                 :             :                                             const char *szLabel,
     143                 :             :                                             const char *szValue,
     144                 :             :                                             int nNumAliasLines,
     145                 :             :                                             int nNumChargeLines,
     146                 :             :                                             int nNumRadicalLines,
     147                 :             :                                             int nNumIsoLines,
     148                 :             :                                             INT_ARRAY *written_bond_ends);
     149                 :             : 
     150                 :             : int OrigAtData_WriteToSDfilePolymerData(const ORIG_ATOM_DATA *inp_at_data,
     151                 :             :                                         INCHI_IOSTREAM *fcb,
     152                 :             :                                         const char *name,
     153                 :             :                                         const char *comment,
     154                 :             :                                         const char *szLabel,
     155                 :             :                                         const char *szValue,
     156                 :             :                                         INT_ARRAY *written_bond_ends);
     157                 :             : 
     158                 :             : /****************************************************************************
     159                 :             :  Skip extra data ( != Molfile) which SDF contains
     160                 :             : ****************************************************************************/
     161                 :          54 : int SDFileSkipExtraData(INCHI_IOSTREAM *inp_file,
     162                 :             :                         unsigned long *CAS_num,
     163                 :             :                         char *comment,
     164                 :             :                         int lcomment,
     165                 :             :                         char *name,
     166                 :             :                         int lname,
     167                 :             :                         int prev_err,
     168                 :             :                         const char *pSdfLabel,
     169                 :             :                         char *pSdfValue,
     170                 :             :                         char *pStrErr,
     171                 :             :                         int bNoWarnings)
     172                 :             : {
     173                 :          54 :     char *p = NULL;
     174                 :             :     char line[MOL_FMT_INPLINELEN];
     175                 :          54 :     const int line_len = sizeof( line );
     176                 :          54 :     int n_blank_lines = 0, n_lines = 0;
     177                 :          54 :     int current_state = SDF_START;
     178                 :          54 :     int err = 0;
     179                 :          54 :     int wait_for_CAS = 0;
     180                 :          54 :     int CAS_num_is_user = 0;
     181   [ -  +  -  -  :          54 :     int wait_for_name = name && lname > 0 && !name[0];
                   -  - ]
     182   [ -  +  -  -  :          54 :     int wait_for_comment = comment && lcomment > 0 && !comment[0];
                   -  - ]
     183   [ -  +  -  -  :          54 :     int wait_for_user = pSdfLabel && pSdfLabel[0] && pSdfValue;
                   -  - ]
     184                 :             : 
     185         [ +  - ]:          54 :     if (CAS_num != NULL)
     186                 :             :     {
     187                 :          54 :         wait_for_CAS = 1;
     188                 :          54 :         *CAS_num = 0LU;
     189   [ -  +  -  - ]:          54 :         CAS_num_is_user = (wait_for_user && !inchi_memicmp(pSdfLabel, "CAS", 3));
     190                 :             :     }
     191                 :             : 
     192         [ +  - ]:         108 :     while (!err &&
     193   [ +  -  -  + ]:         108 :            current_state != SD_FMT_END_OF_DATA_BLOCK &&
     194                 :          54 :            NULL != (p = inchi_fgetsLf(line, line_len, inp_file)))
     195                 :             :     {
     196   [ #  #  #  # ]:           0 :         if (!n_lines && !memcmp(line, "M  END", 6))
     197                 :             :         {
     198                 :             :             /*  allow subtle errors */
     199                 :           0 :             continue;
     200                 :             :         }
     201                 :             : 
     202                 :           0 :         n_lines++;
     203                 :           0 :         remove_trailing_spaces(line);
     204                 :             : 
     205         [ #  # ]:           0 :         if (line[MOL_FMT_MAXLINELEN])
     206                 :             :         {
     207   [ #  #  #  # ]:           0 :             if (current_state != SDF_DATA_HEADER &&
     208         [ #  # ]:           0 :                 current_state != SDF_DATA_LINE &&
     209         [ #  # ]:           0 :                 current_state != SDF_DATA_HEADER_NAME &&
     210         [ #  # ]:           0 :                 current_state != SDF_DATA_HEADER_USER &&
     211                 :             :                 current_state != SDF_DATA_HEADER_COMMENT)
     212                 :             :             {
     213                 :           0 :                 line[MOL_FMT_MAXLINELEN] = '\0';
     214         [ #  # ]:           0 :                 if (!prev_err)
     215                 :             :                 {
     216                 :           0 :                     TREAT_ERR(err, 0, "Too long SData line truncated");
     217                 :             :                 }
     218                 :             :             }
     219                 :             :             else
     220                 :             :             {
     221                 :             :                 /* allow long lines in SDF data. 9-29-00 DCh */
     222                 :           0 :                 line[MOL_FMT_MAXLINELEN] = '\0';
     223                 :             :             }
     224                 :             :         }
     225                 :             : 
     226                 :           0 :         n_blank_lines += (*line == '\0');
     227                 :             : 
     228   [ #  #  #  #  :           0 :         switch (current_state)
                #  #  # ]
     229                 :             :         {
     230                 :           0 :             case SDF_START:
     231                 :             :             case SD_FMT_END_OF_DATA_ITEM:
     232                 :             :             case SDF_EMPTY_LINE: /* Added 9-25-97 DCh */
     233                 :             : 
     234         [ #  # ]:           0 :                 if (!strcmp(line, SD_FMT_END_OF_DATA))
     235                 :             :                 {
     236                 :           0 :                     current_state = SD_FMT_END_OF_DATA_BLOCK;
     237                 :             :                 }
     238         [ #  # ]:           0 :                 else if ('>' == *line)
     239                 :             :                 {
     240   [ #  #  #  #  :           0 :                     current_state = (wait_for_name || wait_for_comment || wait_for_CAS || wait_for_user) ? SDFileIdentifyLabel( line, pSdfLabel ) : SDF_DATA_HEADER;
             #  #  #  # ]
     241                 :             :                 }
     242         [ #  # ]:           0 :                 else if (*line == '\0')
     243                 :             :                 {
     244                 :             :                     /* Added 9-25-97 DCh */
     245                 :             :                     /* Relax the strictness: Allow more than 1 empty line. */
     246                 :           0 :                     current_state = SDF_EMPTY_LINE;
     247                 :             :                 }
     248         [ #  # ]:           0 :                 else if (!prev_err)
     249                 :             :                 {
     250         [ #  # ]:           0 :                     TREAT_ERR(err, 3, "Unexpected SData header line:"); /* djb-rwth: addressing coverity ID #499557 -- TREAT_ERR properly used */
     251                 :           0 :                     dotify_non_printable_chars(line);
     252                 :           0 :                     AddErrorMessage(pStrErr, line);
     253                 :             :                     /* unexpected contents of data header line */
     254                 :             :                 }
     255                 :             :                 else
     256                 :             :                 {
     257                 :           0 :                     err = 3;
     258                 :             :                 }
     259                 :           0 :                 break;
     260                 :             : 
     261                 :           0 :             case SDF_DATA_HEADER_NAME:
     262                 :             : 
     263   [ #  #  #  # ]:           0 :                 if (wait_for_name && 0 < normalize_string(line))
     264                 :             :                 {
     265                 :           0 :                     wait_for_name = 0;
     266                 :           0 :                     mystrncpy(name, line, lname);
     267                 :             :                 }
     268                 :           0 :                 goto got_data_line;
     269                 :             : 
     270                 :           0 :             case SDF_DATA_HEADER_COMMENT:
     271                 :             : 
     272   [ #  #  #  # ]:           0 :                 if (wait_for_comment && 0 < normalize_string(line))
     273                 :             :                 {
     274                 :           0 :                     wait_for_comment = 0;
     275                 :           0 :                     mystrncpy(comment, line, lcomment);
     276                 :             :                 }
     277                 :           0 :                 goto got_data_line;
     278                 :             : 
     279                 :           0 :             case SDF_DATA_HEADER_USER:
     280                 :             : 
     281   [ #  #  #  # ]:           0 :                 if (wait_for_user && 0 < normalize_string(line))
     282                 :             :                 {
     283                 :           0 :                     wait_for_user = 0;
     284                 :           0 :                     mystrncpy(pSdfValue, line, MAX_SDF_VALUE + 1);
     285                 :             : 
     286   [ #  #  #  # ]:           0 :                     if (CAS_num_is_user && wait_for_CAS)
     287                 :             :                     {
     288                 :           0 :                         *CAS_num = SDFileExtractCASNo(line);
     289                 :           0 :                         wait_for_CAS = (0LU == *CAS_num);
     290                 :             :                     }
     291                 :             :                 }
     292                 :           0 :                 goto got_data_line;
     293                 :             : 
     294                 :           0 :             case SDF_DATA_HEADER_CAS:
     295                 :             : 
     296   [ #  #  #  # ]:           0 :                 if (wait_for_CAS && 0 < normalize_string(line))
     297                 :             :                 {
     298                 :           0 :                     *CAS_num = SDFileExtractCASNo(line);
     299                 :           0 :                     wait_for_CAS = (0LU == *CAS_num);
     300                 :             :                 }
     301                 :           0 :                 goto got_data_line;
     302                 :             : 
     303                 :             :             case SDF_DATA_HEADER:
     304                 :             :             case SDF_DATA_LINE:
     305                 :             : 
     306                 :           0 :             got_data_line:
     307         [ #  # ]:           0 :                 current_state = *line ? SDF_DATA_LINE : SD_FMT_END_OF_DATA_ITEM;
     308                 :           0 :                 break;
     309                 :             :         }
     310                 :             :     }
     311                 :             : 
     312   [ +  -  +  -  :          54 :     if (!err && SD_FMT_END_OF_DATA_BLOCK != current_state && NULL == p)
                   +  - ]
     313                 :             :     {
     314                 :             :         ; /* err = 4; */ /* unexpected end of file: missing $$$$ */
     315                 :             :     }
     316                 :             : 
     317   [ #  #  #  #  :           0 :     else if (err && (n_blank_lines == n_lines && *line == '\0'))
                   #  # ]
     318                 :             :     {
     319                 :             :         /* empty lines -- do not know when this can happen */
     320                 :           0 :         err = 5;
     321                 :             :     }
     322                 :             : 
     323   [ -  +  -  -  :          54 :     if (err && err != 5 && current_state != SD_FMT_END_OF_DATA_BLOCK && p)
             -  -  -  - ]
     324                 :             :     {
     325                 :             :         /*  bypass up to $$$$ */
     326         [ #  # ]:           0 :         while ((p = inchi_fgetsLf(line, line_len, inp_file)) &&
     327         [ #  # ]:           0 :                memcmp(line, SD_FMT_END_OF_DATA, 4))
     328                 :             :         {
     329                 :             :             ;
     330                 :             :         }
     331         [ #  # ]:           0 :         if (p)
     332                 :             :         {
     333                 :             :             /*  arrived to $$$$; non-fatal */
     334                 :           0 :             err = 9;
     335         [ #  # ]:           0 :             if (!bNoWarnings)
     336                 :             :             {
     337                 :           0 :                 WarningMessage(pStrErr, "Bypassing to next structure");
     338                 :             :             }
     339                 :             :         }
     340                 :             :     }
     341                 :             : 
     342                 :          54 :     return err;
     343                 :             : }
     344                 :             : 
     345                 :             : /****************************************************************************/
     346                 :           0 : int SDFileIdentifyLabel(char *inp_line, const char *pSdfLabel)
     347                 :             : {
     348                 :             :     char line[MOL_FMT_MAXLINELEN];
     349                 :             :     char *p, *q;
     350                 :           0 :     int i, j, len, tmp1 = 0, tmp2 = 0, cnd = 0;
     351                 :             : 
     352         [ #  # ]:           0 :     if ((p = strchr(inp_line, '<')) &&
     353         [ #  # ]:           0 :         (q = strchr(p, '>')) &&
     354   [ #  #  #  # ]:           0 :         (len = q - p - 1) > 0 && len < (int)sizeof(line))
     355                 :             :     {
     356                 :           0 :         memcpy(line, p + 1, len);
     357                 :           0 :         line[len] = '\0';
     358                 :             : 
     359   [ #  #  #  # ]:           0 :         for (i = 0; (i < len) && (cnd == 0); i++)
     360                 :             :         {
     361         [ #  # ]:           0 :             if (isspace(UCINT line[i]))
     362                 :             :             {
     363                 :           0 :                 tmp1 = i;
     364                 :           0 :                 cnd = 1;
     365                 :             :             }
     366                 :             :         }
     367                 :             : 
     368                 :           0 :         cnd = 0;
     369                 :             : 
     370   [ #  #  #  # ]:           0 :         for (j = len - 1; (j >= tmp1) && (cnd == 0); j--)
     371                 :             :         {
     372         [ #  # ]:           0 :             if (isspace(UCINT line[j]))
     373                 :             :             {
     374                 :           0 :                 tmp2 = j;
     375                 :           0 :                 cnd = 1;
     376                 :             :             }
     377                 :             :         }
     378                 :             : 
     379                 :           0 :         len = tmp2 - tmp1 + 1;
     380                 :           0 :         p = line + tmp1;
     381                 :             : 
     382   [ #  #  #  #  :           0 :         if (pSdfLabel && pSdfLabel[0] && len == (int)strlen(pSdfLabel) && !inchi_memicmp(p, pSdfLabel, len))
             #  #  #  # ]
     383                 :             :         {
     384                 :           0 :             return SDF_DATA_HEADER_USER;
     385                 :             :         }
     386                 :             : 
     387   [ #  #  #  # ]:           0 :         if (len == sizeof(sdf_data_hdr_name) - 1 && !inchi_memicmp(p, sdf_data_hdr_name, len))
     388                 :             :         {
     389                 :           0 :             return SDF_DATA_HEADER_NAME;
     390                 :             :         }
     391                 :             : 
     392   [ #  #  #  # ]:           0 :         if (len == sizeof(sdf_data_hdr_comm) - 1 && !inchi_memicmp(p, sdf_data_hdr_comm, len))
     393                 :             :         {
     394                 :           0 :             return SDF_DATA_HEADER_COMMENT;
     395                 :             :         }
     396                 :             : 
     397         [ #  # ]:           0 :         if (!inchi_memicmp(p, "CAS", 3))
     398                 :             :         {
     399                 :           0 :             return SDF_DATA_HEADER_CAS;
     400                 :             :         }
     401                 :             :     }
     402                 :             : 
     403                 :           0 :     return SDF_DATA_HEADER;
     404                 :             : }
     405                 :             : 
     406                 :             : /****************************************************************************/
     407                 :           0 : unsigned long SDFileExtractCASNo(char *line)
     408                 :             : {
     409                 :             :     int i, j;
     410                 :             : 
     411                 :           0 :     i = line[0] == '-' ? 1 : 0;
     412                 :             : 
     413         [ #  # ]:           0 :     for (j = i; line[i]; i++)
     414                 :             :     {
     415         [ #  # ]:           0 :         if (isdigit(UCINT line[i]))
     416                 :             :         {
     417                 :           0 :             line[j++] = line[i];
     418                 :             :         }
     419         [ #  # ]:           0 :         else if (line[i] != '-')
     420                 :             :         {
     421                 :           0 :             break;
     422                 :             :         }
     423                 :             :     }
     424                 :             : 
     425                 :           0 :     line[j] = '\0';
     426                 :             : 
     427                 :           0 :     return strtoul(line, NULL, 10);
     428                 :             : }
     429                 :             : 
     430                 :             : /****************************************************************************
     431                 :             :  NUM_LISTS - dynamically growing array of int lists
     432                 :             : ****************************************************************************/
     433                 :         192 : int NumLists_Alloc(NUM_LISTS *num_lists, int nlists)
     434                 :             : {
     435         [ +  - ]:         192 :     if (num_lists)
     436                 :             :     {
     437         [ +  - ]:         192 :         if ((num_lists->lists = (int **)inchi_calloc(nlists, sizeof(int *)))) /* djb-rwth: addressing LLVM warning */
     438                 :             :         {
     439                 :         192 :             num_lists->increment =
     440                 :         192 :                 num_lists->allocated = nlists;
     441                 :         192 :             return 0; /*  ok */
     442                 :             :         }
     443                 :             :     }
     444                 :             : 
     445                 :           0 :     return -1; /*  error */
     446                 :             : }
     447                 :             : 
     448                 :             : /****************************************************************************/
     449                 :           2 : int NumLists_ReAlloc(NUM_LISTS *num_lists)
     450                 :             : {
     451         [ +  - ]:           2 :     if (num_lists)
     452                 :             :     {
     453   [ +  -  +  -  :           2 :         if (num_lists->lists && num_lists->allocated > 0 && num_lists->increment > 0)
                   +  - ]
     454                 :             :         {
     455                 :           2 :             void *p = num_lists->lists;
     456                 :           2 :             if ((num_lists->lists =
     457         [ +  - ]:           2 :                      (int **)inchi_calloc((long long)num_lists->allocated + (long long)num_lists->increment, sizeof(int *)))) /* djb-rwth: cast operators added; addressing LLVM warning */
     458                 :             :             {
     459                 :           2 :                 memcpy(num_lists->lists, p, num_lists->used * sizeof(num_lists->lists[0]));
     460         [ +  - ]:           2 :                 inchi_free(p);
     461                 :           2 :                 num_lists->allocated += num_lists->increment;
     462                 :           2 :                 return 0; /*  ok */
     463                 :             :             }
     464                 :             :         }
     465                 :             :     }
     466                 :             : 
     467                 :           0 :     return -1; /*  error */
     468                 :             : }
     469                 :             : 
     470                 :             : /****************************************************************************/
     471                 :         104 : int NumLists_Append(NUM_LISTS *num_lists, int *list)
     472                 :             : {
     473         [ +  - ]:         104 :     if (num_lists)
     474                 :             :     {
     475         [ +  + ]:         104 :         if (num_lists->used + 1 > num_lists->allocated)
     476                 :             :         {
     477                 :             :             /* need to expand buffer */
     478         [ -  + ]:           2 :             if (NumLists_ReAlloc(num_lists))
     479                 :             :             {
     480                 :           0 :                 return -1; /*  error */
     481                 :             :             }
     482                 :             :         }
     483                 :         104 :         num_lists->lists[num_lists->used++] = list;
     484                 :         104 :         return 0;
     485                 :             :     }
     486                 :             : 
     487                 :           0 :     return -1;
     488                 :             : }
     489                 :             : 
     490                 :             : /****************************************************************************/
     491                 :         192 : void NumLists_Free(NUM_LISTS *num_lists)
     492                 :             : {
     493         [ +  - ]:         192 :     if (num_lists)
     494                 :             :     {
     495                 :             :         int i;
     496         [ +  + ]:         296 :         for (i = 0; i < num_lists->used; i++)
     497         [ +  - ]:         104 :             inchi_free(num_lists->lists[i]); /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
     498         [ +  - ]:         192 :         inchi_free(num_lists->lists);
     499                 :         192 :         memset(num_lists, 0, sizeof(*num_lists)); /* djb-rwth: memset_s C11/Annex K variant? */
     500                 :             :     }
     501                 :         192 : }
     502                 :             : 
     503                 :             : /****************************************************************************
     504                 :             :  INT_ARRAY - dynamically growing array of int
     505                 :             : ****************************************************************************/
     506                 :             : 
     507                 :             : /****************************************************************************
     508                 :             :  Allocate new array, return 0 if OK, -1 otherwise
     509                 :             : ****************************************************************************/
     510                 :         540 : int IntArray_Alloc(INT_ARRAY *items, int nitems)
     511                 :             : {
     512         [ +  - ]:         540 :     if ((items->item = (int *)inchi_calloc(nitems, sizeof(int)))) /* djb-rwth: addressing LLVM warning */
     513                 :             :     {
     514                 :         540 :         items->increment = items->allocated = nitems;
     515                 :         540 :         items->used = 0;
     516                 :         540 :         return 0;
     517                 :             :     }
     518                 :             : 
     519                 :           0 :     return -1;
     520                 :             : }
     521                 :             : 
     522                 :             : /****************************************************************************
     523                 :             :  Expand array, return 0 if OK, -1 otherwise
     524                 :             : ****************************************************************************/
     525                 :           0 : int IntArray_ReAlloc(INT_ARRAY *items)
     526                 :             : {
     527         [ #  # ]:           0 :     if (items)
     528                 :             :     {
     529   [ #  #  #  #  :           0 :         if (items->item && items->allocated > 0 && items->increment > 0)
                   #  # ]
     530                 :             :         {
     531                 :           0 :             void *p = items->item;
     532                 :           0 :             if ((items->item =
     533         [ #  # ]:           0 :                      (int *)inchi_calloc((long long)items->allocated + (long long)items->increment, sizeof(items->item[0])))) /* djb-rwth: cast operators added; addressing LLVM warning */
     534                 :             :             {
     535                 :           0 :                 memcpy(items->item, p, items->used * sizeof(items->item[0]));
     536         [ #  # ]:           0 :                 inchi_free(p);
     537                 :           0 :                 items->allocated += items->increment;
     538                 :           0 :                 return 0;
     539                 :             :             }
     540         [ #  # ]:           0 :             inchi_free(p);
     541                 :             :         }
     542                 :             :     }
     543                 :             : 
     544                 :           0 :     return -1;
     545                 :             : }
     546                 :             : 
     547                 :             : /****************************************************************************
     548                 :             :  Push new item to the end of array
     549                 :             : ****************************************************************************/
     550                 :           0 : int IntArray_Append(INT_ARRAY *items, int new_item)
     551                 :             : {
     552         [ #  # ]:           0 :     if (items)
     553                 :             :     {
     554         [ #  # ]:           0 :         if (items->used + 1 > items->allocated)
     555                 :             :         {
     556                 :             :             /* need to expand buffer */
     557         [ #  # ]:           0 :             if (IntArray_ReAlloc(items))
     558                 :             :             {
     559                 :           0 :                 return -1;
     560                 :             :             }
     561                 :             :         }
     562                 :           0 :         items->item[items->used++] = new_item;
     563                 :           0 :         return 0;
     564                 :             :     }
     565                 :             : 
     566                 :           0 :     return -1;
     567                 :             : }
     568                 :             : 
     569                 :             : /****************************************************************************
     570                 :             : Push new item to the end of array only if it is absent there
     571                 :             : ****************************************************************************/
     572                 :           0 : int IntArray_AppendIfAbsent(INT_ARRAY *items, int new_item)
     573                 :             : {
     574         [ #  # ]:           0 :     if (!is_in_the_ilist(items->item, new_item, items->used))
     575                 :             :     {
     576                 :           0 :         return IntArray_Append(items, new_item);
     577                 :             :     }
     578                 :           0 :     return 0;
     579                 :             : }
     580                 :             : 
     581                 :             : /****************************************************************************/
     582                 :           0 : void IntArray_DebugPrint(INT_ARRAY *items)
     583                 :             : {
     584         [ #  # ]:           0 :     if (items)
     585                 :             :     {
     586                 :             :         int i;
     587         [ #  # ]:           0 :         if (items->used > 0)
     588                 :             :         {
     589         [ #  # ]:           0 :             for (i = 0; i < items->used - 1; i++)
     590                 :             :             {
     591                 :             :                 ITRACE_("%-d, ", items->item[i]);
     592                 :             :             }
     593                 :             :             ITRACE_("%-d\n", items->item[items->used - 1]);
     594                 :             :         }
     595                 :             :         else
     596                 :             :         {
     597                 :             :             ; /*ITRACE_( "[None]\n");*/
     598                 :             :         }
     599                 :             :     }
     600                 :           0 : }
     601                 :             : 
     602                 :             : /****************************************************************************/
     603                 :           0 : void IntArray_Reset(INT_ARRAY *items)
     604                 :             : {
     605                 :           0 :     items->used = 0;
     606                 :           0 :     return;
     607                 :             : }
     608                 :             : 
     609                 :             : /****************************************************************************/
     610                 :         540 : void IntArray_Free(INT_ARRAY *items)
     611                 :             : {
     612         [ +  - ]:         540 :     if (items)
     613                 :             :     {
     614         [ +  - ]:         540 :         if (items->item)
     615                 :             :         {
     616         [ +  - ]:         540 :             inchi_free(items->item);
     617                 :             :         }
     618                 :         540 :         memset(items, 0, sizeof(*items)); /* djb-rwth: memset_s C11/Annex K variant? */
     619                 :             :     }
     620                 :         540 :     return;
     621                 :             : }
     622                 :             : 
     623                 :             : /****************************************************************************
     624                 :             :     MOL_FMT_SGROUPS - dynamically growing array of pointers to SGroups
     625                 :             : ****************************************************************************/
     626                 :             : 
     627                 :             : /*
     628                 :             :     SGroup
     629                 :             : */
     630                 :             : 
     631                 :             : /****************************************************************************
     632                 :             :  Allocate new array Sgroup, return 0 if OK, -1 otherwise
     633                 :             : ****************************************************************************/
     634                 :           0 : int MolFmtSgroup_Create(MOL_FMT_SGROUP **sgroup, int id, int type)
     635                 :             : {
     636                 :           0 :     *sgroup = (MOL_FMT_SGROUP *)inchi_calloc(1, sizeof(MOL_FMT_SGROUP));
     637         [ #  # ]:           0 :     if (*sgroup)
     638                 :             :     {
     639   [ #  #  #  # ]:           0 :         if (IntArray_Alloc(&((*sgroup)->alist), 8) ||
     640                 :           0 :             IntArray_Alloc(&((*sgroup)->blist), 8))
     641                 :             :         {
     642                 :           0 :             MolFmtSgroup_Free(*sgroup);
     643                 :           0 :             return -1;
     644                 :             :         }
     645                 :           0 :         (*sgroup)->id = id;
     646                 :           0 :         (*sgroup)->type = type;
     647                 :             : 
     648                 :           0 :         (*sgroup)->subtype = 0;
     649                 :           0 :         (*sgroup)->conn = 0;
     650                 :           0 :         (*sgroup)->label = 0;
     651                 :             : 
     652                 :           0 :         return 0;
     653                 :             :     }
     654                 :           0 :     return -1;
     655                 :             : }
     656                 :             : 
     657                 :             : /****************************************************************************/
     658                 :           0 : void MolFmtSgroup_Free(MOL_FMT_SGROUP *sgroup)
     659                 :             : {
     660         [ #  # ]:           0 :     if (sgroup)
     661                 :             :     {
     662                 :           0 :         IntArray_Free(&(sgroup->alist));
     663                 :           0 :         IntArray_Free(&(sgroup->blist));
     664         [ #  # ]:           0 :         inchi_free(sgroup);
     665                 :             :     }
     666                 :           0 : }
     667                 :             : 
     668                 :             : /*
     669                 :             :     SGroups
     670                 :             : */
     671                 :             : 
     672                 :             : /****************************************************************************
     673                 :             :  Allocate new array of Sgroups, return 0 if OK, -1 otherwise
     674                 :             : ****************************************************************************/
     675                 :          54 : int MolFmtSgroups_Alloc(MOL_FMT_SGROUPS *sgroups, int nsgroups)
     676                 :             : {
     677         [ +  - ]:          54 :     if (sgroups)
     678                 :             :     {
     679         [ +  - ]:          54 :         if (NULL != (sgroups->group = (MOL_FMT_SGROUP **)inchi_calloc(nsgroups, sizeof(MOL_FMT_SGROUP *))))
     680                 :             :         {
     681                 :             :             /* ITRACE_( "\nAllocated sgroups->group at %-p \n", sgroups->group ); */
     682                 :          54 :             sgroups->increment = sgroups->allocated = nsgroups;
     683                 :          54 :             return 0;
     684                 :             :         }
     685                 :             :     }
     686                 :             : 
     687                 :           0 :     return -1;
     688                 :             : }
     689                 :             : 
     690                 :             : /****************************************************************************
     691                 :             :  Expand array of Sgroups, return 0 if OK, -1 otherwise
     692                 :             : ****************************************************************************/
     693                 :           0 : int MolFmtSgroups_ReAlloc(MOL_FMT_SGROUPS *sgroups)
     694                 :             : {
     695         [ #  # ]:           0 :     if (sgroups)
     696                 :             :     {
     697   [ #  #  #  #  :           0 :         if (sgroups->group && sgroups->allocated > 0 && sgroups->increment > 0)
                   #  # ]
     698                 :             :         {
     699                 :           0 :             void *p = sgroups->group;
     700         [ #  # ]:           0 :             if ((sgroups->group = (MOL_FMT_SGROUP **)inchi_calloc( (long long)sgroups->allocated + (long long)sgroups->increment,
     701                 :             :                 sizeof( sgroups->group[0] ) ))) /* djb-rwth: cast operators added; addressing LLVM warning */
     702                 :             :             {
     703                 :           0 :                 memcpy(sgroups->group, p, sgroups->used * sizeof(sgroups->group[0]));
     704         [ #  # ]:           0 :                 inchi_free(p);
     705                 :           0 :                 sgroups->allocated += sgroups->increment;
     706                 :           0 :                 return 0; /*  ok */
     707                 :             :             }
     708                 :             :         }
     709                 :             :     }
     710                 :             : 
     711                 :           0 :     return -1;
     712                 :             : }
     713                 :             : 
     714                 :             : /****************************************************************************/
     715                 :           0 : int MolFmtSgroups_Append(MOL_FMT_SGROUPS *sgroups, int id, int type)
     716                 :             : {
     717         [ #  # ]:           0 :     if (sgroups)
     718                 :             :     {
     719                 :             :         /* Make new Sgroup */
     720                 :           0 :         MOL_FMT_SGROUP *sgroup = NULL;
     721         [ #  # ]:           0 :         if (0 != MolFmtSgroup_Create(&sgroup, id, type))
     722                 :             :         {
     723                 :           0 :             return -1;
     724                 :             :         }
     725                 :             :         /* Add new created Sgroup to Sgroups */
     726         [ #  # ]:           0 :         if (sgroups->used + 1 > sgroups->allocated)
     727                 :             :         {
     728                 :             :             /* expand buffer */
     729         [ #  # ]:           0 :             if (MolFmtSgroups_ReAlloc(sgroups))
     730                 :             :             {
     731                 :           0 :                 MolFmtSgroup_Free(sgroup); /* djb-rwth: avoiding memory leak */
     732                 :           0 :                 return -1; /*  no RAM */
     733                 :             :             }
     734                 :             :         }
     735                 :           0 :         sgroups->group[sgroups->used++] = sgroup;
     736                 :             : 
     737                 :             :         /*
     738                 :             :         {
     739                 :             :         int num = sgroups->used-1;
     740                 :             :         printf("\nCreated/added Sgroup: id=%-d ( num in Sgroups=%-d ) of type=%-d \n", sgroups->group[num]->id, num, sgroups->group[num]->type );
     741                 :             :         }
     742                 :             :         */
     743                 :             : 
     744                 :           0 :         return 0;
     745                 :             :     }
     746                 :             : 
     747                 :           0 :     return -1;
     748                 :             : }
     749                 :             : 
     750                 :             : /****************************************************************************/
     751                 :          54 : void MolFmtSgroups_Free(MOL_FMT_SGROUPS *sgroups)
     752                 :             : {
     753         [ +  - ]:          54 :     if (sgroups)
     754                 :             :     {
     755                 :             :         int i;
     756         [ -  + ]:          54 :         for (i = 0; i < sgroups->used; i++)
     757                 :             :         {
     758                 :           0 :             MolFmtSgroup_Free(sgroups->group[i]);
     759                 :             :         }
     760                 :             : 
     761                 :             :         /* ITRACE_( "\nAbout to free sgroups->group at %-p\n", sgroups->group ); */
     762         [ +  - ]:          54 :         inchi_free(sgroups->group);
     763                 :             : 
     764                 :          54 :         memset(sgroups, 0, sizeof(MOL_FMT_SGROUPS)); /* djb-rwth: memset_s C11/Annex K variant? */
     765                 :             :     }
     766                 :          54 : }
     767                 :             : 
     768                 :             : /****************************************************************************/
     769                 :           0 : int MolFmtSgroups_GetIndexBySgroupId(int id, MOL_FMT_SGROUPS *sgroups)
     770                 :             : {
     771                 :             :     int i;
     772         [ #  # ]:           0 :     for (i = 0; i < sgroups->used; i++)
     773                 :             :     {
     774         [ #  # ]:           0 :         if (sgroups->group[i]->id == id)
     775                 :             :         {
     776                 :           0 :             return i;
     777                 :             :         }
     778                 :             :     }
     779                 :           0 :     return -1;
     780                 :             : }
     781                 :             : 
     782                 :             : /****************************************************************************/
     783                 :           0 : int OrigAtData_WriteToSDfile(const ORIG_ATOM_DATA *inp_at_data,
     784                 :             :                              INCHI_IOSTREAM *fcb,
     785                 :             :                              const char *name,
     786                 :             :                              const char *comment,
     787                 :             :                              int bChiralFlag,
     788                 :             :                              int bAtomsDT,
     789                 :             :                              const char *szLabel,
     790                 :             :                              const char *szValue)
     791                 :             : {
     792                 :           0 :     int num_bonds = 0, nNumAddLines = 0, nNumIsoLines = 0, nNumChargeLines = 0,
     793                 :           0 :         nNumRadicalLines = 0, nNumAliasLines = 0, ret = 0;
     794                 :             :     INT_ARRAY written_bond_ends;
     795                 :             : 
     796                 :           0 :     OrigAtData_WriteToSDfileHeaderAndCountThings((ORIG_ATOM_DATA *)inp_at_data,
     797                 :             :                                                  fcb, name, comment,
     798                 :             :                                                  bChiralFlag, bAtomsDT,
     799                 :             :                                                  szLabel, szValue,
     800                 :             :                                                  &nNumAliasLines,
     801                 :             :                                                  &nNumChargeLines,
     802                 :             :                                                  &nNumRadicalLines,
     803                 :             :                                                  &nNumIsoLines,
     804                 :             :                                                  &nNumAddLines,
     805                 :             :                                                  &num_bonds);
     806                 :             : 
     807   [ #  #  #  # ]:           0 :     if (IntArray_Alloc(&written_bond_ends, num_bonds ? num_bonds : 255))
     808                 :             :     {
     809                 :           0 :         ret = _IS_ERROR;
     810                 :           0 :         goto exit_function;
     811                 :             :     }
     812                 :             : 
     813                 :           0 :     OrigAtData_WriteToSDfileAtomsBlock(inp_at_data, fcb, name, comment,
     814                 :             :                                        bAtomsDT, szLabel, szValue);
     815                 :             : 
     816                 :           0 :     OrigAtData_WriteToSDfileBondsBlock(inp_at_data, fcb, name, comment,
     817                 :             :                                        szLabel, szValue, &written_bond_ends);
     818                 :             : 
     819         [ #  # ]:           0 :     if (nNumAddLines)
     820                 :             :     {
     821                 :           0 :         OrigAtData_WriteToSDfileAdditionalLines(inp_at_data, fcb, name, comment,
     822                 :             :                                                 bAtomsDT, szLabel, szValue,
     823                 :             :                                                 nNumAliasLines, nNumChargeLines,
     824                 :             :                                                 nNumRadicalLines, nNumIsoLines,
     825                 :             :                                                 &written_bond_ends);
     826                 :             :     }
     827                 :             : 
     828                 :             :     /* Add field with label/ID if applicable and mark the end of record */
     829   [ #  #  #  # ]:           0 :     if (szValue && szValue[0])
     830                 :             :     {
     831   [ #  #  #  # ]:           0 :         if (szLabel && szLabel[0])
     832                 :             :         {
     833                 :           0 :             inchi_ios_print_nodisplay(fcb, "> <%s>\n", szLabel);
     834                 :             :         }
     835                 :             :         else
     836                 :             :         {
     837                 :           0 :             inchi_ios_print_nodisplay(fcb, "> <ID>\n");
     838                 :             :         }
     839                 :           0 :         inchi_ios_print_nodisplay(fcb, " %s\n\n", szValue);
     840                 :             :     }
     841                 :           0 :     inchi_ios_print_nodisplay(fcb, "$$$$\n");
     842                 :             : 
     843                 :           0 : exit_function:
     844                 :           0 :     IntArray_Free(&written_bond_ends);
     845                 :             : 
     846                 :           0 :     return ret;
     847                 :             : }
     848                 :             : 
     849                 :             : /****************************************************************************
     850                 :             :  OrigAtData : Write To SDfile : Atoms Block
     851                 :             : ****************************************************************************/
     852                 :           0 : int OrigAtData_WriteToSDfileHeaderAndCountThings(const ORIG_ATOM_DATA *inp_at_data,
     853                 :             :                                                  INCHI_IOSTREAM *fcb,
     854                 :             :                                                  const char *name,
     855                 :             :                                                  const char *comment,
     856                 :             :                                                  int bChiralFlag,
     857                 :             :                                                  int bAtomsDT,
     858                 :             :                                                  const char *szLabel,
     859                 :             :                                                  const char *szValue,
     860                 :             :                                                  int *nNumAliasLines,
     861                 :             :                                                  int *nNumChargeLines,
     862                 :             :                                                  int *nNumRadicalLines,
     863                 :             :                                                  int *nNumIsoLines,
     864                 :             :                                                  int *nNumAddLines,
     865                 :             :                                                  int *num_bonds)
     866                 :             : {
     867                 :           0 :     int i, ret = 0;
     868                 :             :     int bAtomNeedsAlias,
     869                 :           0 :         nNumNecessaryIsoLines = 0,
     870                 :           0 :         nNumNecessaryChgLines = 0,
     871                 :           0 :         nNumNecessaryRadLines = 0;
     872                 :           0 :     int num_atoms = inp_at_data->num_inp_atoms;
     873                 :           0 :     int bV2000 = SDF_OUTPUT_V2000;
     874                 :           0 :     const inp_ATOM *at = inp_at_data->at;
     875                 :             : 
     876                 :             :     {
     877                 :             :         char strLocName[82];
     878                 :           0 :         memset(strLocName, 0, sizeof(strLocName)); /* djb-rwth: memset_s C11/Annex K variant? */
     879   [ #  #  #  # ]:           0 :         if (name && *name)
     880                 :             :         {
     881                 :           0 :             strncpy(strLocName, name, 80);
     882                 :             :         }
     883                 :           0 :         inchi_ios_print_nodisplay(fcb, "%s\n", strLocName);
     884                 :             :     }
     885                 :             : 
     886                 :             :     /**********************************************************************/
     887                 :             :     /**                                                                  **/
     888                 :             :     /** Important: Atoms with alias cannot have charge, radical          **/
     889                 :             :     /**            isotope differences are allowed                       **/
     890                 :             :     /**                                                                  **/
     891                 :             :     /**            Atoms with alias cannot be abnormal.                  **/
     892                 :             :     /**                                                                  **/
     893                 :             :     /** Abnormal atoms are atoms which need M  CHG, M RAD, M  ISO        **/
     894                 :             :     /**                                                                  **/
     895                 :             :     /** Output aliased atoms if they have implicit D or T                **/
     896                 :             :     /**                                                                  **/
     897                 :             :     /**********************************************************************/
     898                 :             : 
     899                 :             :     /*                                    F10.5     F12.5       I6
     900                 :             :                      IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR
     901                 :             :     inchi_ios_eprint( fcb,"NISTTRANHP09089809272D 1   1.0         0.0    %6ld\n", lEpa);*/
     902                 :             :     /*^^^
     903                 :             :     inchi_ios_print_nodisplay( fcb,"  %s v%s SDfile Output                       \n", INCHI_NAME, INCHI_VERSION);
     904                 :             : 
     905                 :             :     Changed 01/10/2009 to conform CTFile specification (by Symyx request)*/
     906                 :             : 
     907                 :           0 :     inchi_ios_print_nodisplay(fcb,
     908                 :             :                               /*   IIPPPPPPPPMMDDYYHHmmddSSssssssssssEEEEEEEEEEEERRRRRR*/
     909                 :             :                               "  InChIV10                                     \n");
     910                 :             :     /*y_fprintf(fcb, "  -CPSS-  1213981200n\n");*/
     911                 :             : 
     912                 :             :     {
     913                 :             :         char strLocName[82];
     914                 :             : 
     915                 :           0 :         memset(strLocName, 0, sizeof(strLocName)); /* djb-rwth: memset_s C11/Annex K variant? */
     916   [ #  #  #  # ]:           0 :         if (comment && *comment)
     917                 :             :         {
     918                 :           0 :             strncpy(strLocName, comment, 80);
     919                 :             :         }
     920                 :           0 :         inchi_ios_print_nodisplay(fcb, "%s\n", strLocName);
     921                 :             :     }
     922                 :             : 
     923                 :           0 :     *num_bonds = 0;
     924         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
     925                 :             :     {
     926                 :           0 :         (*num_bonds) += at[i].valence;
     927                 :             :     }
     928                 :           0 :     (*num_bonds) /= 2;
     929                 :             : 
     930                 :             :     /*find if we need "M  CHG" and "M  RAD"*/
     931         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
     932                 :             :     {
     933         [ #  # ]:           0 :         if ((bAtomNeedsAlias = ALIASED_AT(i))) /* djb-rwth: addressing LLVM warning */
     934                 :             :         {
     935                 :             :             /* has isotopic implicit D or T; ignoring pure 1H */
     936                 :           0 :             (*nNumAliasLines) += 2 * bAtomNeedsAlias;
     937                 :             :         }
     938                 :             :         else
     939                 :             :         {
     940                 :             :             /* abnormal means atom needs CHG, RAD, or ISO entry */
     941                 :             :             /* nNumAddLines    += ABNORMAL_AT(i); */
     942                 :             :             /* nNumIso         += ( 0 == strcmp( at[i].elname, "D" ) || ( 0 == strcmp( at[i].elname, "T" ) || at[i].iso_atw_diff ) ); */
     943                 :             :             /* nNumAddIso      += at[i].iso_atw_diff && (at[i].iso_atw_diff == 1 || at[i].iso_atw_diff < -3 || at[i].iso_atw_diff > 5 ); */
     944   [ #  #  #  #  :           0 :             nNumNecessaryIsoLines += ABNORMAL_ISO(i);
                   #  # ]
     945                 :           0 :             nNumNecessaryChgLines += ABNORMAL_CHG(i);
     946   [ #  #  #  # ]:           0 :             nNumNecessaryRadLines += ABNORMAL_RAD(i);
     947   [ #  #  #  #  :           0 :             (*nNumIsoLines) += ANY_ISO(i, bAtomsDT);
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                      # ]
     948                 :           0 :             (*nNumChargeLines) += ANY_CHG(i);
     949   [ #  #  #  # ]:           0 :             (*nNumRadicalLines) += ANY_RAD(i);
     950                 :             :         }
     951                 :             :     }
     952                 :             : 
     953                 :           0 :     *nNumChargeLines = (*nNumChargeLines + 7) / 8;
     954                 :           0 :     *nNumRadicalLines = (*nNumRadicalLines + 7) / 8;
     955                 :           0 :     *nNumIsoLines = (*nNumIsoLines + 7) / 8;
     956                 :             : 
     957         [ #  # ]:           0 :     if (!bV2000)
     958                 :             :     {
     959   [ #  #  #  # ]:           0 :         if (!nNumNecessaryRadLines && !nNumNecessaryChgLines)
     960                 :             :         {
     961                 :           0 :             *nNumRadicalLines = 0;
     962                 :           0 :             *nNumChargeLines = 0;
     963                 :             :         }
     964         [ #  # ]:           0 :         if (!nNumNecessaryIsoLines)
     965                 :             :         {
     966                 :           0 :             *nNumIsoLines = 0;
     967                 :             :         }
     968                 :             :     }
     969                 :             : 
     970                 :             :     /* recalculate number of added lines */
     971                 :           0 :     *nNumAddLines = *nNumChargeLines + *nNumRadicalLines + *nNumIsoLines + *nNumAliasLines; /* 1 for M  END*/
     972                 :             : 
     973   [ #  #  #  # ]:           0 :     if (*nNumAddLines || bV2000)
     974                 :             :     {
     975                 :           0 :         *nNumAddLines += 1; /* add 1 for "M  END" line*/
     976                 :             :     }
     977                 :             : 
     978                 :             :     /*                         aaabbblllfffcccsssxxxrrrpppiiimmmvvvvvv                                      */
     979                 :             : 
     980                 :           0 :     inchi_ios_print_nodisplay(fcb, "%3d%3d  0  0%3d  0  0  0  0  0%3d%s\n",
     981         [ #  # ]:           0 :                               num_atoms, *num_bonds, bChiralFlag ? 1 : 0, *nNumAddLines, *nNumAddLines ? " V2000" : "");
     982                 :             : 
     983                 :           0 :     return ret;
     984                 :             : }
     985                 :             : 
     986                 :             : /****************************************************************************
     987                 :             :  OrigAtData : Write To SDfile : Atoms Block
     988                 :             : ****************************************************************************/
     989                 :           0 : int OrigAtData_WriteToSDfileAtomsBlock(const ORIG_ATOM_DATA *inp_at_data,
     990                 :             :                                         INCHI_IOSTREAM       *fcb,
     991                 :             :                                         const char           *name,
     992                 :             :                                         const char           *comment,
     993                 :             :                                         int                  bAtomsDT,
     994                 :             :                                         const char           *szLabel,
     995                 :             :                                         const char           *szValue)
     996                 :             : {
     997                 :           0 :     int i, ret = 0;
     998                 :             :     int bAtomNeedsAlias;
     999                 :             :     /* djb-rwth: removing redundant variables */
    1000                 :           0 :     int num_atoms = inp_at_data->num_inp_atoms;
    1001                 :           0 :     const inp_ATOM *at = inp_at_data->at;
    1002                 :             :     double x, y, z;
    1003                 :             : 
    1004         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
    1005                 :             :     {
    1006                 :           0 :         char elname[ATOM_EL_LEN] = "\0\0\0\0\0";
    1007                 :           0 :         int iso = 0;
    1008                 :           0 :         int charge = 0;
    1009                 :           0 :         int valence = 0;
    1010   [ #  #  #  #  :           0 :         int nIsotopeH = IS_DEUTERIUM( i ) ? 1 : IS_TRITIUM( i ) ? 2 : 0;
          #  #  #  #  #  
                #  #  # ]
    1011                 :             :         int bonds_val;
    1012                 :           0 :         bAtomNeedsAlias = ALIASED_AT( i );
    1013                 :           0 :         memset( elname, 0, sizeof( elname ) ); /* djb-rwth: memset_s C11/Annex K variant? */
    1014                 :             : 
    1015         [ #  # ]:           0 :         if (bAtomNeedsAlias)
    1016                 :             :         {
    1017                 :             :             /* alias */
    1018                 :           0 :             strcpy(elname, "C");
    1019                 :             :         }
    1020                 :             :         else
    1021                 :             :         {
    1022                 :             :             /* isotope*/
    1023         [ #  # ]:           0 :             if (nIsotopeH)
    1024                 :             :             {
    1025   [ #  #  #  # ]:           0 :                 strcpy(elname, bAtomsDT ? (nIsotopeH == 1 ? "D" : "T") : "H");
    1026                 :             :             }
    1027                 :             :             else
    1028                 :             :             {
    1029                 :           0 :                 strncpy(elname, at[i].elname, sizeof(elname) - 1);
    1030                 :           0 :                 elname[sizeof(elname) - 1] = 0; /* adding zero termination after strncpy */
    1031                 :             :             }
    1032   [ #  #  #  #  :           0 :             if (!ABNORMAL_CHG(i) && !ANY_RAD(i))
                   #  # ]
    1033                 :             :             {
    1034                 :             :                 /* charge*/
    1035                 :             :                 /* Only atoms without alias can be here*/
    1036   [ #  #  #  #  :           0 :                 switch (at[i].charge)
             #  #  #  # ]
    1037                 :             :                 {
    1038                 :           0 :                 case 3:
    1039                 :           0 :                     charge = 1;
    1040                 :           0 :                     break;
    1041                 :           0 :                 case 2:
    1042                 :           0 :                     charge = 2;
    1043                 :           0 :                     break;
    1044                 :           0 :                 case 1:
    1045                 :           0 :                     charge = 3;
    1046                 :           0 :                     break;
    1047                 :           0 :                 case -1:
    1048                 :           0 :                     charge = 5;
    1049                 :           0 :                     break;
    1050                 :           0 :                 case -2:
    1051                 :           0 :                     charge = 6;
    1052                 :           0 :                     break;
    1053                 :           0 :                 case -3:
    1054                 :           0 :                     charge = 7;
    1055                 :           0 :                     break;
    1056                 :           0 :                 case 0:
    1057                 :           0 :                     charge = 0;
    1058                 :           0 :                     break;
    1059                 :           0 :                 default:
    1060                 :           0 :                     break; /* djb-rwth: removing redundant code */
    1061                 :             :                 }
    1062                 :             :             }
    1063                 :             : 
    1064                 :             :             /* radical*/
    1065   [ #  #  #  #  :           0 :             if (ANY_RAD(i) && !ANY_CHG(i))
                   #  # ]
    1066                 :             :             {
    1067         [ #  # ]:           0 :                 if (at[i].radical == RADICAL_DOUBLET)
    1068                 :             :                 {
    1069                 :           0 :                     charge = 4;
    1070                 :             :                 }
    1071                 :             :             }
    1072                 :             :         }
    1073                 :             : 
    1074                 :             :         /* allow isotopic shift for aliased atoms */
    1075   [ #  #  #  #  :           0 :         if (NORMAL_ISO(i, bAtomsDT))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  # ]
    1076                 :             :         {
    1077         [ #  # ]:           0 :             iso = at[i].iso_atw_diff > 0 ? at[i].iso_atw_diff - 1 :
    1078         [ #  # ]:           0 :                     at[i].iso_atw_diff < 0 ? at[i].iso_atw_diff :
    1079                 :             :                         nIsotopeH ? nIsotopeH : 0; /* djb-rwth: removing redundant code */
    1080                 :             :         }
    1081                 :             : 
    1082                 :           0 :         x = at[i].x;
    1083                 :           0 :         y = at[i].y;
    1084                 :           0 :         z = at[i].z;
    1085                 :             : 
    1086                 :             :         /* valence -- set only if needed */
    1087                 :           0 :         bonds_val = nBondsValenceInpAt(at + i, NULL, NULL);
    1088                 :           0 :         valence = needed_unusual_el_valence(at[i].el_number, at[i].charge, at[i].radical,
    1089                 :           0 :                                             at[i].chem_bonds_valence, bonds_val, NUMH(at, i), at[i].valence);
    1090                 :             : 
    1091         [ #  # ]:           0 :         if (valence < 0)
    1092                 :             :         {
    1093                 :           0 :             valence = 15; /* means no bonds nor H */
    1094                 :             :         }
    1095                 :             : 
    1096                 :             :         /* Convert "Zz" to "*" element symbol */
    1097                 :             : 
    1098   [ #  #  #  # ]:           0 :         if (!strcmp(elname, "Zz") || !strcmp(elname, "Zy"))
    1099                 :             :         {
    1100                 :           0 :             strcpy(elname, "*");
    1101                 :             :         }
    1102                 :             : 
    1103                 :             :         /*inchi_ios_eprint(fcb,"%10.4f%10.4f%10.4f %-3.3s%2d%3d  0     0  0  0  0  0  0\n",*/
    1104                 :             :         /*    (float)at[i].x, (float)(-at[i].y), fzero, at[i].elname, iso, charge);*/
    1105                 :             :         /*              xxxxxxyyyyyyzzzzzz aaa____ddcccsssnnnbbbvvvrrriiimmmeee  */
    1106                 :           0 :         inchi_ios_print_nodisplay(fcb, "%10.4f%10.4f%10.4f %-3.3s%2d%3d  0     0%3d  0  0  0  0\n",
    1107                 :             :                                   x, y, z, elname, (int)iso, (int)charge, valence /* at[i].special*/);
    1108                 :             : 
    1109                 :             :         /* Reflect image against x-axis;                                    */
    1110                 :             :         /* when transforming MOLfile back to STDATA in mol_to_stdata(...),  */
    1111                 :             :         /* make one more reflection to restore original orientation.        */
    1112                 :             :         /* Reason: in MS Search y-axis is directed from top to bottom,      */
    1113                 :             :         /*         while in MOLfile y-axis goes from bottom to top.         */
    1114                 :             :     }
    1115                 :             : 
    1116                 :           0 :     return ret;
    1117                 :             : }
    1118                 :             : 
    1119                 :             : /****************************************************************************
    1120                 :             :  OrigAtData : Write To SDfile : Bonds Block
    1121                 :             : ****************************************************************************/
    1122                 :           0 : int OrigAtData_WriteToSDfileBondsBlock( const ORIG_ATOM_DATA *inp_at_data,
    1123                 :             :                                         INCHI_IOSTREAM       *fcb,
    1124                 :             :                                         const char           *name,
    1125                 :             :                                         const char           *comment,
    1126                 :             :                                         const char           *szLabel,
    1127                 :             :                                         const char           *szValue,
    1128                 :             :                                         INT_ARRAY            *written_bond_ends )
    1129                 :             : {
    1130                 :           0 :     int i, j, k, ret = 0;
    1131                 :           0 :     int num_atoms = inp_at_data->num_inp_atoms;
    1132                 :           0 :     const inp_ATOM *at = inp_at_data->at;
    1133                 :             : 
    1134                 :             :     /* bonds*/
    1135         [ #  # ]:           0 :     for (i = 0; i < num_atoms; i++)
    1136                 :             :     {
    1137         [ #  # ]:           0 :         for (j = 0; j < at[i].valence; j++)
    1138                 :             :         {
    1139         [ #  # ]:           0 :             if (i < at[i].neighbor[j])
    1140                 :             :             {
    1141                 :             :                 unsigned a1, a2;
    1142         [ #  # ]:           0 :                 if ((k = at[i].bond_stereo[j])) /* djb-rwth: addressing LLVM warning */
    1143                 :             :                 {
    1144                 :             :                     /* bond stereo */
    1145         [ #  # ]:           0 :                     if (k < 0)
    1146                 :             :                     {
    1147                 :             :                         /* transposition */
    1148                 :           0 :                         a1 = (unsigned)(at[i].neighbor[j] + 1);
    1149                 :           0 :                         a2 = (unsigned)(i + 1);
    1150                 :           0 :                         inchi_ios_print_nodisplay(fcb, "%3u%3u%3u%3u  0  0  0\n",
    1151                 :           0 :                                                   a1, a2, (unsigned)(at[i].bond_type[j]), (unsigned)abs(k));
    1152                 :             :                     }
    1153                 :             :                     else
    1154                 :             :                     {
    1155                 :             :                         /* no transposition*/
    1156                 :           0 :                         a1 = (unsigned)(i + 1);
    1157                 :           0 :                         a2 = (unsigned)(at[i].neighbor[j] + 1);
    1158                 :           0 :                         inchi_ios_print_nodisplay(fcb, "%3u%3u%3u%3u  0  0  0\n",
    1159                 :           0 :                                                   a1, a2, (unsigned)(at[i].bond_type[j]), (unsigned)abs(k));
    1160                 :             :                     }
    1161                 :             :                 }
    1162                 :             :                 else
    1163                 :             :                 {
    1164                 :           0 :                     a1 = (unsigned)(i + 1);
    1165                 :           0 :                     a2 = (unsigned)(at[i].neighbor[j] + 1);
    1166                 :           0 :                     inchi_ios_print_nodisplay(fcb, "%3u%3u%3u  0  0  0  0\n",
    1167                 :           0 :                                               a1, a2, (unsigned)(at[i].bond_type[j]));
    1168                 :             :                 }
    1169                 :             : 
    1170                 :           0 :                 IntArray_Append(written_bond_ends, a1);
    1171                 :           0 :                 IntArray_Append(written_bond_ends, a2);
    1172                 :             :             }
    1173                 :             :         }
    1174                 :             :     }
    1175                 :             : 
    1176                 :           0 :     return ret;
    1177                 :             : }
    1178                 :             : 
    1179                 :             : /****************************************************************************
    1180                 :             :  OrigAtData : Write To SDfile : Additional Lines
    1181                 :             : ****************************************************************************/
    1182                 :           0 : int OrigAtData_WriteToSDfileAdditionalLines( const ORIG_ATOM_DATA *inp_at_data,
    1183                 :             :                                              INCHI_IOSTREAM       *fcb,
    1184                 :             :                                              const char           *name,
    1185                 :             :                                              const char           *comment,
    1186                 :             :                                              int                  bAtomsDT,
    1187                 :             :                                              const char           *szLabel,
    1188                 :             :                                              const char           *szValue,
    1189                 :             :                                              int                  nNumAliasLines,
    1190                 :             :                                              int                  nNumChargeLines,
    1191                 :             :                                              int                  nNumRadicalLines,
    1192                 :             :                                              int                  nNumIsoLines,
    1193                 :             :                                              INT_ARRAY            *written_bond_ends )
    1194                 :             : {
    1195                 :             :     char str_m[66], entry[25];
    1196                 :           0 :     int i, num_m, k, j, ret = 0;
    1197                 :             : 
    1198         [ #  # ]:           0 :     if (inp_at_data) /* djb-rwth: fixing a NULL pointer dereference */
    1199                 :             :     {
    1200                 :           0 :         int num_atoms = inp_at_data->num_inp_atoms;
    1201   [ #  #  #  #  :           0 :         int is_polymer = inp_at_data && inp_at_data->polymer && inp_at_data->polymer->n > 0 && inp_at_data->valid_polymer;
             #  #  #  # ]
    1202                 :           0 :         const inp_ATOM *at = inp_at_data->at;
    1203                 :             : 
    1204                 :             :         /* Aliases. 5-3-99 DCh.*/
    1205         [ #  # ]:           0 :         if (nNumAliasLines)
    1206                 :             :         {
    1207                 :           0 :             num_m = 0;
    1208         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    1209                 :             :             {
    1210         [ #  # ]:           0 :                 if (ALIASED_AT(i))
    1211                 :             :                 {
    1212                 :             :                     int len;
    1213                 :           0 :                     inchi_ios_print_nodisplay(fcb, "A  %d\n", i + 1);
    1214                 :           0 :                     num_m++;
    1215                 :           0 :                     len = sprintf(str_m, "%s", at[i].elname);
    1216                 :             :                     /* add isotopic H to the alias */
    1217         [ #  # ]:           0 :                     for (k = 0; k < NUM_H_ISOTOPES; k++)
    1218                 :             :                     {
    1219         [ #  # ]:           0 :                         int num_H = at[i].num_iso_H[k] + (k ? 0 : at[i].num_H);
    1220         [ #  # ]:           0 :                         if (num_H)
    1221                 :             :                         {
    1222   [ #  #  #  #  :           0 :                             len += sprintf(str_m + len, "%s", k == 0 ? "H" : k == 1 ? "D" : k == 2 ? "T" : "?");
                   #  # ]
    1223         [ #  # ]:           0 :                             if (num_H != 1)
    1224                 :             :                             {
    1225                 :           0 :                                 len += sprintf(str_m + len, "%d", num_H);
    1226                 :             :                             }
    1227                 :             :                         }
    1228                 :             :                     }
    1229                 :             : 
    1230                 :             :                     /* Add charge to the Alias */
    1231         [ #  # ]:           0 :                     if (at[i].charge)
    1232                 :             :                     {
    1233         [ #  # ]:           0 :                         len += sprintf(str_m + len, "%s", at[i].charge > 0 ? "+" : "-");
    1234         [ #  # ]:           0 :                         if (1 < (j = abs(at[i].charge)))
    1235                 :             :                         {
    1236                 :           0 :                             len += sprintf(str_m + len, "%d", j);
    1237                 :             :                         }
    1238                 :             :                     }
    1239                 :             : 
    1240                 :             :                     /* Add radical to the Alias */
    1241         [ #  # ]:           0 :                     if (at[i].radical == RADICAL_SINGLET)
    1242                 :             :                     {
    1243                 :           0 :                         len += sprintf(str_m + len, "%s", ":");
    1244                 :             :                     }
    1245         [ #  # ]:           0 :                     else if (at[i].radical == RADICAL_DOUBLET)
    1246                 :             :                     {
    1247                 :           0 :                         len += sprintf(str_m + len, "%s", "^");
    1248                 :             :                     }
    1249         [ #  # ]:           0 :                     else if (at[i].radical == RADICAL_TRIPLET)
    1250                 :             :                     {
    1251                 :           0 :                         len += sprintf(str_m + len, "%s", "^^");
    1252                 :             :                     }
    1253                 :           0 :                     inchi_ios_print_nodisplay(fcb, "%s\n", str_m);
    1254                 :           0 :                     num_m++;
    1255                 :             :                 }
    1256                 :             :             }
    1257                 :             : 
    1258         [ #  # ]:           0 :             if (num_m != nNumAliasLines)
    1259                 :             :             {
    1260                 :             :                 /* error in lines counting*/
    1261                 :           0 :                 ret++;
    1262                 :             :             }
    1263                 :             :         }
    1264                 :             : 
    1265                 :             :         /* charges*/
    1266                 :           0 :         str_m[0] = 0;
    1267                 :           0 :         num_m = 0;
    1268         [ #  # ]:           0 :         if (nNumChargeLines)
    1269                 :             :         {
    1270         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    1271                 :             :             {
    1272   [ #  #  #  # ]:           0 :                 if (at[i].charge && !ALIASED_AT(i))
    1273                 :             :                 {
    1274                 :           0 :                     sprintf(entry, " %3d %3d", i + 1, (int)at[i].charge);
    1275                 :           0 :                     strcat(str_m, entry);
    1276                 :           0 :                     num_m++;
    1277                 :             :                 }
    1278   [ #  #  #  #  :           0 :                 if ((i == num_atoms - 1 && num_m) || num_m == 8) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    1279                 :             :                 {
    1280                 :           0 :                     inchi_ios_print_nodisplay(fcb, "M  CHG%3d%s\n", num_m, str_m);
    1281                 :           0 :                     str_m[0] = 0;
    1282                 :           0 :                     num_m = 0;
    1283                 :             :                 }
    1284                 :             :             }
    1285                 :             :         }
    1286                 :             : 
    1287                 :             :         /* radicals*/
    1288                 :           0 :         str_m[0] = 0;
    1289                 :           0 :         num_m = 0;
    1290                 :             : 
    1291         [ #  # ]:           0 :         if (nNumRadicalLines)
    1292                 :             :         {
    1293         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    1294                 :             :             {
    1295   [ #  #  #  # ]:           0 :                 if (at[i].radical && !ALIASED_AT(i))
    1296                 :             :                 {
    1297                 :           0 :                     int radical = (at[i].radical == RADICAL_SINGLET ||
    1298         [ #  # ]:           0 :                                    at[i].radical == RADICAL_DOUBLET ||
    1299   [ #  #  #  # ]:           0 :                                    at[i].radical == RADICAL_TRIPLET) ? at[i].radical : 0;
    1300         [ #  # ]:           0 :                     if (radical)
    1301                 :             :                     {
    1302                 :           0 :                         sprintf(entry, " %3d %3d", i + 1, radical);
    1303                 :           0 :                         strcat(str_m, entry);
    1304                 :           0 :                         num_m++;
    1305                 :             :                     }
    1306                 :             :                 }
    1307   [ #  #  #  #  :           0 :                 if ((i == num_atoms - 1 && num_m) || num_m == 8) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    1308                 :             :                 {
    1309                 :           0 :                     inchi_ios_print_nodisplay(fcb, "M  RAD%3d%s\n", num_m, str_m);
    1310                 :           0 :                     str_m[0] = 0;
    1311                 :           0 :                     num_m = 0;
    1312                 :             :                 }
    1313                 :             :             }
    1314                 :             :         }
    1315                 :             : 
    1316                 :             :         /* isotopes*/
    1317                 :           0 :         str_m[0] = 0;
    1318                 :           0 :         num_m = 0;
    1319         [ #  # ]:           0 :         if (nNumIsoLines)
    1320                 :             :         {
    1321                 :             :             int el_num, iso;
    1322         [ #  # ]:           0 :             for (i = 0; i < num_atoms; i++)
    1323                 :             :             {
    1324                 :             :                 /*
    1325                 :             :                 if ( 0 == strcmp( at[i].elname, "D" ) ) {
    1326                 :             :                     sprintf( entry, " %3d %3d", i+1, 2 );
    1327                 :             :                     strcat( str_m, entry );
    1328                 :             :                     num_m ++;
    1329                 :             :                 } else
    1330                 :             :                 if ( 0 == strcmp( at[i].elname, "T" ) ) {
    1331                 :             :                     sprintf( entry, " %3d %3d", i+1, 3 );
    1332                 :             :                     strcat( str_m, entry );
    1333                 :             :                     num_m ++;
    1334                 :             :                 } else
    1335                 :             :                 if ( k = at[i].iso_atw_diff ) {
    1336                 :             :                     int mw = get_atomic_mass_from_elnum( at[i].el_number );
    1337                 :             :                     mw += (k > 0)? k-1 : k;
    1338                 :             :                     sprintf( entry, " %3d %3d", i+1, mw );
    1339                 :             :                     strcat( str_m, entry );
    1340                 :             :                     num_m ++;
    1341                 :             :                 }
    1342                 :             :                 */
    1343                 :             : 
    1344   [ #  #  #  #  :           0 :                 if (ANY_ISO(i, bAtomsDT) && !ALIASED_AT(i))
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    1345                 :             :                 {
    1346   [ #  #  #  #  :           0 :                     if (IS_DEUTERIUM(i))
                   #  # ]
    1347                 :             :                     {
    1348                 :           0 :                         iso = 1;
    1349                 :           0 :                         el_num = 1;
    1350                 :             :                     }
    1351   [ #  #  #  #  :           0 :                     else if (IS_TRITIUM(i))
                   #  # ]
    1352                 :             :                     {
    1353                 :           0 :                         iso = 2;
    1354                 :           0 :                         el_num = 1;
    1355                 :             :                     }
    1356                 :             :                     else
    1357                 :             :                     {
    1358         [ #  # ]:           0 :                         iso = at[i].iso_atw_diff > 0 ? at[i].iso_atw_diff - 1 : at[i].iso_atw_diff;
    1359                 :           0 :                         el_num = at[i].el_number;
    1360                 :             :                     }
    1361                 :           0 :                     iso += get_atomic_mass_from_elnum(el_num);
    1362                 :           0 :                     sprintf(entry, " %3d %3d", i + 1, iso);
    1363                 :           0 :                     strcat(str_m, entry);
    1364                 :           0 :                     num_m++;
    1365                 :             :                 }
    1366                 :             : 
    1367   [ #  #  #  #  :           0 :                 if ((i == num_atoms - 1 && num_m) || num_m == 8) /* djb-rwth: addressing LLVM warning */
                   #  # ]
    1368                 :             :                 {
    1369                 :           0 :                     inchi_ios_print_nodisplay(fcb, "M  ISO%3d%s\n", num_m, str_m);
    1370                 :           0 :                     str_m[0] = 0;
    1371                 :           0 :                     num_m = 0;
    1372                 :             :                 }
    1373                 :             :             }
    1374                 :             :         }
    1375                 :             : 
    1376         [ #  # ]:           0 :         if (is_polymer)
    1377                 :             :         {
    1378                 :           0 :             OrigAtData_WriteToSDfilePolymerData(inp_at_data, fcb, name, comment,
    1379                 :             :                                                 szLabel, szValue, written_bond_ends);
    1380                 :             :         }
    1381                 :             : 
    1382                 :           0 :         inchi_ios_print_nodisplay(fcb, "M  END\n");
    1383                 :             :     }
    1384                 :           0 :     return ret;
    1385                 :             : }
    1386                 :             : 
    1387                 :             : /****************************************************************************
    1388                 :             : OrigAtData : Write To SDfile : Polymer Data
    1389                 :             : ****************************************************************************/
    1390                 :           0 : int OrigAtData_WriteToSDfilePolymerData( const ORIG_ATOM_DATA *inp_at_data,
    1391                 :             :                                          INCHI_IOSTREAM       *fcb,
    1392                 :             :                                          const char           * name,
    1393                 :             :                                          const char           *comment,
    1394                 :             :                                          const char           *szLabel,
    1395                 :             :                                          const char           *szValue,
    1396                 :             :                                          INT_ARRAY            *written_bond_ends )
    1397                 :             : {
    1398                 :           0 :     int j, k, ju, jj, jprev, ret = 0;
    1399                 :           0 :     const char *sty[] = {"NON", "SRU", "MON", "COP", "MOD", "CRO", "MER"};
    1400                 :           0 :     const char *sst[] = {"NON", "ALT", "RAN", "BLO"};
    1401                 :           0 :     const char *con[] = {"NON", "HT", "HH", "EU"};
    1402                 :           0 :     OAD_PolymerUnit *u = NULL;
    1403                 :             : 
    1404                 :             :     /* STY */
    1405                 :           0 :     jj = 0;
    1406                 :           0 :     jprev = -1;
    1407         [ #  # ]:           0 :     for (j = 0; j < inp_at_data->polymer->n; j++)
    1408                 :             :     {
    1409                 :           0 :         u = inp_at_data->polymer->units[j];
    1410   [ #  #  #  # ]:           0 :         if (u->type > 0 && u->type <= 6)
    1411                 :             :         {
    1412                 :           0 :             jj++;
    1413                 :             :         }
    1414   [ #  #  #  # ]:           0 :         if (jj == 8 || j == inp_at_data->polymer->n - 1)
    1415                 :             :         {
    1416         [ #  # ]:           0 :             inchi_ios_print_nodisplay(fcb, "M  STY%3d", jj % 8 ? jj % 8 : 8);
    1417         [ #  # ]:           0 :             for (k = jprev + 1; k <= j; k++)
    1418                 :             :             {
    1419                 :           0 :                 u = inp_at_data->polymer->units[k];
    1420   [ #  #  #  # ]:           0 :                 if (u->type > 0 && u->type <= 6)
    1421                 :             :                 {
    1422                 :           0 :                     inchi_ios_print_nodisplay(fcb, " %3d %3s", u->id, sty[u->type]);
    1423                 :             :                 }
    1424                 :             :             }
    1425                 :           0 :             inchi_ios_print_nodisplay(fcb, "\n");
    1426                 :           0 :             jj = 0;
    1427                 :           0 :             jprev = j;
    1428                 :             :         }
    1429                 :             :     }
    1430                 :             :     /* SLB */
    1431                 :             :     /* djb-rwth: removing redundant code */
    1432                 :           0 :     jprev = -1;
    1433         [ #  # ]:           0 :     for (j = 0; j < inp_at_data->polymer->n; j++)
    1434                 :             :     {
    1435                 :             :         /* djb-rwth: removing redundant code */
    1436   [ #  #  #  # ]:           0 :         if (j == 8 || j == inp_at_data->polymer->n - 1)
    1437                 :             :         {
    1438                 :           0 :             jj = j + 1;
    1439         [ #  # ]:           0 :             inchi_ios_print_nodisplay(fcb, "M  SLB%3d", jj % 8 ? jj % 8 : 8);
    1440         [ #  # ]:           0 :             for (k = jprev + 1; k < jj; k++)
    1441                 :             :             {
    1442                 :           0 :                 u = inp_at_data->polymer->units[k];
    1443                 :           0 :                 inchi_ios_print_nodisplay(fcb, " %3d %3d", u->id, u->label);
    1444                 :             :             }
    1445                 :           0 :             inchi_ios_print_nodisplay(fcb, "\n");
    1446                 :             :             /* djb-rwth: removing redundant code */
    1447                 :           0 :             jprev = j;
    1448                 :             :         }
    1449                 :             :     }
    1450                 :             : 
    1451                 :             :     /* SST */
    1452                 :           0 :     jj = 0;
    1453                 :             :     /* djb-rwth: removing redundant code */
    1454         [ #  # ]:           0 :     for (j = 0; j < inp_at_data->polymer->n; j++)
    1455                 :             :     {
    1456                 :           0 :         u = inp_at_data->polymer->units[j];
    1457   [ #  #  #  #  :           0 :         if (u->subtype == MOL_FMT_M_SST_ALT || u->subtype == MOL_FMT_M_SST_RAN || u->subtype == MOL_FMT_M_SST_BLK)
                   #  # ]
    1458                 :             :         {
    1459                 :           0 :             jj++;
    1460                 :             :         }
    1461                 :             :     }
    1462         [ #  # ]:           0 :     if (jj)
    1463                 :             :     {
    1464                 :           0 :         jj = 0;
    1465                 :           0 :         jprev = -1;
    1466         [ #  # ]:           0 :         for (j = 0; j < inp_at_data->polymer->n; j++)
    1467                 :             :         {
    1468                 :           0 :             u = inp_at_data->polymer->units[j];
    1469   [ #  #  #  #  :           0 :             if (u->subtype == MOL_FMT_M_SST_ALT || u->subtype == MOL_FMT_M_SST_RAN || u->subtype == MOL_FMT_M_SST_BLK)
                   #  # ]
    1470                 :             :             {
    1471                 :           0 :                 jj++;
    1472                 :             :             }
    1473   [ #  #  #  # ]:           0 :             if (jj == 8 || j == inp_at_data->polymer->n - 1)
    1474                 :             :             {
    1475         [ #  # ]:           0 :                 inchi_ios_print_nodisplay(fcb, "M  SST%3d", jj % 8 ? jj % 8 : 8);
    1476         [ #  # ]:           0 :                 for (k = jprev + 1; k <= j; k++)
    1477                 :             :                 {
    1478                 :           0 :                     u = inp_at_data->polymer->units[k];
    1479   [ #  #  #  #  :           0 :                     if (u->subtype == MOL_FMT_M_SST_ALT || u->subtype == MOL_FMT_M_SST_RAN || u->subtype == MOL_FMT_M_SST_BLK)
                   #  # ]
    1480                 :             :                     {
    1481                 :           0 :                         inchi_ios_print_nodisplay(fcb, " %3d %3s", u->id, sst[u->subtype]);
    1482                 :             :                     }
    1483                 :             :                 }
    1484                 :           0 :                 inchi_ios_print_nodisplay(fcb, "\n");
    1485                 :           0 :                 jj = 0;
    1486                 :           0 :                 jprev = j;
    1487                 :             :             }
    1488                 :             :         }
    1489                 :             :     }
    1490                 :             : 
    1491                 :             :     /* SCN */
    1492                 :           0 :     jj = 0;
    1493                 :             :     /* djb-rwth: removing redundant code */
    1494         [ #  # ]:           0 :     for (j = 0; j < inp_at_data->polymer->n; j++)
    1495                 :             :     {
    1496                 :           0 :         u = inp_at_data->polymer->units[j];
    1497   [ #  #  #  #  :           0 :         if (u->conn == MOL_FMT_M_CONN_HT || u->conn == MOL_FMT_M_CONN_HH || u->conn == MOL_FMT_M_CONN_EU)
                   #  # ]
    1498                 :             :         {
    1499                 :           0 :             jj++;
    1500                 :             :         }
    1501                 :             :     }
    1502         [ #  # ]:           0 :     if (jj)
    1503                 :             :     {
    1504                 :           0 :         jj = 0;
    1505                 :           0 :         jprev = -1;
    1506         [ #  # ]:           0 :         for (j = 0; j < inp_at_data->polymer->n; j++)
    1507                 :             :         {
    1508                 :           0 :             u = inp_at_data->polymer->units[j];
    1509   [ #  #  #  #  :           0 :             if (u->conn == MOL_FMT_M_CONN_HT || u->conn == MOL_FMT_M_CONN_HH || u->conn == MOL_FMT_M_CONN_EU)
                   #  # ]
    1510                 :             :             {
    1511                 :           0 :                 jj++;
    1512                 :             :             }
    1513   [ #  #  #  # ]:           0 :             if (jj == 8 || j == inp_at_data->polymer->n - 1)
    1514                 :             :             {
    1515         [ #  # ]:           0 :                 inchi_ios_print_nodisplay(fcb, "M  SCN%3d", jj % 8 ? jj % 8 : 8);
    1516         [ #  # ]:           0 :                 for (k = jprev + 1; k <= j; k++)
    1517                 :             :                 {
    1518                 :           0 :                     u = inp_at_data->polymer->units[k];
    1519   [ #  #  #  #  :           0 :                     if (u->conn == MOL_FMT_M_CONN_HT || u->conn == MOL_FMT_M_CONN_HH || u->conn == MOL_FMT_M_CONN_EU)
                   #  # ]
    1520                 :             :                     {
    1521                 :           0 :                         inchi_ios_print_nodisplay(fcb, " %3d %3s", u->id, con[u->conn]);
    1522                 :             :                     }
    1523                 :             :                 }
    1524                 :           0 :                 inchi_ios_print_nodisplay(fcb, "\n");
    1525                 :           0 :                 jj = 0;
    1526                 :           0 :                 jprev = j;
    1527                 :             :             }
    1528                 :             :         }
    1529                 :             :     }
    1530                 :             :     /* SAL */
    1531         [ #  # ]:           0 :     for (ju = 0; ju < inp_at_data->polymer->n; ju++)
    1532                 :             :     {
    1533                 :           0 :         u = inp_at_data->polymer->units[ju];
    1534                 :           0 :         jj = 0;
    1535                 :           0 :         jprev = -1;
    1536         [ #  # ]:           0 :         for (j = 0; j < u->na; j++)
    1537                 :             :         {
    1538                 :           0 :             jj++;
    1539   [ #  #  #  # ]:           0 :             if (jj == 15 || j == u->na - 1)
    1540                 :             :             {
    1541         [ #  # ]:           0 :                 inchi_ios_print_nodisplay(fcb, "M  SAL %3d%3d", u->id, jj % 15 ? jj % 15 : 15);
    1542         [ #  # ]:           0 :                 for (k = jprev + 1; k <= j; k++)
    1543                 :             :                 {
    1544                 :           0 :                     inchi_ios_print_nodisplay(fcb, " %3d", u->alist[k]);
    1545                 :             :                 }
    1546                 :           0 :                 inchi_ios_print_nodisplay(fcb, "\n");
    1547                 :           0 :                 jj = 0;
    1548                 :           0 :                 jprev = j;
    1549                 :             :             }
    1550                 :             :         }
    1551                 :             :     }
    1552                 :             :     /* SBL */
    1553         [ #  # ]:           0 :     for (ju = 0; ju < inp_at_data->polymer->n; ju++)
    1554                 :             :     {
    1555                 :           0 :         u = inp_at_data->polymer->units[ju];
    1556                 :           0 :         jj = 0;
    1557                 :           0 :         jprev = -1;
    1558         [ #  # ]:           0 :         for (j = 0; j < u->nb; j++)
    1559                 :             :         {
    1560                 :           0 :             jj++;
    1561   [ #  #  #  # ]:           0 :             if (jj == 15 || j == u->nb - 1)
    1562                 :             :             {
    1563         [ #  # ]:           0 :                 inchi_ios_print_nodisplay(fcb, "M  SBL %3d%3d", u->id, jj % 15 ? jj % 15 : 15);
    1564                 :             : 
    1565         [ #  # ]:           0 :                 for (k = jprev + 1; k <= j; k++)
    1566                 :             :                 {
    1567                 :           0 :                     int a1, a2, e1, e2, wb, bond_num = 0;
    1568                 :           0 :                     a1 = u->blist[2 * k];
    1569                 :           0 :                     a2 = u->blist[2 * k + 1];
    1570         [ #  # ]:           0 :                     for (wb = 0; wb < written_bond_ends->used / 2; wb++)
    1571                 :             :                     {
    1572                 :           0 :                         e1 = written_bond_ends->item[2 * wb];
    1573                 :           0 :                         e2 = written_bond_ends->item[2 * wb + 1];
    1574   [ #  #  #  #  :           0 :                         if ((a1 == e1 && a2 == e2) || (a2 == e1 && a1 == e2))
             #  #  #  # ]
    1575                 :             :                         {
    1576                 :           0 :                             bond_num = wb + 1;
    1577                 :           0 :                             break;
    1578                 :             :                         }
    1579                 :             :                     }
    1580         [ #  # ]:           0 :                     if (bond_num)
    1581                 :             :                     {
    1582                 :           0 :                         inchi_ios_print_nodisplay(fcb, " %3d", bond_num);
    1583                 :             :                     }
    1584                 :             :                 }
    1585                 :             : 
    1586                 :           0 :                 inchi_ios_print_nodisplay(fcb, "\n");
    1587                 :           0 :                 jj = 0;
    1588                 :           0 :                 jprev = j;
    1589                 :             :             }
    1590                 :             :         }
    1591                 :             :     }
    1592                 :             : 
    1593                 :             :     /* SDI */
    1594         [ #  # ]:           0 :     for (j = 0; j < inp_at_data->polymer->n; j++)
    1595                 :             :     {
    1596                 :             :         /* better than nothing */
    1597                 :             :         float xmin, xmax, ymin, ymax;
    1598                 :           0 :         xmin = ymin = -1.0 * ((float)j + 1.0); /* djb-rwth: cast operator added, 1->1.0 */
    1599                 :           0 :         xmax = ymax = +1.0 * ((float)j + 1.0); /* djb-rwth: cast operator added, 1->1.0 */
    1600                 :           0 :         u = inp_at_data->polymer->units[j];
    1601                 :             :         /* u->xbr1[0], x1, y1, x2, y2 u->xbr1[1], u->xbr1[2], u->xbr1[3] */
    1602                 :           0 :         inchi_ios_print_nodisplay(fcb, "M  SDI %3d%3d%10.4f%10.4f%10.4f%10.4f\n", u->id, 4, xmin, ymin, xmin, ymax);
    1603                 :             :         /* u->xbr2[0], u->xbr2[1], u->xbr2[2], u->xbr2[3] */
    1604                 :           0 :         inchi_ios_print_nodisplay(fcb, "M  SDI %3d%3d%10.4f%10.4f%10.4f%10.4f\n", u->id, 4, xmax, ymax, xmax, ymin);
    1605                 :             :     }
    1606                 :             : 
    1607                 :           0 :     return ret;
    1608                 :             : }
        

Generated by: LCOV version 2.0-1