LCOV - code coverage report
Current view: top level - src - runichi2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 19.4 % 1037 201
Test Date: 2026-08-20 14:32:48 Functions: 29.0 % 31 9
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 11.0 % 1010 111

             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                 :             : 
      42                 :             : /*
      43                 :             :     Reading input data
      44                 :             : 
      45                 :             :     Prepare and make edits
      46                 :             : 
      47                 :             : */
      48                 :             : 
      49                 :             : #include <stdlib.h>
      50                 :             : #include <string.h>
      51                 :             : #include <stdarg.h>
      52                 :             : #include <errno.h>
      53                 :             : #include <limits.h>
      54                 :             : #include <math.h>
      55                 :             : #include <ctype.h>
      56                 :             : 
      57                 :             : #include "mode.h"
      58                 :             : #include "ichitime.h"
      59                 :             : #ifndef COMPILE_ANSI_ONLY
      60                 :             : #include <conio.h>
      61                 :             : #endif
      62                 :             : 
      63                 :             : #include "ichister.h"
      64                 :             : 
      65                 :             : #include "ichimain.h"
      66                 :             : #include "ichi_io.h"
      67                 :             : #include "mol_fmt.h"
      68                 :             : #include "inchi_api.h"
      69                 :             : #include "readinch.h"
      70                 :             : #ifdef TARGET_LIB_FOR_WINCHI
      71                 :             : #include "../../../IChI_lib/src/ichi_lib.h"
      72                 :             : #include "inchi_api.h"
      73                 :             : #else
      74                 :             : #include "inchi_gui.h"
      75                 :             : #endif
      76                 :             : #include "readinch.h"
      77                 :             : 
      78                 :             : #include "ichirvrs.h"
      79                 :             : 
      80                 :             : #include "bcf_s.h"
      81                 :             : 
      82                 :             : /* Modified in-CRU stereoventer info */
      83                 :             : typedef struct tagModSCenterInfo
      84                 :             : {
      85                 :             :     int num;                    /* atnums are 0-based, internal ones */
      86                 :             :     int valence;
      87                 :             :     int n_stereo;
      88                 :             :     int nbr[MAXVAL];
      89                 :             :     int new_nbr[MAXVAL];
      90                 :             : } ModSCenterInfo;
      91                 :             : 
      92                 :             : typedef struct tagDiylFrag
      93                 :             : {
      94                 :             :     int na;                     /* number of atoms      */
      95                 :             :     int nb;                     /* number of bonds      */
      96                 :             :     int end1;           /* "starting" end     */
      97                 :             :     int end2;           /* "ending" end               */
      98                 :             :     int *alist;         /* list of atoms orig numbers       */
      99                 :             :     int *xclist;        /* list of atoms extended classes   */
     100                 :             :     INCHI_IOS_STRING sig; /* string signature           */
     101                 :             : } DiylFrag;
     102                 :             : 
     103                 :             : static DiylFrag* DiylFrag_New( int na, int e1nd, int end2, char *s );
     104                 :             : static void DiylFrag_Free( DiylFrag *pfrag );
     105                 :             : static void DiylFrag_MakeSignature( DiylFrag *pfrag, int nxc, int *xc, int *tmp );
     106                 :             : static int DiylFrag_Diff( DiylFrag *pfrag1, DiylFrag *pfrag2 );
     107                 :             : static void DiylFrag_DebugTrace( DiylFrag *pfrag );
     108                 :             : 
     109                 :             : static int NDefStereoBonds( inp_ATOM *at, int iatom, int bOnlyPointedEndMatters );
     110                 :             : 
     111                 :             : static void ModSCenter_Init( ModSCenterInfo *scinfo, inp_ATOM *at, int iatom );
     112                 :             : static void ModSCenter_AddTo( ModSCenterInfo *scinfo, int iadd );
     113                 :             : static void ModSCenter_DelFrom( ModSCenterInfo *scinfo, int idel );
     114                 :             : static int ModSCenter_IsChanged( ModSCenterInfo *scinfo, inp_ATOM *at );
     115                 :             : 
     116                 :             : static int GetFrameShiftInfoFrom105PlusInChI( char *sinchi, int *alist, int max_crossing );
     117                 :             : /* static int IsPolymerRequiringEdits(ORIG_ATOM_DATA* orig_inp_data); */ /* djb-rwth: function definition not found*/
     118                 :             : static int analyze_CRU_folding( ORIG_ATOM_DATA *orig_at_data,
     119                 :             :                                 int iunit,
     120                 :             :                                 int n_all_bkb,
     121                 :             :                                 int *all_bkb,
     122                 :             :                                 int nxclasses,
     123                 :             :                                 int *xc,
     124                 :             :                                 OAD_StructureEdits *ed );
     125                 :             : static int count_colors_in_sequence( int *entries, int n_entries, int max_distinct, int *counts );
     126                 :             : static int len_repeating_subsequence( int *color, int *color2, int n );
     127                 :             : 
     128                 :             : 
     129                 :             : 
     130                 :             : /****************************************************************************
     131                 :             :  Get (the next) one portion of input data of any possible kind
     132                 :             :  (Molfile, InChI string, ...) from a sequential input stream
     133                 :             : ****************************************************************************/
     134                 :         121 : int GetOneStructure( INCHI_CLOCK    *ic,
     135                 :             :                      STRUCT_DATA    *sd,
     136                 :             :                      INPUT_PARMS    *ip,
     137                 :             :                      char           *szTitle,
     138                 :             :                      INCHI_IOSTREAM *inp_file,
     139                 :             :                      INCHI_IOSTREAM *log_file,
     140                 :             :                      INCHI_IOSTREAM *out_file,
     141                 :             :                      INCHI_IOSTREAM *prb_file,
     142                 :             :                      ORIG_ATOM_DATA *orig_inp_data,
     143                 :             :                      long           *num_inp,
     144                 :             :                      STRUCT_FPTRS   *struct_fptrs )
     145                 :             : {
     146                 :         121 :     int nRet, inp_index, out_index, bUseFptr = ( NULL != struct_fptrs );
     147                 :             : 
     148                 :         121 :     FreeOrigAtData( orig_inp_data );
     149                 :             : 
     150                 :             :     /* added for TARGET_LIB_FOR_WINCHI early EOF detection */
     151                 :         121 :     inp_index = -1;
     152                 :         121 :     out_index = -1;
     153                 :             : 
     154         [ -  + ]:         121 :     if (struct_fptrs)
     155                 :             :     {
     156         [ #  # ]:           0 :         if (inp_file->f == stdin)
     157                 :             :         {
     158                 :           0 :             return _IS_FATAL;
     159                 :             :         }
     160         [ #  # ]:           0 :         if (ip->nInputType == INPUT_CMLFILE)
     161                 :             :         {
     162                 :           0 :             bUseFptr = 0;
     163                 :             :         }
     164                 :             : 
     165                 :             :         /* Initially allocate or increase length of struct_fptrs->fptr array */
     166   [ #  #  #  # ]:           0 :         if (!struct_fptrs->fptr || struct_fptrs->len_fptr <= struct_fptrs->cur_fptr + 1)
     167                 :             :         {
     168                 :             : 
     169                 :             :             INCHI_FPTR *new_fptr = (INCHI_FPTR *)
     170                 :           0 :                                         inchi_calloc( (long long)struct_fptrs->len_fptr + ADD_LEN_STRUCT_FPTRS, sizeof( new_fptr[0] ) ); /* djb-rwth: cast operator added */
     171                 :             : 
     172         [ #  # ]:           0 :             if (new_fptr)
     173                 :             :             {
     174         [ #  # ]:           0 :                 if (struct_fptrs->fptr)
     175                 :             :                 {
     176         [ #  # ]:           0 :                     if (struct_fptrs->len_fptr)
     177                 :             :                     {
     178                 :           0 :                         memcpy(new_fptr, struct_fptrs->fptr, struct_fptrs->len_fptr * sizeof(new_fptr[0]));
     179                 :             :                     }
     180         [ #  # ]:           0 :                     inchi_free( struct_fptrs->fptr );
     181                 :             :                 }
     182                 :             :                 else
     183                 :             :                 {
     184                 :           0 :                     struct_fptrs->len_fptr = 0;
     185                 :           0 :                     struct_fptrs->cur_fptr = 0;
     186                 :           0 :                     struct_fptrs->max_fptr = 0;
     187                 :             :                 }
     188                 :           0 :                 struct_fptrs->len_fptr += ADD_LEN_STRUCT_FPTRS;
     189                 :           0 :                 struct_fptrs->fptr = new_fptr;
     190                 :             :             }
     191                 :             :             else
     192                 :             :             {
     193                 :           0 :                 return _IS_FATAL;  /* new_fptr allocation error */
     194                 :             :             }
     195                 :             :         }
     196                 :             : 
     197         [ #  # ]:           0 :         if (struct_fptrs->fptr[struct_fptrs->cur_fptr] == EOF)
     198                 :             :         {
     199                 :           0 :             return _IS_EOF;
     200                 :             :         }
     201                 :             :         else
     202                 :             :         {
     203                 :             : 
     204         [ #  # ]:           0 :             if (bUseFptr)
     205                 :             :             {
     206         [ #  # ]:           0 :                 if (fseek( inp_file->f,
     207                 :           0 :                     struct_fptrs->fptr[struct_fptrs->cur_fptr],
     208                 :             :                     SEEK_SET ))
     209                 :             :                 {
     210                 :           0 :                     return _IS_FATAL;
     211                 :             :                 }
     212         [ #  # ]:           0 :                 if (struct_fptrs->cur_fptr &&
     213         [ #  # ]:           0 :                      struct_fptrs->max_fptr <= struct_fptrs->cur_fptr)
     214                 :             :                 {
     215                 :           0 :                     return _IS_FATAL;
     216                 :             :                 }
     217                 :             :             }
     218                 :             :             else
     219                 :             :             {
     220                 :           0 :                 inp_index = struct_fptrs->fptr[struct_fptrs->cur_fptr];
     221                 :           0 :                 out_index = EOF;
     222                 :             :             }
     223                 :             :         }
     224                 :             : 
     225                 :           0 :         *num_inp = struct_fptrs->cur_fptr; /* set structure count */
     226                 :             :     }
     227                 :             : 
     228                 :             : 
     229                 :         121 :     nRet = ReadTheStructure( ic, sd, ip, inp_file, orig_inp_data, inp_index, &out_index );
     230                 :             : 
     231         [ +  - ]:         121 :     if (!nRet)
     232                 :             :     {
     233   [ +  -  -  +  :         121 :         if (ip->nInputType == INPUT_INCHI_PLAIN || ip->nInputType == INPUT_MOLFILE || ip->nInputType == INPUT_SDFILE)
                   -  - ]
     234                 :             :         {
     235         [ -  + ]:         121 :             if (ip->lMolfileNumber)
     236                 :             :             {
     237                 :           0 :                 *num_inp = ip->lMolfileNumber;
     238                 :             :             }
     239                 :             :             else
     240                 :             :             {
     241                 :         121 :                 *num_inp += 1;
     242                 :             :             }
     243                 :             :         }
     244                 :             :         else
     245                 :             :         {
     246                 :           0 :             *num_inp += 1;
     247                 :             :         }
     248                 :             : 
     249                 :         121 :         nRet = TreatErrorsInReadTheStructure( sd, ip, LOG_MASK_ALL,
     250                 :             :                                               inp_file, log_file, out_file, prb_file,
     251                 :             :                                               orig_inp_data, num_inp );
     252                 :             :     }
     253                 :             : 
     254                 :             :     /************************************************************
     255                 :             :      Added for TARGET_LIB_FOR_WINCHI:
     256                 :             :      look ahead for end of file detection
     257                 :             :     ************************************************************/
     258         [ -  + ]:         121 :     if ( inp_file->type == INCHI_IOS_TYPE_FILE              &&
     259   [ #  #  #  #  :           0 :          inp_file->f && struct_fptrs && struct_fptrs->fptr  &&
                   #  # ]
     260         [ #  # ]:           0 :          struct_fptrs->fptr[struct_fptrs->cur_fptr + 1] <= 0 )
     261                 :             :     {
     262                 :             : 
     263                 :           0 :         int nRet2 = 0;
     264                 :           0 :         INCHI_FPTR next_fptr = 0;
     265                 :             :         STRUCT_DATA sd2;
     266                 :             : 
     267   [ #  #  #  # ]:           0 :         if (nRet != _IS_EOF && nRet != _IS_FATAL)
     268                 :             :         {
     269   [ #  #  #  # ]:           0 :             if (inp_file->f == stdin || struct_fptrs->len_fptr <= struct_fptrs->cur_fptr + 1)
     270                 :             :             {
     271                 :           0 :                 return _IS_FATAL;
     272                 :             :             }
     273                 :             :             /* Get the next structure fptr */
     274         [ #  # ]:           0 :             if (bUseFptr)
     275                 :             :             {
     276                 :           0 :                 next_fptr = ftell( inp_file->f );
     277                 :             :             }
     278                 :             :             else
     279                 :             :             {
     280                 :           0 :                 inp_index = out_index;
     281                 :           0 :                 out_index = EOF;
     282                 :             :             }
     283                 :             : 
     284                 :             :             /* Read the next structure */
     285                 :           0 :             nRet2 = ReadTheStructure( ic, &sd2, ip, inp_file,
     286                 :             :                                       NULL, inp_index, &out_index );
     287                 :             : 
     288                 :             :             /* Restore fptr to the next structure */
     289         [ #  # ]:           0 :             if (bUseFptr)
     290                 :             :             {
     291         [ #  # ]:           0 :                 if (next_fptr != -1L)
     292                 :             :                 {
     293                 :           0 :                     fseek( inp_file->f, next_fptr, SEEK_SET );
     294                 :             :                 }
     295                 :             :             }
     296                 :             :         }
     297                 :             :         else
     298                 :             :         {
     299                 :             :             /* Treat current fatal error as end of file */
     300                 :           0 :             struct_fptrs->fptr[struct_fptrs->cur_fptr] = EOF;
     301                 :             :         }
     302                 :             : 
     303                 :             :         /* Next is end of file or fatal */
     304   [ #  #  #  #  :           0 :         if (nRet == _IS_EOF || nRet == _IS_FATAL ||
                   #  # ]
     305         [ #  # ]:           0 :              nRet2 == _IS_EOF || nRet2 == _IS_FATAL)
     306                 :             :         {
     307                 :           0 :             struct_fptrs->fptr[struct_fptrs->cur_fptr + 1] = EOF;
     308                 :             :         }
     309                 :             :         else
     310                 :             :         {
     311         [ #  # ]:           0 :             struct_fptrs->fptr[struct_fptrs->cur_fptr + 1] = bUseFptr ? sd->fPtrEnd : inp_index;
     312                 :             :         }
     313                 :             : 
     314                 :             :         /* Update struct_fptrs->max_fptr */
     315         [ #  # ]:           0 :         if (struct_fptrs->max_fptr <= struct_fptrs->cur_fptr + 1)
     316                 :             :         {
     317                 :           0 :             struct_fptrs->max_fptr = struct_fptrs->cur_fptr + 2;
     318                 :             :         }
     319                 :             :     }
     320                 :             : 
     321      [ -  -  + ]:         121 :     switch (nRet)
     322                 :             :     {
     323                 :           0 :         case _IS_EOF:
     324                 :           0 :             *num_inp -= 1;
     325                 :           0 :         case _IS_FATAL:
     326                 :             :         case _IS_ERROR:
     327                 :             :         case _IS_SKIP:
     328                 :           0 :             goto exit_function;
     329                 :             :     }
     330                 :             : 
     331                 :             :     /*
     332                 :             :     if ( !orig_inp_data->num_dimensions ) {
     333                 :             :         WarningMessage(sd->pStrErrStruct, "0D"); */ /* 0D-structure: no coordinates
     334                 :             :     }
     335                 :             :     */
     336                 :             : 
     337                 :         121 : exit_function:
     338                 :         121 :     return nRet;
     339                 :             : }
     340                 :             : 
     341                 :             : /** @nnuk
     342                 :             : ****************************************************************************
     343                 :             :  Build a component-local mask of polymer crossing-bond endpoints.
     344                 :             : 
     345                 :             :  The polymer crossing-bond list (OAD_PolymerUnit.blist) uses whole-structure,
     346                 :             :  1-based atom numbering, whereas inp_cur_data contains only atoms from the
     347                 :             :  selected connected component. ExtractConnectedComponent() preserves the original
     348                 :             :  atom order within the component, allowing the corresponding local atom index to
     349                 :             :  be reconstructed.
     350                 :             : 
     351                 :             :  The mask is later consulted by remove_terminal_HDT() to preserve explicit
     352                 :             :  H/D/T atoms that participate in polymer crossing bonds.
     353                 :             : 
     354                 :             :  @param inp_cur_data chemical structure information for the current component
     355                 :             :  @param orig_inp_data chemical structure information for the whole structure
     356                 :             :  @param ip input parameters
     357                 :             :  @param component_number number of component in the chemical structure
     358                 :             : 
     359                 :             :  @return Return 0 on success or when no mask is required; return -1 on allocation
     360                 :             :  failure.
     361                 :             : ****************************************************************************/
     362                 :         161 : static int BuildPolymerCrossingBondEndpointMask(INP_ATOM_DATA *inp_cur_data,
     363                 :             :                                                 const ORIG_ATOM_DATA *orig_inp_data,
     364                 :             :                                                 const INPUT_PARMS *ip,
     365                 :             :                                                 int component_number)
     366                 :             : {
     367                 :             :     int orig_idx;
     368                 :         161 :     int local_idx = 0;
     369                 :             :     int unit_idx;
     370                 :             :     int endpoint_idx;
     371                 :             : 
     372   [ +  -  +  + ]:         161 :     if (inp_cur_data->num_at <= 0 || ip->bPolymers == POLYMERS_NO ||
     373   [ +  -  +  - ]:           2 :         !orig_inp_data->valid_polymer || !orig_inp_data->polymer ||
     374         [ -  + ]:           2 :         orig_inp_data->polymer->n <= 0)
     375                 :             :     {
     376                 :         159 :         return 0;
     377                 :             :     }
     378                 :             : 
     379                 :             :     /* No mask is needed if this component contains no explicit H/D/T atoms. */
     380         [ +  - ]:          10 :     for (local_idx = 0; local_idx < inp_cur_data->num_at; local_idx++)
     381                 :             :     {
     382                 :          10 :         const char *elname = inp_cur_data->at[local_idx].elname;
     383                 :             : 
     384   [ +  -  +  +  :          10 :         if (elname[1] == '\0' && (elname[0] == 'H' || elname[0] == 'D' || elname[0] == 'T'))
             +  -  +  - ]
     385                 :             :         {
     386                 :             :             break;
     387                 :             :         }
     388                 :             :     }
     389                 :             : 
     390         [ -  + ]:           2 :     if (local_idx == inp_cur_data->num_at)
     391                 :             :     {
     392                 :           0 :         return 0;
     393                 :             :     }
     394                 :             : 
     395                 :           2 :     local_idx = 0;
     396                 :             : 
     397                 :           2 :     inp_cur_data->keep_explicit_HDT = (unsigned char *)inchi_calloc((long long)inp_cur_data->num_at, sizeof(inp_cur_data->keep_explicit_HDT[0]));
     398                 :             : 
     399         [ -  + ]:           2 :     if (!inp_cur_data->keep_explicit_HDT)
     400                 :             :     {
     401                 :           0 :         return -1;
     402                 :             :     }
     403                 :             : 
     404         [ +  + ]:          12 :     for (orig_idx = 0; orig_idx < orig_inp_data->num_inp_atoms; orig_idx++)
     405                 :             :     {
     406         [ -  + ]:          10 :         if (orig_inp_data->at[orig_idx].component != component_number)
     407                 :             :         {
     408                 :           0 :             continue;
     409                 :             :         }
     410                 :             : 
     411                 :             :         /*
     412                 :             :          * The mask is consulted only for explicit H/D/T atoms by
     413                 :             :          * remove_terminal_HDT(), so heavy-atom and pseudoatom endpoints
     414                 :             :          * do not need to be marked.
     415                 :             :         */
     416         [ +  - ]:          10 :         if (!(orig_inp_data->at[orig_idx].elname[1] == '\0' &&
     417         [ +  + ]:          10 :               (orig_inp_data->at[orig_idx].elname[0] == 'H' ||
     418         [ +  - ]:           8 :                orig_inp_data->at[orig_idx].elname[0] == 'D' ||
     419         [ +  - ]:           8 :                orig_inp_data->at[orig_idx].elname[0] == 'T')))
     420                 :             :         {
     421                 :           8 :             local_idx++;
     422                 :           8 :             continue;
     423                 :             :         }
     424                 :             : 
     425         [ +  - ]:           2 :         for (unit_idx = 0; unit_idx < orig_inp_data->polymer->n; unit_idx++)
     426                 :             :         {
     427                 :           2 :             const OAD_PolymerUnit *u = orig_inp_data->polymer->units[unit_idx];
     428                 :             : 
     429   [ +  -  -  + ]:           2 :             if (!u || !u->blist)
     430                 :             :             {
     431                 :           0 :                 continue;
     432                 :             :             }
     433                 :             : 
     434                 :             :             /*
     435                 :             :              * Each crossing bond contributes two atom numbers to blist.
     436                 :             :              * blist uses whole-structure, 1-based atom numbering.
     437                 :             :              */
     438         [ +  - ]:           8 :             for (endpoint_idx = 0; endpoint_idx < 2 * u->nb; endpoint_idx++)
     439                 :             :             {
     440         [ +  + ]:           8 :                 if (u->blist[endpoint_idx] == orig_idx + 1)
     441                 :             :                 {
     442                 :           2 :                     inp_cur_data->keep_explicit_HDT[local_idx] = 1;
     443                 :           2 :                     break;
     444                 :             :                 }
     445                 :             :             }
     446                 :             : 
     447         [ +  - ]:           2 :             if (inp_cur_data->keep_explicit_HDT[local_idx])
     448                 :             :             {
     449                 :           2 :                 break;
     450                 :             :             }
     451                 :             :         }
     452                 :             : 
     453                 :           2 :         local_idx++;
     454                 :             :     }
     455                 :             : 
     456                 :           2 :     return 0;
     457                 :             : }
     458                 :             : 
     459                 :             : /****************************************************************************
     460                 :             :  Extract one connected component from the input structure
     461                 :             : ****************************************************************************/
     462                 :         161 : int GetOneComponent( INCHI_CLOCK        *ic,
     463                 :             :                      STRUCT_DATA        *sd,
     464                 :             :                      INPUT_PARMS        *ip,
     465                 :             :                      INCHI_IOSTREAM     *log_file,
     466                 :             :                      INCHI_IOSTREAM     *out_file,
     467                 :             :                      INP_ATOM_DATA      *inp_cur_data,
     468                 :             :                      ORIG_ATOM_DATA     *orig_inp_data,
     469                 :             :                      int                i,
     470                 :             :                      long               num_inp )
     471                 :             : {
     472                 :             :     inchiTime ulTStart;
     473                 :             : 
     474                 :         161 :     InchiTimeGet( &ulTStart );
     475                 :             : 
     476                 :         161 :     CreateInpAtomData( inp_cur_data, orig_inp_data->nCurAtLen[i], 0 );
     477                 :             : 
     478                 :         161 :     inp_cur_data->num_at = ExtractConnectedComponent( orig_inp_data->at, orig_inp_data->num_inp_atoms, i + 1, inp_cur_data->at );
     479                 :             : 
     480         [ -  + ]:         161 :     if (BuildPolymerCrossingBondEndpointMask(inp_cur_data, orig_inp_data, ip, i + 1) < 0)
     481                 :             :     {
     482                 :           0 :         AddErrorMessage(sd->pStrErrStruct, "Out of memory while processing polymer data");
     483                 :             : 
     484                 :           0 :         sd->nErrorCode = CT_OUT_OF_RAM;
     485                 :           0 :         sd->nErrorType = _IS_FATAL;
     486                 :             : 
     487                 :           0 :         sd->ulStructTime += InchiTimeElapsed(ic, &ulTStart);
     488                 :             : 
     489                 :           0 :         return sd->nErrorType;
     490                 :             :     }
     491                 :             : 
     492                 :         161 :     sd->ulStructTime += InchiTimeElapsed( ic, &ulTStart );
     493                 :             : 
     494                 :             : 
     495                 :             :     /*  Error processing */
     496   [ +  -  -  + ]:         161 :     if (inp_cur_data->num_at <= 0 || orig_inp_data->nCurAtLen[i] != inp_cur_data->num_at)
     497                 :             :     {
     498                 :             :         /*  Log error message */
     499                 :           0 :         AddErrorMessage( sd->pStrErrStruct, "Cannot extract Component" );
     500   [ #  #  #  #  :           0 :         inchi_ios_eprint( log_file, "%s #%d structure #%ld.%s%s%s%s\n", sd->pStrErrStruct, i + 1, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     501   [ #  #  #  # ]:           0 :         sd->nErrorCode = inp_cur_data->num_at < 0 ? inp_cur_data->num_at : ( orig_inp_data->nCurAtLen[i] != inp_cur_data->num_at ) ? CT_ATOMCOUNT_ERR : CT_UNKNOWN_ERR;
     502                 :             :         /* num_err ++; */
     503                 :           0 :         sd->nErrorType = _IS_ERROR;
     504                 :             : #ifdef TARGET_LIB_FOR_WINCHI
     505                 :             :         if (( ip->bINChIOutputOptions & INCHI_OUT_WINCHI_WINDOW ) &&
     506                 :             :             ( ip->bINChIOutputOptions & INCHI_OUT_PLAIN_TEXT ))
     507                 :             :         {
     508                 :             :             sd->nErrorType = ProcessStructError( out_file,
     509                 :             :                                                  log_file,
     510                 :             :                                                  sd->pStrErrStruct,
     511                 :             :                                                  sd->nErrorType,
     512                 :             :                                                  num_inp,
     513                 :             :                                                  ip );
     514                 :             :         }
     515                 :             : #endif
     516                 :             :     }
     517                 :             : 
     518                 :         161 :     return sd->nErrorType;
     519                 :             : }
     520                 :             : 
     521                 :             : 
     522                 :             : /****************************************************************************
     523                 :             :  Read input data of any possible kind (Molfile, InChI string, ...)
     524                 :             : ****************************************************************************/
     525                 :         121 : int ReadTheStructure( struct tagINCHI_CLOCK *ic,
     526                 :             :                       STRUCT_DATA           *sd,
     527                 :             :                       INPUT_PARMS           *ip,
     528                 :             :                       INCHI_IOSTREAM        *inp_file,
     529                 :             :                       ORIG_ATOM_DATA        *orig_inp_data,
     530                 :             :                       /* the further is deprecated (CML support)        */
     531                 :             :                       int                   inp_index,
     532                 :             :                       int                   *out_index )
     533                 :             : {
     534                 :             :     inchiTime ulTStart;
     535                 :         121 :     int nRet = 0, nRet2 = 0;
     536                 :         121 :     int bGetOrigCoord = !( ip->bINChIOutputOptions &
     537                 :             :         ( INCHI_OUT_NO_AUX_INFO | INCHI_OUT_SHORT_AUX_INFO ) );
     538                 :             : 
     539                 :         121 :     INCHI_MODE InpAtomFlags = 0;
     540                 :             :     /* NB: reading Molfile may set FLAG_INP_AT_CHIRAL bit */
     541                 :             : 
     542                 :         121 :     int vABParityUnknown = AB_PARITY_UNDF;
     543                 :             :         /* vABParityUnknown holds actual value of an internal constant */
     544                 :             :         /* signifying unknown parity: either the same as for undefined */
     545                 :             :         /* parity (default==standard)  or a specific one (non-std;       */
     546                 :             :         /* requested by SLUUD switch).                                   */
     547                 :             : 
     548         [ -  + ]:         121 :     if (0 != ( ip->nMode & REQ_MODE_DIFF_UU_STEREO ))
     549                 :             :     {
     550                 :             :         /* Make labels for unknown and undefined stereo different */
     551                 :           0 :         vABParityUnknown = AB_PARITY_UNKN;
     552                 :             :     }
     553                 :             : 
     554         [ -  + ]:         121 :     if (ip->bLargeMolecules)
     555                 :             :     {
     556                 :           0 :         InpAtomFlags |= FLAG_SET_INP_LARGE_MOLS;
     557                 :             :     }
     558                 :             : 
     559                 :         121 :     memset( sd, 0, sizeof( *sd ) ); /* djb-rwth: memset_s C11/Annex K variant? */
     560                 :             : 
     561      [ +  -  - ]:         121 :     switch (ip->nInputType)
     562                 :             :     {
     563                 :             : 
     564                 :         121 :         case INPUT_MOLFILE:
     565                 :             :         case INPUT_SDFILE:
     566                 :             : 
     567                 :             :             /*  Read the original input structure from Molfile */
     568         [ +  - ]:         121 :             if (orig_inp_data)
     569                 :             :             {
     570                 :             : 
     571   [ -  +  -  - ]:         121 :                 if (ip->pSdfValue && ip->pSdfValue[0])
     572                 :             :                 {
     573                 :             :                     /* Added 07-29-2003 to avoid inheriting exact value from prev.
     574                 :             :                         structure and to make reference to a (bad) structure
     575                 :             :                         with unknown ID Value                                     */
     576                 :             :                     char *p, *q;  /* q shadows prev declaration of const char *q */
     577                 :             :                     int  n;
     578         [ #  # ]:           0 :                     if (( p = strrchr( ip->pSdfValue, '+' ) ) &&
     579         [ #  # ]:           0 :                          '[' == *( p - 1 ) &&
     580         [ #  # ]:           0 :                          0 < ( n = strtol( p + 1, &q, 10 ) ) &&
     581         [ #  # ]:           0 :                          q[0] &&
     582         [ #  # ]:           0 :                          ']' == q[0] &&
     583         [ #  # ]:           0 :                          !q[1])
     584                 :             :                     {
     585                 :           0 :                         sprintf(p + 1, "%d]", n + 1);
     586                 :             :                     }
     587                 :             :                     else
     588                 :             :                     {
     589                 :           0 :                         strcat(ip->pSdfValue, " [+1]");
     590                 :             :                     }
     591                 :             :                 }
     592                 :             : 
     593                 :         121 :                 InchiTimeGet( &ulTStart );
     594                 :             : 
     595   [ -  +  -  - ]:         121 :                 if (inp_file->type == INCHI_IOS_TYPE_FILE && inp_file->f)
     596         [ #  # ]:           0 :                     sd->fPtrStart = ( inp_file->f == stdin ) ? -1 : ftell( inp_file->f );
     597                 :             : 
     598                 :             : 
     599                 :         121 :                 nRet2 = CreateOrigInpDataFromMolfile( inp_file,
     600                 :             :                                                       orig_inp_data,
     601                 :             :                                                       ip->bMergeAllInputStructures,
     602                 :             :                                                       bGetOrigCoord,
     603                 :             :                                                       ip->bDoNotAddH,
     604                 :             :                                                       ip->bPolymers,
     605                 :             :                                                       ip->bNPZz,
     606                 :         121 :                                                       ip->pSdfLabel,
     607                 :             :                                                       ip->pSdfValue,
     608                 :             :                                                       &ip->lSdfId,
     609                 :             :                                                       &ip->lMolfileNumber,
     610                 :             :                                                       &InpAtomFlags,
     611                 :             :                                                       &sd->nStructReadError,
     612                 :         121 :                                                       sd->pStrErrStruct,
     613                 :             :                                                       ip->bNoWarnings); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     614                 :             : 
     615                 :             : 
     616                 :             : 
     617   [ -  +  -  - ]:         121 :                 if (!ip->bGetSdfileId || ip->lSdfId == 999999LU)
     618                 :             :                 {
     619                 :         121 :                     ip->lSdfId = 0LU;
     620                 :             :                 }
     621                 :             : 
     622   [ -  +  -  - ]:         121 :                 if (!ip->bGetMolfileNumber || ip->lMolfileNumber < 0)
     623                 :             :                 {
     624                 :         121 :                     ip->lMolfileNumber = 0;
     625                 :             :                 }
     626                 :             : 
     627   [ -  +  -  - ]:         121 :                 if (inp_file->type == INCHI_IOS_TYPE_FILE && inp_file->f)
     628                 :             :                 {
     629         [ #  # ]:           0 :                     sd->fPtrEnd = ( inp_file->f == stdin ) ? -1 : ftell( inp_file->f );
     630                 :             :                 }
     631                 :             : 
     632                 :         121 :                 sd->ulStructTime += InchiTimeElapsed( ic, &ulTStart );
     633                 :             : 
     634                 :             : #if ( bRELEASE_VERSION == 0 )
     635                 :             :                 sd->bExtract |= orig_inp_data->bExtract;
     636                 :             : #endif
     637                 :             : 
     638                 :             :             /* 2004-11-16: added Molfile Chiral Flag Mode */
     639                 :             :             /* ********************************************
     640                 :             :              * Chiral flags are set in:
     641                 :             :              * - RunICHI.c -- ReadTheStructure()
     642                 :             :              * - e_IchiMain.c -- main()
     643                 :             :              * - inchi_dll.c -- ExtractOneStructure
     644                 :             :              **********************************************/
     645                 :             : 
     646                 :             :             /* 1. Highest precedence: Chiral Flag set by the user */
     647         [ -  + ]:         121 :                 if (ip->bChiralFlag & FLAG_SET_INP_AT_CHIRAL)
     648                 :             :                 {
     649                 :           0 :                     InpAtomFlags = FLAG_INP_AT_CHIRAL; /* forced by the user */
     650                 :             :                 }
     651         [ -  + ]:         121 :                 else if (ip->bChiralFlag & FLAG_SET_INP_AT_NONCHIRAL)
     652                 :             :                 {
     653                 :           0 :                     InpAtomFlags = FLAG_INP_AT_NONCHIRAL; /* forced by the user */
     654                 :             :                 }
     655   [ +  +  -  + ]:         121 :                 else if (( InpAtomFlags & FLAG_INP_AT_CHIRAL ) && ( InpAtomFlags & FLAG_INP_AT_NONCHIRAL )) /* djb-rwth: correcting &&->& for bitwise calculation? */
     656                 :             :                 {
     657                 :           0 :                     InpAtomFlags &= ~FLAG_INP_AT_NONCHIRAL;
     658                 :             :                 }
     659                 :             : 
     660                 :             :                 /* Save requested flags in the AuxInfo */
     661                 :         121 :                 sd->bChiralFlag &= ~( FLAG_INP_AT_CHIRAL | FLAG_INP_AT_NONCHIRAL );
     662                 :         121 :                 sd->bChiralFlag |= InpAtomFlags & ( FLAG_INP_AT_CHIRAL | FLAG_INP_AT_NONCHIRAL );
     663                 :             : 
     664                 :             :                 /* Quick fix: modify ip->nMode on the fly */
     665                 :             : 
     666                 :             :                 /* 2. The user requested both Stereo AND Chiral flag */
     667   [ -  +  -  - ]:         121 :                 if (( ip->nMode & REQ_MODE_CHIR_FLG_STEREO ) && ( ip->nMode & REQ_MODE_STEREO ))
     668                 :             :                 {
     669         [ #  # ]:           0 :                     if (InpAtomFlags & FLAG_INP_AT_CHIRAL)
     670                 :             :                     {
     671                 :             :                         /* structure has chiral flag or the user said it is chiral */
     672                 :           0 :                         ip->nMode &= ~( REQ_MODE_RELATIVE_STEREO | REQ_MODE_RACEMIC_STEREO );
     673                 :           0 :                         sd->bChiralFlag |= FLAG_INP_AT_CHIRAL; /* write AuxInfo as chiral */
     674                 :             :                     }
     675                 :             :                     else
     676                 :             :                     {
     677                 :           0 :                         ip->nMode &= ~REQ_MODE_RACEMIC_STEREO;
     678                 :           0 :                         ip->nMode |= REQ_MODE_RELATIVE_STEREO;
     679                 :           0 :                         sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL; /* write AuxInfo as explicitly not chiral */
     680                 :             :                     }
     681                 :             :                 }
     682                 :             :             } /* if ( orig_inp_data )  */
     683                 :             : 
     684                 :             :             else    /* !orig_inp_data */
     685                 :             :             {
     686                 :             :                 /*  read the next original structure */
     687                 :           0 :                 int nStructReadError = 0;
     688                 :             : 
     689         [ #  # ]:           0 :                 if (!ip->bMergeAllInputStructures)
     690                 :             :                 {
     691                 :           0 :                     nRet2 = CreateOrigInpDataFromMolfile( inp_file,
     692                 :             :                                                           NULL,     /* *orig_at_data, */
     693                 :             :                                                           0,        /* bMergeAllInputStructures */
     694                 :             :                                                           0,        /* bGetOrigCoord */
     695                 :             :                                                           0,        /* bDoNotAddH */
     696                 :             :                                                           0, /* ip->bPolymers */
     697                 :             :                                                           0, /* ip->bNPZz */
     698                 :             :                                                           NULL,     /* *pSdfLabel */
     699                 :             :                                                           NULL,     /* *pSdfValue */
     700                 :             :                                                           NULL,     /* *lSdfId */
     701                 :             :                                                           NULL,     /* *lMolfileNumber */
     702                 :             :                                                           &InpAtomFlags, /*NULL, */
     703                 :             :                                                           &nStructReadError,
     704                 :             :                                                           NULL,      /* *pStrErr */
     705                 :             :                                                           0);
     706                 :             : 
     707   [ #  #  #  #  :           0 :                     if (nRet2 <= 0 && 10 < nStructReadError && nStructReadError < 20)
                   #  # ]
     708                 :             :                     {
     709                 :           0 :                         return _IS_EOF;
     710                 :             :                     }
     711                 :             :                 }
     712                 :             :                 else
     713                 :             :                 {
     714                 :           0 :                     return _IS_EOF;
     715                 :             :                 }
     716                 :             :             }
     717                 :             : 
     718                 :         121 :             break;
     719                 :             : 
     720                 :           0 :         case INPUT_INCHI_PLAIN:
     721                 :             :             /*  Read the original input data  as text (InChI string ) */
     722         [ #  # ]:           0 :             if (orig_inp_data)
     723                 :             :             {
     724   [ #  #  #  # ]:           0 :                 if (ip->pSdfValue && ip->pSdfValue[0])
     725                 :             :                 {
     726                 :             :                     /* Added 07-29-2003 to avoid inheriting exact value from prev. structure
     727                 :             :                        and to make reference to a (bad) structure with unknown ID Value */
     728                 :             :                     char *p, *q;
     729                 :             :                     int  n;
     730         [ #  # ]:           0 :                     if (( p = strrchr( ip->pSdfValue, '+' ) ) &&
     731         [ #  # ]:           0 :                          '[' == *( p - 1 ) &&
     732         [ #  # ]:           0 :                          0 < ( n = strtol( p + 1, &q, 10 ) ) &&
     733         [ #  # ]:           0 :                          q[0] &&
     734         [ #  # ]:           0 :                          ']' == q[0] &&
     735         [ #  # ]:           0 :                          !q[1])
     736                 :             :                     {
     737                 :           0 :                         sprintf(p + 1, "%d]", n + 1);
     738                 :             :                     }
     739                 :             :                     else
     740                 :             :                     {
     741                 :           0 :                         strcat(ip->pSdfValue, " [+1]");
     742                 :             :                     }
     743                 :             :                 }
     744                 :             : 
     745                 :           0 :                 InchiTimeGet( &ulTStart );
     746                 :             : 
     747   [ #  #  #  # ]:           0 :                 if (inp_file->type == INCHI_IOS_TYPE_FILE && inp_file->f)
     748                 :             :                 {
     749         [ #  # ]:           0 :                     sd->fPtrStart = ( inp_file->f == stdin ) ? -1 : ftell( inp_file->f );
     750                 :             :                 }
     751                 :             : 
     752                 :             : 
     753                 :             :                 /*  Read and make internal molecular  data */
     754                 :           0 :                 nRet2 = InchiToOrigAtom( inp_file,
     755                 :             :                                          orig_inp_data,
     756                 :             :                                          ip->bMergeAllInputStructures,
     757                 :             :                                          bGetOrigCoord,
     758                 :             :                                          ip->bDoNotAddH,
     759                 :             :                                          vABParityUnknown,
     760                 :             :                                          ip->nInputType,
     761                 :             :                                          ip->pSdfLabel,
     762                 :             :                                          ip->pSdfValue,
     763                 :           0 :                                          (unsigned long *) &ip->lMolfileNumber,
     764                 :             :                                          &InpAtomFlags,
     765                 :             :                                          &sd->nStructReadError,
     766                 :           0 :                                          sd->pStrErrStruct ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     767                 :             : 
     768                 :             :                 /*if ( !ip->bGetSdfileId || ip->lSdfId == 999999LU) ip->lSdfId = 0;*/
     769   [ #  #  #  # ]:           0 :                 if (inp_file->type == INCHI_IOS_TYPE_FILE && inp_file->f)
     770                 :             :                 {
     771         [ #  # ]:           0 :                     sd->fPtrEnd = ( inp_file->f == stdin ) ? -1 : ftell( inp_file->f );
     772                 :             :                 }
     773                 :             : 
     774                 :           0 :                 sd->ulStructTime += InchiTimeElapsed( ic, &ulTStart );
     775                 :             : 
     776                 :             : #if ( bRELEASE_VERSION == 0 )
     777                 :             :                 sd->bExtract |= orig_inp_data->bExtract;
     778                 :             : #endif
     779                 :             : 
     780                 :             :                 /* 2004-11-16: added Molfile Chiral Flag Mode */
     781         [ #  # ]:           0 :                 if (ip->bChiralFlag & FLAG_SET_INP_AT_CHIRAL)
     782                 :             :                 {
     783                 :           0 :                     InpAtomFlags = FLAG_INP_AT_CHIRAL; /* forced by the user */
     784                 :             :                 }
     785         [ #  # ]:           0 :                 else if (ip->bChiralFlag & FLAG_SET_INP_AT_NONCHIRAL)
     786                 :             :                 {
     787                 :           0 :                     InpAtomFlags = FLAG_INP_AT_NONCHIRAL; /* forced by the user */
     788                 :             :                 }
     789   [ #  #  #  # ]:           0 :                 else if (( InpAtomFlags & FLAG_INP_AT_CHIRAL ) && ( InpAtomFlags & FLAG_INP_AT_NONCHIRAL )) /* djb-rwth: correcting &&->& for bitwise calculation? */
     790                 :             :                 {
     791                 :           0 :                     InpAtomFlags &= ~FLAG_INP_AT_NONCHIRAL;
     792                 :             :                 }
     793                 :             : 
     794                 :           0 :                 sd->bChiralFlag |= InpAtomFlags; /* copy chiral flag to AuxInfo */
     795                 :             : 
     796                 :             :                 /* Quick fix: modify ip->nMode on the fly */
     797   [ #  #  #  # ]:           0 :                 if (( ip->nMode & REQ_MODE_CHIR_FLG_STEREO ) && ( ip->nMode & REQ_MODE_STEREO ))
     798                 :             :                 {
     799         [ #  # ]:           0 :                     if (InpAtomFlags & FLAG_INP_AT_CHIRAL)
     800                 :             :                     {
     801                 :           0 :                         ip->nMode &= ~( REQ_MODE_RELATIVE_STEREO | REQ_MODE_RACEMIC_STEREO );
     802                 :             :                     }
     803                 :             :                     else
     804                 :             :                     {
     805                 :           0 :                         ip->nMode &= ~REQ_MODE_RACEMIC_STEREO;
     806                 :           0 :                         ip->nMode |= REQ_MODE_RELATIVE_STEREO;
     807                 :             :                     }
     808                 :             :                 }
     809                 :             :             }
     810                 :             :             else
     811                 :             :             {
     812                 :             :                 /*  Read the next original structure */
     813                 :           0 :                 int           nStructReadError = 0;
     814         [ #  # ]:           0 :                 if (!ip->bMergeAllInputStructures)
     815                 :             :                 {
     816                 :           0 :                     nRet2 = InchiToOrigAtom( inp_file,
     817                 :             :                                              NULL, 0, 0, 0, 0,
     818                 :             :                                              ip->nInputType,
     819                 :             :                                              NULL, NULL, NULL, NULL,
     820                 :             :                                              &nStructReadError,
     821                 :             :                                              NULL );
     822   [ #  #  #  #  :           0 :                     if (nRet2 <= 0 && 10 < nStructReadError && nStructReadError < 20)
                   #  # ]
     823                 :             :                     {
     824                 :           0 :                         return _IS_EOF;
     825                 :             :                     }
     826                 :             :                 }
     827                 :             :                 else
     828                 :             :                 {
     829                 :           0 :                     return _IS_EOF;
     830                 :             :                 }
     831                 :             :             }
     832                 :           0 :             break;
     833                 :             : 
     834                 :           0 :         default:
     835                 :           0 :             nRet = _IS_FATAL; /*  wrong file type */
     836                 :             :     }
     837                 :             : 
     838                 :         121 :     return nRet;
     839                 :             : }
     840                 :             : 
     841                 :             : 
     842                 :             : /****************************************************************************
     843                 :             :  Interpret and treat input reading errors/warnings
     844                 :             : ****************************************************************************/
     845                 :         121 : int TreatErrorsInReadTheStructure( STRUCT_DATA      *sd,
     846                 :             :                                    INPUT_PARMS      *ip,
     847                 :             :                                    int              nLogMask,
     848                 :             :                                    INCHI_IOSTREAM   *inp_file,
     849                 :             :                                    INCHI_IOSTREAM   *log_file,
     850                 :             :                                    INCHI_IOSTREAM   *out_file,
     851                 :             :                                    INCHI_IOSTREAM   *prb_file,
     852                 :             :                                    ORIG_ATOM_DATA   *orig_inp_data,
     853                 :             :                                    long             *num_inp )
     854                 :             : {
     855                 :         121 :     int nRet = _IS_OKAY;
     856                 :             : 
     857   [ -  +  -  - ]:         121 :     if (10 < sd->nStructReadError && sd->nStructReadError < 20)
     858                 :             :     {
     859                 :             :         /*  End of file */
     860         [ #  # ]:           0 :         if (sd->pStrErrStruct[0])
     861                 :             :         {
     862   [ #  #  #  #  :           0 :             inchi_ios_eprint( log_file, "%s inp structure #%ld: End of file.%s%s%s%s    \n", sd->pStrErrStruct, *num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     863                 :             :         }
     864                 :             : 
     865                 :           0 :         inchi_ios_eprint( log_file, "End of file detected after structure #%ld.   \n", *num_inp - 1 );
     866                 :             : 
     867                 :           0 :         nRet = _IS_EOF;
     868                 :           0 :         goto exit_function; /*  end of file */
     869                 :             :     }
     870                 :             : 
     871                 :             :     /*(*num_inp) ++;*/
     872                 :             : 
     873         [ -  + ]:         121 :     if (*num_inp < ip->first_struct_number)
     874                 :             :     {
     875                 :             :         /*  Skip the structure */
     876                 :             : 
     877                 :             : #if ( !defined(TARGET_API_LIB) && !defined(TARGET_EXE_STANDALONE) )
     878                 :             : /* #ifndef TARGET_API_LIB */
     879                 :             :         if (log_file->f != stderr)
     880                 :             :             inchi_fprintf( stderr, "\rSkipping structure #%ld.%s%s%s%s...", *num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
     881                 :             : #endif
     882                 :             : 
     883                 :           0 :         nRet = sd->nErrorType = _IS_SKIP;
     884                 :           0 :         goto exit_function;
     885                 :             :     }
     886                 :             : 
     887                 :         242 :     sd->nErrorType = GetInpStructErrorType( ip, sd->nStructReadError,
     888                 :         121 :                                             sd->pStrErrStruct,
     889                 :             :                                             orig_inp_data->num_inp_atoms );
     890                 :             : 
     891         [ -  + ]:         121 :     if (sd->nErrorType == _IS_FATAL)
     892                 :             :     {
     893                 :             :         /*  Fatal error */
     894         [ #  # ]:           0 :         if (nLogMask & LOG_MASK_FATAL)
     895                 :             :         {
     896                 :           0 :             inchi_ios_eprint( log_file, "Fatal Error %d (aborted; %s) inp structure #%ld.%s%s%s%s\n",
     897   [ #  #  #  #  :           0 :                      sd->nStructReadError, sd->pStrErrStruct, *num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     898                 :             :         }
     899                 :             : 
     900                 :             : #if ( bRELEASE_VERSION == 1 || EXTR_FLAGS == 0 )
     901                 :             :         /* djb-rwth: fixing oss-fuzz issue #27902 */
     902   [ #  #  #  #  :           0 :         if (prb_file && prb_file->f && 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd && !ip->bSaveAllGoodStructsAsProblem)
          #  #  #  #  #  
                      # ]
     903                 :             :         {
     904                 :           0 :             MolfileSaveCopy( inp_file, sd->fPtrStart, sd->fPtrEnd, prb_file->f, *num_inp );
     905                 :             :         }
     906                 :             : #endif
     907                 :             :         /* goto exit_function; */
     908                 :             :     }
     909                 :             : 
     910         [ -  + ]:         121 :     if (sd->nErrorType == _IS_ERROR)
     911                 :             :     {
     912                 :             :         /*  Non-fatal errors: do not produce INChI */
     913                 :             : 
     914                 :             :         /*  70 => too many atoms */
     915         [ #  # ]:           0 :         if (nLogMask & LOG_MASK_ERR)
     916                 :             :         {
     917                 :           0 :             inchi_ios_eprint( log_file, "Error %d (no %s; %s) inp structure #%ld.%s%s%s%s\n",
     918                 :           0 :                  sd->nStructReadError, ( ip->bINChIOutputOptions & INCHI_OUT_SDFILE_ONLY ) ? "Molfile" : INCHI_NAME,
     919   [ #  #  #  #  :           0 :                  sd->pStrErrStruct, *num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
     920                 :             :         }
     921                 :             : 
     922                 :             : #if ( bRELEASE_VERSION == 1 || EXTR_FLAGS == 0 )
     923   [ #  #  #  #  :           0 :         if (prb_file && prb_file->f && 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd && !ip->bSaveAllGoodStructsAsProblem)
          #  #  #  #  #  
                      # ]
     924                 :             :         {
     925                 :           0 :             MolfileSaveCopy( inp_file, sd->fPtrStart, sd->fPtrEnd, prb_file->f, *num_inp ); /* djb-rwth: addressing coverity ID #499477 -- return values handled properly */
     926                 :             :         }
     927                 :             : #endif
     928                 :             :     }
     929                 :             : 
     930         [ +  + ]:         121 :     if (sd->nErrorType == _IS_WARNING)
     931                 :             :     {
     932                 :             :         /*  Warnings: try to produce INChI */
     933                 :             : 
     934         [ -  + ]:          11 :         if (nLogMask & LOG_MASK_WARN)
     935                 :             :         {
     936                 :          44 :             inchi_ios_eprint( log_file, "Warning: (%s) inp structure #%ld.%s%s%s%s\n",
     937   [ -  +  -  -  :          55 :                sd->pStrErrStruct, *num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
          -  +  -  -  -  
          +  -  -  -  -  
          -  -  -  +  -  
             -  -  +  -  
                      - ]
     938                 :             :         }
     939                 :             :     }
     940                 :             : 
     941                 :             : 
     942                 :             : #ifdef TARGET_LIB_FOR_WINCHI
     943                 :             :     if (( ip->bINChIOutputOptions & INCHI_OUT_WINCHI_WINDOW ) &&
     944                 :             :         ( ip->bINChIOutputOptions & INCHI_OUT_PLAIN_TEXT ))
     945                 :             :     {
     946                 :             :         if (sd->nErrorType != _IS_OKAY && sd->nErrorType != _IS_WARNING)
     947                 :             :         {
     948                 :             :             sd->nErrorType =
     949                 :             :                 ProcessStructError( out_file, log_file, sd->pStrErrStruct, sd->nErrorType, *num_inp, ip );
     950                 :             :         }
     951                 :             :     }
     952                 :             : #endif
     953                 :             : 
     954                 :         110 : exit_function:
     955   [ +  -  +  + ]:         121 :     if (nRet <= _IS_OKAY && sd->nErrorType > 0)
     956                 :             :     {
     957                 :          11 :         nRet = sd->nErrorType;
     958                 :             :     }
     959                 :             : 
     960                 :         121 :     return nRet;
     961                 :             : }
     962                 :             : 
     963                 :             : 
     964                 :             : #ifdef TARGET_EXE_USING_API
     965                 :             : 
     966                 :             : 
     967                 :             : /****************************************************************************/
     968                 :             : int InchiToInchi_Input( INCHI_IOSTREAM  *inp_file,
     969                 :             :                         inchi_Input     *orig_at_data,
     970                 :             :                         int             bMergeAllInputStructures,
     971                 :             :                         int             bDoNotAddH,
     972                 :             :                         int             vABParityUnknown,
     973                 :             :                         INPUT_TYPE      nInputType,
     974                 :             :                         char            *pSdfLabel,
     975                 :             :                         char            *pSdfValue,
     976                 :             :                         unsigned long   *lSdfId,
     977                 :             :                         INCHI_MODE      *pInpAtomFlags,
     978                 :             :                         int             *err,
     979                 :             :                         char            *pStrErr )
     980                 :             : {
     981                 :             : /* inp_ATOM       *at = NULL; */
     982                 :             :     int             num_dimensions_new;
     983                 :             :     int             num_inp_bonds_new;
     984                 :             :     int             num_inp_atoms_new;
     985                 :             :     int             num_inp_0D_new;
     986                 :             :     inp_ATOM     *at_new = NULL;
     987                 :             :     inp_ATOM     *at_old = NULL;
     988                 :             :     inchi_Stereo0D *stereo0D_new = NULL;
     989                 :             :     inchi_Stereo0D *stereo0D_old = NULL;
     990                 :             :     int             nNumAtoms = 0, nNumStereo0D = 0;
     991                 :             :     MOL_COORD      *szCoordNew = NULL;
     992                 :             :     MOL_COORD      *szCoordOld = NULL;
     993                 :             :     int            i, j;
     994                 :             :     int               max_num_at;
     995                 :             : 
     996                 :             : 
     997                 :             :     max_num_at = MAX_ATOMS;
     998                 :             :     if (*pInpAtomFlags  & FLAG_SET_INP_LARGE_MOLS)
     999                 :             :         max_num_at = MAX_ATOMS_LARGE_MOL;
    1000                 :             : 
    1001                 :             :     if (pStrErr)
    1002                 :             :         pStrErr[0] = '\0';
    1003                 :             : 
    1004                 :             : 
    1005                 :             :     /*FreeOrigAtData( orig_at_data );*/
    1006                 :             :     if (lSdfId)
    1007                 :             :         *lSdfId = 0LU;
    1008                 :             : 
    1009                 :             :     do
    1010                 :             :     {
    1011                 :             :         at_old = orig_at_data ? orig_at_data->atom : NULL; /*  save pointer to the previous allocation */
    1012                 :             : 
    1013                 :             :         stereo0D_old = orig_at_data ? orig_at_data->stereo0D : NULL;
    1014                 :             : 
    1015                 :             :         szCoordOld = NULL;
    1016                 :             : 
    1017                 :             :         num_inp_atoms_new =
    1018                 :             :             InchiToinp_ATOM( inp_file, orig_at_data ? &stereo0D_new : NULL, &num_inp_0D_new,
    1019                 :             :                           bDoNotAddH, vABParityUnknown, nInputType,
    1020                 :             :                           orig_at_data ? &at_new : NULL, MAX_ATOMS,
    1021                 :             :                           &num_dimensions_new, &num_inp_bonds_new,
    1022                 :             :                           pSdfLabel, pSdfValue, lSdfId, pInpAtomFlags, err, pStrErr );
    1023                 :             : 
    1024                 :             :         if (num_inp_atoms_new <= 0 && !*err)
    1025                 :             :         {
    1026                 :             :             TREAT_ERR( *err, 0, "Empty structure" );
    1027                 :             :             *err = 98;
    1028                 :             :         }
    1029                 :             :         else if (orig_at_data &&
    1030                 :             :                   !num_inp_atoms_new &&
    1031                 :             :                   10 < *err && *err < 20 &&
    1032                 :             :                   orig_at_data->num_atoms > 0
    1033                 :             :                   && bMergeAllInputStructures)
    1034                 :             :         {
    1035                 :             :             *err = 0; /* end of file */
    1036                 :             :             break;
    1037                 :             :         }
    1038                 :             :         else if (num_inp_atoms_new > 0 && orig_at_data)
    1039                 :             :         {
    1040                 :             :             /*  merge pOrigDataTmp + orig_at_data => pOrigDataTmp; */
    1041                 :             :             nNumAtoms = num_inp_atoms_new + orig_at_data->num_atoms;
    1042                 :             :             nNumStereo0D = num_inp_0D_new + orig_at_data->num_stereo0D;
    1043                 :             : 
    1044                 :             :             if (nNumAtoms >= max_num_at) /*MAX_ATOMS ) */
    1045                 :             :             {
    1046                 :             :                 TREAT_ERR( *err, 0, "Too many atoms [check  'LargeMolecules' switch]" );
    1047                 :             :                 *err = 70;
    1048                 :             :                 orig_at_data->num_atoms = -1;
    1049                 :             :             }
    1050                 :             :             else if (!at_old)
    1051                 :             :             {
    1052                 :             :                 /* the first structure */
    1053                 :             : 
    1054                 :             :                 orig_at_data->atom = at_new;            at_new = NULL;
    1055                 :             :                 orig_at_data->num_atoms = num_inp_atoms_new; num_inp_atoms_new = 0;
    1056                 :             :                 orig_at_data->stereo0D = stereo0D_new;      stereo0D_new = NULL;
    1057                 :             :                 orig_at_data->num_stereo0D = num_inp_0D_new;    num_inp_0D_new = 0;
    1058                 :             :             }
    1059                 :             :             else if (orig_at_data->atom = Createinp_ATOM( nNumAtoms ))
    1060                 :             :             {
    1061                 :             :                 /*  switch at_new <--> orig_at_data->at; */
    1062                 :             : 
    1063                 :             :                 if (orig_at_data->num_atoms)
    1064                 :             :                 {
    1065                 :             :                     memcpy( orig_at_data->atom, at_old, orig_at_data->num_atoms * sizeof( orig_at_data->atom[0] ) );
    1066                 :             :                     /*  adjust numbering in the newly read structure */
    1067                 :             :                     for (i = 0; i < num_inp_atoms_new; i++)
    1068                 :             :                     {
    1069                 :             :                         for (j = 0; j < at_new[i].num_bonds; j++)
    1070                 :             :                         {
    1071                 :             :                             at_new[i].neighbor[j] += orig_at_data->num_atoms;
    1072                 :             :                         }
    1073                 :             :                     }
    1074                 :             :                 }
    1075                 :             :                 Freeinp_ATOM( &at_old );
    1076                 :             : 
    1077                 :             :                 /*  copy newly read structure */
    1078                 :             :                 memcpy( orig_at_data->atom + orig_at_data->num_atoms,
    1079                 :             :                         at_new,
    1080                 :             :                         num_inp_atoms_new * sizeof( orig_at_data->atom[0] ) );
    1081                 :             : 
    1082                 :             :                 /*  copy newly read 0D stereo */
    1083                 :             :                 if (num_inp_0D_new > 0 && stereo0D_new)
    1084                 :             :                 {
    1085                 :             :                     if (orig_at_data->stereo0D = CreateInchi_Stereo0D( nNumStereo0D ))
    1086                 :             :                     {
    1087                 :             :                         int ncopy = orig_at_data->num_stereo0D * sizeof( orig_at_data->stereo0D[0] );
    1088                 :             :                         memcpy( orig_at_data->stereo0D, stereo0D_old, ncopy );
    1089                 :             : 
    1090                 :             :                         /*  adjust numbering in the newly read structure */
    1091                 :             :                         for (i = 0; i < num_inp_0D_new; i++)
    1092                 :             :                         {
    1093                 :             :                             if (stereo0D_new[i].central_atom >= 0)
    1094                 :             :                                 stereo0D_new[i].central_atom += orig_at_data->num_atoms;
    1095                 :             : 
    1096                 :             :                             for (j = 0; j < 4; j++)
    1097                 :             :                                 stereo0D_new[i].neighbor[j] += orig_at_data->num_atoms;
    1098                 :             :                         }
    1099                 :             : 
    1100                 :             :                         FreeInchi_Stereo0D( &stereo0D_old );
    1101                 :             : 
    1102                 :             :                         int ncopy = num_inp_0D_new * sizeof( orig_at_data->stereo0D[0] );
    1103                 :             :                         memcpy( orig_at_data->stereo0D + orig_at_data->num_stereo0D,
    1104                 :             :                                 stereo0D_new,
    1105                 :             :                                 ncopy );
    1106                 :             :                     }
    1107                 :             :                     else
    1108                 :             :                     {
    1109                 :             :                         num_inp_0D_new = 0;
    1110                 :             :                         TREAT_ERR( *err, 0, "Out of RAM" );
    1111                 :             :                         *err = -1;
    1112                 :             :                     }
    1113                 :             :                 }
    1114                 :             :                 else
    1115                 :             :                 {
    1116                 :             :                     num_inp_0D_new = 0;
    1117                 :             :                 }
    1118                 :             : 
    1119                 :             :                 /* update lengths */
    1120                 :             :                 orig_at_data->num_atoms += num_inp_atoms_new;
    1121                 :             :                 orig_at_data->num_stereo0D += num_inp_0D_new;
    1122                 :             :             }
    1123                 :             :             else
    1124                 :             :             {
    1125                 :             :                 TREAT_ERR( *err, 0, "Out of RAM" );
    1126                 :             :                 *err = -1;
    1127                 :             :             }
    1128                 :             :         }
    1129                 :             :         else if (num_inp_atoms_new > 0)
    1130                 :             :         {
    1131                 :             :             nNumAtoms += num_inp_atoms_new;
    1132                 :             :         }
    1133                 :             : 
    1134                 :             :         Freeinp_ATOM( &at_new );
    1135                 :             :         num_inp_atoms_new = 0;
    1136                 :             :         FreeInchi_Stereo0D( &stereo0D_new );
    1137                 :             :         num_inp_0D_new = 0;
    1138                 :             :     }
    1139                 :             :     while (!*err && bMergeAllInputStructures);
    1140                 :             : 
    1141                 :             :  /*
    1142                 :             :  if ( !*err )
    1143                 :             :  {
    1144                 :             :      orig_at_data->num_components =
    1145                 :             :          MarkDisconnectedComponents( orig_at_data );
    1146                 :             :      if ( orig_at_data->num_components == 0 )
    1147                 :             :      {
    1148                 :             :          TREAT_ERR (*err, 0, "No components found");
    1149                 :             :          *err = 99;
    1150                 :             :      }
    1151                 :             :      if ( orig_at_data->num_components < 0 )
    1152                 :             :      {
    1153                 :             :          TREAT_ERR (*err, 0, "Too many components");
    1154                 :             :          *err = 99;
    1155                 :             :      }
    1156                 :             :  }
    1157                 :             :  */
    1158                 :             : 
    1159                 :             :     if (szCoordNew)
    1160                 :             :         inchi_free( szCoordNew );
    1161                 :             : 
    1162                 :             :     if (at_new)
    1163                 :             :         inchi_free( at_new );
    1164                 :             : 
    1165                 :             :     /*
    1166                 :             :     if ( !*err )
    1167                 :             :     {
    1168                 :             :         if ( ReconcileAllCmlBondParities( orig_at_data->atom, orig_at_data->num_atoms ) )
    1169                 :             :         {
    1170                 :             :             TREAT_ERR (*err, 0, "Cannot reconcile stereobond parities");
    1171                 :             :             if (!orig_at_data->num_atoms)
    1172                 :             :             {
    1173                 :             :                 *err = 1;
    1174                 :             :             }
    1175                 :             :         }
    1176                 :             :     }
    1177                 :             :     */
    1178                 :             : 
    1179                 :             :     if (*err)
    1180                 :             :         FreeInchi_Input( orig_at_data );
    1181                 :             : 
    1182                 :             :     if (*err && !( 10 < *err && *err < 20 ) && pStrErr && !pStrErr[0])
    1183                 :             :     {
    1184                 :             :         TREAT_ERR( *err, 0, "Unknown error" );  /*   <BRKPT> */
    1185                 :             :     }
    1186                 :             : 
    1187                 :             :     return orig_at_data ? orig_at_data->num_atoms : nNumAtoms;
    1188                 :             : }
    1189                 :             : 
    1190                 :             : #endif /* #ifdef TARGET_EXE_USING_API */
    1191                 :             : 
    1192                 :             : 
    1193                 :             : /****************************************************************************
    1194                 :             :  Read input InChI string and fill internal data structs
    1195                 :             : ****************************************************************************/
    1196                 :           0 : int InchiToOrigAtom( INCHI_IOSTREAM *inp_molfile,
    1197                 :             :                      ORIG_ATOM_DATA *orig_at_data,
    1198                 :             :                      int            bMergeAllInputStructures,
    1199                 :             :                      int            bGetOrigCoord,
    1200                 :             :                      int            bDoNotAddH,
    1201                 :             :                      int            vABParityUnknown,
    1202                 :             :                      INPUT_TYPE     nInputType,
    1203                 :             :                      char           *pSdfLabel,
    1204                 :             :                      char           *pSdfValue,
    1205                 :             :                      unsigned long *lSdfId,
    1206                 :             :                      INCHI_MODE     *pInpAtomFlags,
    1207                 :             :                      int            *err,
    1208                 :             :                      char           *pStrErr )
    1209                 :             : {
    1210                 :             :     int       num_dimensions_new;
    1211                 :             :     int       num_inp_bonds_new;
    1212                 :             :     int       num_inp_atoms_new;
    1213                 :           0 :     inp_ATOM  *at_new = NULL;
    1214                 :           0 :     inp_ATOM  *at_old = NULL;
    1215                 :           0 :     MOL_COORD *szCoordNew = NULL;
    1216                 :           0 :     MOL_COORD *szCoordOld = NULL;
    1217                 :           0 :     int       nNumAtoms = 0;
    1218                 :             :     int       i, j, max_num_at;
    1219                 :             : 
    1220                 :             : 
    1221                 :           0 :     max_num_at = MAX_ATOMS;
    1222         [ #  # ]:           0 :     if (!( *pInpAtomFlags  & FLAG_SET_INP_LARGE_MOLS ))
    1223                 :             :     {
    1224                 :           0 :         max_num_at = NORMALLY_ALLOWED_INP_MAX_ATOMS;
    1225                 :             :     }
    1226                 :             : 
    1227         [ #  # ]:           0 :     if (pStrErr)
    1228                 :             :     {
    1229                 :           0 :         pStrErr[0] = '\0';
    1230                 :             :     }
    1231                 :             : 
    1232                 :             :     /*FreeOrigAtData( orig_at_data );*/
    1233         [ #  # ]:           0 :     if (lSdfId)
    1234                 :             :     {
    1235                 :           0 :         *lSdfId = 0LU;
    1236                 :             :     }
    1237                 :             : 
    1238                 :             :     do
    1239                 :             :     {
    1240         [ #  # ]:           0 :         at_old = orig_at_data ? orig_at_data->at : NULL; /*  save pointer to the previous allocation */
    1241                 :             : 
    1242         [ #  # ]:           0 :         szCoordOld = orig_at_data ? orig_at_data->szCoord : NULL;
    1243                 :             : 
    1244   [ #  #  #  # ]:           0 :         num_inp_atoms_new = InchiToInpAtom( inp_molfile,
    1245         [ #  # ]:           0 :                                             ( bGetOrigCoord && orig_at_data ) ? &szCoordNew : NULL,
    1246                 :             :                                             bDoNotAddH,
    1247                 :             :                                             vABParityUnknown,
    1248                 :             :                                             nInputType,
    1249                 :             :                                             orig_at_data ? &at_new : NULL,
    1250                 :             :                                             MAX_ATOMS,
    1251                 :             :                                             &num_dimensions_new,
    1252                 :             :                                             &num_inp_bonds_new,
    1253                 :             :                                             pSdfLabel,
    1254                 :             :                                             pSdfValue,
    1255                 :             :                                             lSdfId,
    1256                 :             :                                             pInpAtomFlags,
    1257                 :             :                                             err,
    1258                 :             :                                             pStrErr );
    1259                 :             : 
    1260   [ #  #  #  # ]:           0 :         if (num_inp_atoms_new <= 0 && !*err)
    1261                 :             :         {
    1262                 :           0 :             TREAT_ERR( *err, 0, "Empty structure" );
    1263                 :           0 :             *err = 98;
    1264                 :             :         }
    1265   [ #  #  #  # ]:           0 :         else if (orig_at_data && !num_inp_atoms_new &&
    1266   [ #  #  #  # ]:           0 :                   10 < *err && *err < 20 &&
    1267   [ #  #  #  # ]:           0 :                   orig_at_data->num_inp_atoms > 0 &&
    1268                 :             :                   bMergeAllInputStructures)
    1269                 :             :         {
    1270                 :           0 :             *err = 0; /* end of file */
    1271                 :           0 :             break;
    1272                 :             :         }
    1273   [ #  #  #  # ]:           0 :         else if (num_inp_atoms_new > 0 && orig_at_data)
    1274                 :             :         {
    1275                 :             :             /*  merge pOrigDataTmp + orig_at_data => pOrigDataTmp; */
    1276                 :           0 :             nNumAtoms = num_inp_atoms_new + orig_at_data->num_inp_atoms;
    1277         [ #  # ]:           0 :             if (nNumAtoms >= max_num_at) /*MAX_ATOMS ) */
    1278                 :             :             {
    1279                 :           0 :                 TREAT_ERR( *err, 0, "Too many atoms [check  'LargeMolecules' switch]" );
    1280                 :           0 :                 *err = 70;
    1281                 :           0 :                 orig_at_data->num_inp_atoms = -1;
    1282                 :             :             }
    1283         [ #  # ]:           0 :             else if (!at_old)
    1284                 :             :             {
    1285                 :             :                 /* the first structure */
    1286                 :           0 :                 orig_at_data->at = at_new;
    1287                 :           0 :                 orig_at_data->szCoord = szCoordNew;
    1288                 :           0 :                 at_new = NULL;
    1289                 :           0 :                 szCoordNew = NULL;
    1290                 :           0 :                 orig_at_data->num_inp_atoms = num_inp_atoms_new;
    1291                 :           0 :                 orig_at_data->num_inp_bonds = num_inp_bonds_new;
    1292                 :           0 :                 orig_at_data->num_dimensions = num_dimensions_new;
    1293                 :             :             }
    1294         [ #  # ]:           0 :             else if (( orig_at_data->at = (inp_ATOM*) inchi_calloc( nNumAtoms, sizeof( inp_ATOM ) ) ) &&
    1295   [ #  #  #  # ]:           0 :                 ( !szCoordNew || ( orig_at_data->szCoord = (MOL_COORD *) inchi_calloc( nNumAtoms, sizeof( MOL_COORD ) ) ) ))
    1296                 :             :             {
    1297                 :             :                 /*  switch at_new <--> orig_at_data->at; */
    1298         [ #  # ]:           0 :                 if (orig_at_data->num_inp_atoms)
    1299                 :             :                 {
    1300                 :           0 :                     memcpy(orig_at_data->at,
    1301                 :             :                         at_old,
    1302                 :           0 :                         orig_at_data->num_inp_atoms * sizeof(orig_at_data->at[0]));
    1303                 :             :                     /*  adjust numbering in the newly read structure */
    1304         [ #  # ]:           0 :                     for (i = 0; i < num_inp_atoms_new; i++)
    1305                 :             :                     {
    1306         [ #  # ]:           0 :                         if (at_new) /* djb-rwth: fixing a NULL pointer dereference */
    1307                 :             :                         {
    1308         [ #  # ]:           0 :                             for (j = 0; j < at_new[i].valence; j++)
    1309                 :             :                             {
    1310                 :           0 :                                 at_new[i].neighbor[j] += orig_at_data->num_inp_atoms;
    1311                 :             :                             }
    1312                 :           0 :                             at_new[i].orig_at_number += orig_at_data->num_inp_atoms; /* 12-19-2003 */
    1313                 :             :                         }
    1314                 :             :                     }
    1315   [ #  #  #  # ]:           0 :                     if (orig_at_data->szCoord && szCoordOld)
    1316                 :             :                     {
    1317                 :           0 :                         memcpy(orig_at_data->szCoord,
    1318                 :             :                             szCoordOld,
    1319                 :           0 :                             orig_at_data->num_inp_atoms * sizeof(MOL_COORD));
    1320                 :             :                     }
    1321                 :             :                 }
    1322         [ #  # ]:           0 :                 if (at_old)
    1323                 :             :                 {
    1324                 :             :                     /* inchi_free( at_old ); */ /* djb-rwth: avoiding the use of freed memory */
    1325                 :           0 :                     at_old = NULL;
    1326                 :             :                 }
    1327         [ #  # ]:           0 :                 if (szCoordOld)
    1328                 :             :                 {
    1329                 :             :                     /* inchi_free( szCoordOld ); */ /* djb-rwth: avoiding the use of freed memory */
    1330                 :           0 :                     szCoordOld = NULL;
    1331                 :             :                 }
    1332                 :             :                 /*  copy newly read structure */
    1333         [ #  # ]:           0 :                 if (at_new) /* djb-rwth: fixing a NULL pointer dereference */
    1334                 :           0 :                     memcpy(orig_at_data->at + orig_at_data->num_inp_atoms, at_new, num_inp_atoms_new * sizeof(orig_at_data->at[0]));
    1335   [ #  #  #  # ]:           0 :                 if (orig_at_data->szCoord && szCoordNew)
    1336                 :             :                 {
    1337                 :           0 :                     memcpy(orig_at_data->szCoord + orig_at_data->num_inp_atoms,
    1338                 :             :                         szCoordNew,
    1339                 :             :                         num_inp_atoms_new * sizeof(MOL_COORD));
    1340                 :             :                 }
    1341                 :             :                 /*  add other things */
    1342                 :           0 :                 orig_at_data->num_inp_atoms += num_inp_atoms_new;
    1343                 :           0 :                 orig_at_data->num_inp_bonds += num_inp_bonds_new;
    1344                 :           0 :                 orig_at_data->num_dimensions = inchi_max( num_dimensions_new, orig_at_data->num_dimensions );
    1345                 :             :             }
    1346                 :             :             else
    1347                 :             :             {
    1348                 :           0 :                 TREAT_ERR( *err, 0, "Out of RAM" );
    1349                 :           0 :                 *err = -1;
    1350                 :             :             }
    1351                 :             :         }
    1352         [ #  # ]:           0 :         else if (num_inp_atoms_new > 0)
    1353                 :             :         {
    1354                 :           0 :             nNumAtoms += num_inp_atoms_new;
    1355                 :             :         }
    1356         [ #  # ]:           0 :         if (at_new)
    1357                 :             :         {
    1358                 :             :             /* inchi_free( at_new ); */ /* djb-rwth: avoiding the use of freed memory */
    1359                 :           0 :             at_new = NULL;
    1360                 :             :         }
    1361                 :             :     }
    1362   [ #  #  #  # ]:           0 :     while (!*err && bMergeAllInputStructures);
    1363                 :             : 
    1364                 :             :      /*
    1365                 :             :      if ( !*err ) {
    1366                 :             :          orig_at_data->num_components =
    1367                 :             :              MarkDisconnectedComponents( orig_at_data );
    1368                 :             :          if ( orig_at_data->num_components == 0 ) {
    1369                 :             :              TREAT_ERR (*err, 0, "No components found");
    1370                 :             :              *err = 99;
    1371                 :             :          }
    1372                 :             :          if ( orig_at_data->num_components < 0 ) {
    1373                 :             :              TREAT_ERR (*err, 0, "Too many components");
    1374                 :             :              *err = 99;
    1375                 :             :          }
    1376                 :             :      }
    1377                 :             :      */
    1378                 :             : 
    1379                 :             :     /* djb-rwth: avoiding the use of freed memory */
    1380                 :             :     /*
    1381                 :             :     if (szCoordNew)
    1382                 :             :     {
    1383                 :             :         inchi_free( szCoordNew );
    1384                 :             :     }
    1385                 :             :     if (at_new)
    1386                 :             :     {
    1387                 :             :         inchi_free( at_new );
    1388                 :             :     }
    1389                 :             :     */
    1390                 :             : 
    1391   [ #  #  #  # ]:           0 :     if (!*err && orig_at_data)
    1392                 :             :     {
    1393         [ #  # ]:           0 :         if (ReconcileAllCmlBondParities( orig_at_data->at,
    1394                 :             :             orig_at_data->num_inp_atoms, 0 ))
    1395                 :             :         {
    1396                 :           0 :             TREAT_ERR( *err, 0, "Cannot reconcile stereobond parities" );  /* <BRKPT> */
    1397         [ #  # ]:           0 :             if (!orig_at_data->num_dimensions)
    1398                 :             :             {
    1399                 :           0 :                 *err = 1;
    1400                 :             :             }
    1401                 :             :         }
    1402                 :             :     }
    1403                 :             : 
    1404         [ #  # ]:           0 :     if (*err)
    1405                 :             :     {
    1406                 :           0 :         FreeOrigAtData( orig_at_data );
    1407                 :             :     }
    1408                 :             : 
    1409   [ #  #  #  #  :           0 :     if (*err && !( 10 < *err && *err < 20 ) && pStrErr && !pStrErr[0])
          #  #  #  #  #  
                      # ]
    1410                 :             :     {
    1411                 :           0 :         TREAT_ERR( *err, 0, "Unknown error" );  /*   <BRKPT> */
    1412                 :             :     }
    1413                 :             : 
    1414         [ #  # ]:           0 :     return orig_at_data ? orig_at_data->num_inp_atoms : nNumAtoms;
    1415                 :             : }
    1416                 :             : 
    1417                 :             : 
    1418                 :             : /****************************************************************************
    1419                 :             : Returns 1 if bonds (a1,a2) and (b1,b2) are the same, -1 if atoms swapped,
    1420                 :             : 0 if not the same
    1421                 :             : ****************************************************************************/
    1422                 :           0 : int bIsSameBond(int a1, int a2, int b1, int b2)
    1423                 :             : {
    1424   [ #  #  #  # ]:           0 :     if (a1 == b1 && a2 == b2) return 1;
    1425   [ #  #  #  # ]:           0 :     if (a1 == b2 && a2 == b1) return -1;
    1426                 :           0 :     return 0;
    1427                 :             : }
    1428                 :             : 
    1429                 :             : 
    1430                 :             : /****************************************************************************
    1431                 :             : Parse InChI and get a list of crossing bonds in z layer
    1432                 :             : Return number of frame_shift_info triples or 0
    1433                 :             : ****************************************************************************/
    1434                 :           0 : static int GetFrameShiftInfoFrom105PlusInChI(char *sinchi,
    1435                 :             :     int *frame_shift_info,
    1436                 :             :     int max_crossing)
    1437                 :             : {
    1438                 :           0 :     int k, c = 0, j, aindex = 0, iunit = 0;
    1439                 :             :     const char *p, *q;
    1440                 :             : 
    1441                 :           0 :     p = strstr(sinchi, "/z");  /* must always be there */
    1442                 :             : 
    1443                 :             :                                /* each frame_shift_info triple(iunit, iunit_a1, iunit_a2) contains,
    1444                 :             :                                for each eligible frame-shiftable unit,
    1445                 :             :                                iunit - unit_no
    1446                 :             :                                iunit_a1, iunit_a2 - atom numbers for the senior bkbond
    1447                 :             :                                note that iunit_a1 is more senior then iunit_a2
    1448                 :             :                                */
    1449                 :             : 
    1450                 :             :                                /* eligible unit has Z-layer pattern
    1451                 :             :                                "range-of-numbers(number1,number2,nimbers...)"
    1452                 :             :                                >=2 bkbonds in CRU; relink may be necessary to shift frame or swap bkbond atoms?
    1453                 :             :                                OPTIONALLY DO NOT DO SWAP NOW?
    1454                 :             :                                senior bkbond and right atoms order is (number1,number2)
    1455                 :             :                                "range-of-numbers(number1.number2)"
    1456                 :             :                                1-bkbond CRU; relink may still be necessary to swap bkbond atoms so that
    1457                 :             :                                more senior atom is connected to lesser-numbered Zz
    1458                 :             :                                OPTIONALLY DO NOT DO SWAP NOW?
    1459                 :             :                                senior atoms order in bkbond is (number1,number2)
    1460                 :             :                                "range-of-numbers(number)"  1-atom CRU
    1461                 :             :                                relink is not applicable, skip it
    1462                 :             :                                */
    1463                 :             : 
    1464         [ #  # ]:           0 :     while (p)
    1465                 :             :     {
    1466                 :           0 :         int num[2] = { -1,-1 };
    1467                 :           0 :         p = strstr(p + 2, "(");
    1468         [ #  # ]:           0 :         if (!p)
    1469                 :             :         {
    1470                 :           0 :             break;
    1471                 :             :         }
    1472                 :           0 :         p++;
    1473                 :           0 :         q = p;
    1474                 :           0 :         j = 0;
    1475   [ #  #  #  # ]:           0 :         while ((k = (int)inchi_strtol(p, &q, 10)) && j < 2)
    1476                 :             :         {
    1477                 :           0 :             num[j] = k;
    1478                 :           0 :             j++;
    1479                 :           0 :             c = UCINT *q;
    1480   [ #  #  #  # ]:           0 :             if (j==1 && c == '-') /* do not consider pattern "(cap-end, cap-end)" */
    1481                 :             :             {
    1482                 :           0 :                 goto find_next_unit;
    1483                 :             :             }
    1484         [ #  # ]:           0 :             else if (c != ')')
    1485                 :             :             {
    1486                 :           0 :                 p = q + 1;
    1487                 :             :             }
    1488                 :             :             else
    1489                 :             :             {
    1490                 :           0 :                 goto find_next_unit;
    1491                 :             :             }
    1492                 :             :         }
    1493         [ #  # ]:           0 :         if (j < 2)
    1494                 :             :         {
    1495                 :           0 :             goto find_next_unit;
    1496                 :             :         }
    1497                 :           0 :         frame_shift_info[3 * aindex] = iunit;
    1498                 :           0 :         frame_shift_info[3 * aindex + 1] = num[0];
    1499                 :           0 :         frame_shift_info[3 * aindex + 2] = num[1];
    1500                 :           0 :         aindex++;
    1501         [ #  # ]:           0 :         if (aindex >= max_crossing)
    1502                 :             :         {
    1503                 :           0 :             break;
    1504                 :             :         }
    1505                 :             : 
    1506                 :           0 :     find_next_unit:
    1507                 :           0 :         p = strstr(p, ";");
    1508                 :           0 :         iunit++;
    1509                 :             :     }
    1510                 :             : 
    1511                 :           0 :     return aindex;
    1512                 :             : }
    1513                 :             : 
    1514                 :             : 
    1515                 :             : /****************************************************************************
    1516                 :             : Parse AuxInfostring and get a list of original atom numbers orig[cano_num]
    1517                 :             : ****************************************************************************/
    1518                 :           0 : int extract_orig_nums_from_auxinfo_string(char *saux, int *orig)
    1519                 :             : {
    1520                 :           0 :     int res = _IS_OKAY;
    1521                 :           0 :     int k, c = 0, cano_num = 1 /*0*/;
    1522                 :             :     const char *p, *q;
    1523                 :             : 
    1524                 :           0 :     p = strstr(saux, "/N:");  /* must always be there */
    1525   [ #  #  #  #  :           0 :     if (!p || !p[3] || !isdigit(UCINT p[3]))
                   #  # ]
    1526                 :             :     {
    1527                 :           0 :         res = _IS_ERROR;
    1528                 :           0 :         goto exit_function;
    1529                 :             :     }
    1530                 :             : 
    1531                 :           0 :     p += 3;
    1532                 :           0 :     q = p;
    1533                 :             : 
    1534         [ #  # ]:           0 :     while ((k = inchi_strtol(p, &q, 10))) /* djb-rwth: addressing LLVM warning */
    1535                 :             :     {
    1536                 :           0 :         orig[cano_num++] = k/* - 1*/; /* 1-based numbers */
    1537   [ #  #  #  # ]:           0 :         if ((c = UCINT *q) && c != '/') /* djb-rwth: addressing LLVM warning */
    1538                 :             :         {
    1539                 :           0 :             p = q + 1;
    1540                 :             :         }
    1541                 :             :         else
    1542                 :             :         {
    1543                 :             :             break;
    1544                 :             :         }
    1545                 :             :     }
    1546                 :             : 
    1547                 :           0 : exit_function:
    1548                 :             : 
    1549                 :           0 :     return res;
    1550                 :             : }
    1551                 :             : 
    1552                 :             : 
    1553                 :             : /****************************************************************************
    1554                 :             :  (currently, this function gets only the first list of E: )
    1555                 :             : ****************************************************************************/
    1556                 :           0 : int extract_nonstereo_eq_classes_from_auxinfo_string( char *saux,
    1557                 :             :                                                       int nat,
    1558                 :             :                                                       int *orig,
    1559                 :             :                                                       int *nclasses,
    1560                 :             :                                                       int *eclass,
    1561                 :             :                                                       int *eclass_by_origs)
    1562                 :             : {
    1563                 :           0 :     int res = _IS_OKAY;
    1564                 :           0 :     int k, c = 0, cano_num = 1, orig_num = 1;
    1565                 :             :     const char *p, *q;
    1566                 :             : 
    1567                 :             :     /* Note that all atom and class numbers here are 1-based */
    1568                 :             : 
    1569                 :           0 :     *nclasses = 0;
    1570                 :           0 :     memset(eclass, -1, ((long long)nat+1) * sizeof(int)); /* djb-rwth: cast operator added; memset_s C11/Annex K variant? */
    1571                 :           0 :     memset(eclass_by_origs, -1, ((long long)nat+1) * sizeof(int)); /* djb-rwth: cast operator added; memset_s C11/Annex K variant? */
    1572                 :             : 
    1573                 :           0 :     p = strstr(saux, "/E:");
    1574         [ #  # ]:           0 :     if (!p)
    1575                 :             :     {
    1576                 :             :         /* No "/E" means that all atoms are different  */
    1577                 :           0 :         return res;
    1578                 :             :     }
    1579                 :             : 
    1580                 :           0 :     p += 3;
    1581                 :           0 :     q = p;
    1582         [ #  # ]:           0 :     while ((k = (AT_NUMB)inchi_strtol(p + 1, &q, 10))) /* djb-rwth: addressing LLVM warning */
    1583                 :             :     {
    1584                 :           0 :         c = UCINT *q;
    1585         [ #  # ]:           0 :         if (c == '/')
    1586                 :             :         {
    1587                 :           0 :             break;
    1588                 :             :         }
    1589   [ #  #  #  # ]:           0 :         else if (c == ',' || c == ')')
    1590                 :             :         {
    1591                 :           0 :             eclass[k] = *nclasses;
    1592         [ #  # ]:           0 :             if (c == ')')
    1593                 :             :             {
    1594                 :           0 :                 (*nclasses)++;
    1595                 :           0 :                 q++;
    1596                 :           0 :                 c = UCINT *q;
    1597         [ #  # ]:           0 :                 if (c == '/')
    1598                 :           0 :                     break;
    1599                 :             :                 else
    1600                 :             :                     ;
    1601                 :             :             }
    1602                 :           0 :             p = q;
    1603                 :             :         }
    1604                 :             :         else
    1605                 :             :         {
    1606                 :           0 :             return _IS_ERROR;
    1607                 :             :         }
    1608                 :             :     }
    1609                 :             :     /* NB: cano, origs start from 0 */
    1610         [ #  # ]:           0 :     for (cano_num = 1; cano_num <= nat; cano_num++)
    1611                 :             :     {
    1612         [ #  # ]:           0 :         if (eclass[cano_num] == -1) /* the atom is unique, add one more eq class for him */
    1613                 :             :         {
    1614                 :           0 :             (*nclasses)++;
    1615                 :           0 :             eclass[cano_num] = *nclasses;
    1616                 :             :         }
    1617                 :             :     }
    1618                 :             : 
    1619         [ #  # ]:           0 :     for (cano_num = 1; cano_num <= nat; cano_num++)
    1620                 :             :     {
    1621                 :           0 :         orig_num = orig[cano_num];  /* NB: cano, origs start from 0 */
    1622                 :           0 :         eclass_by_origs[orig_num] = eclass[cano_num];
    1623                 :             :     }
    1624                 :             : 
    1625                 :           0 :     return res;
    1626                 :             : }
    1627                 :             : 
    1628                 :             : 
    1629                 :             : /****************************************************************************
    1630                 :             : Make a copy of the context of ProcessOneStructureEx or set a a new one
    1631                 :             : ****************************************************************************/
    1632                 :           1 : int  POSEContext_Init(POSEContext *context,
    1633                 :             :                       STRUCT_DATA *sd, INPUT_PARMS *ip, char *szTitle,
    1634                 :             :                       PINChI2 *pINChI2[INCHI_NUM], PINChI_Aux2 *pINChI_Aux2[INCHI_NUM],
    1635                 :             :                       INCHI_IOSTREAM *inp_file, INCHI_IOSTREAM *log_file,
    1636                 :             :                       INCHI_IOSTREAM *out_file, INCHI_IOSTREAM *prb_file,
    1637                 :             :                       ORIG_ATOM_DATA *orig_inp_data, ORIG_ATOM_DATA *prep_inp_data,
    1638                 :             :                       long num_inp, INCHI_IOS_STRING *strbuf, unsigned char save_opt_bits)
    1639                 :             : {
    1640                 :           1 :     char *sz = NULL;
    1641                 :           1 :     int ret = _IS_OKAY, res = 0, i;
    1642                 :             : 
    1643                 :           1 :     memset(context, 0, sizeof(*context)); /* djb-rwth: memset_s C11/Annex K variant? */
    1644                 :             : 
    1645         [ -  + ]:           1 :     if (!sd)
    1646                 :             :     {
    1647                 :           0 :         memset(&context->sd, 0, sizeof(context->sd)); /* djb-rwth: memset_s C11/Annex K variant? */
    1648                 :             :     }
    1649                 :             :     else
    1650                 :             :     {
    1651                 :           1 :         memcpy(&context->sd, sd, sizeof(context->sd));
    1652                 :             :     }
    1653                 :             : 
    1654         [ -  + ]:           1 :     if (!ip)
    1655                 :             :     {
    1656                 :           0 :         memset(&context->ip, 0, sizeof(context->ip)); /* djb-rwth: memset_s C11/Annex K variant? */
    1657                 :             :     }
    1658                 :             :     else
    1659                 :             :     {
    1660                 :           1 :         memcpy(&context->ip, ip, sizeof(context->ip));
    1661         [ +  + ]:           5 :         for (i = 0; i < MAX_NUM_PATHS; i++)
    1662                 :             :         {
    1663         [ -  + ]:           4 :             if (ip->path[i])
    1664                 :             :             {
    1665                 :           0 :                 sz = (char*)inchi_malloc((strlen(ip->path[i]) + 1) * sizeof(sz[0]));
    1666         [ #  # ]:           0 :                 if (!sz)
    1667                 :             :                 {
    1668                 :           0 :                     ret = _IS_ERROR;
    1669                 :           0 :                     goto exit_function;
    1670                 :             :                 }
    1671                 :           0 :                 strcpy(sz, context->ip.path[i]);
    1672                 :           0 :                 context->ip.path[i] = sz;
    1673                 :             :             }
    1674                 :             :         }
    1675                 :             :     }
    1676                 :             : 
    1677         [ +  - ]:           1 :     if (strlen(szTitle))
    1678                 :             :     {
    1679                 :           1 :         strcpy(context->szTitle, szTitle);
    1680                 :             :     }
    1681                 :             :     else
    1682                 :             :     {
    1683                 :           0 :         context->szTitle[0] = '\0';
    1684                 :             :     }
    1685                 :             : 
    1686                 :             :     /* pINChI2, pINChI_Aux2: We do not fill/allocate elements of these structures   */
    1687                 :             :     /* assuming that NULL's are there. If not just raise an error.                  */
    1688                 :             : 
    1689                 :           1 :     context->pINChI2[0] = context->pINChI2[1] = NULL;
    1690   [ +  -  +  -  :           1 :     if (pINChI2 && (pINChI2[0] || pINChI2[1])) /* djb-rwth: condition corrected */
                   -  + ]
    1691                 :             :     {
    1692                 :           0 :         ret = _IS_ERROR;
    1693                 :           0 :         goto exit_function;
    1694                 :             :     }
    1695                 :           1 :     context->pINChI_Aux2[0] = context->pINChI_Aux2[1] = NULL;
    1696   [ +  -  +  -  :           1 :     if (pINChI_Aux2 && (pINChI_Aux2[0] || pINChI_Aux2[1])) /* djb-rwth: condition corrected */
                   -  + ]
    1697                 :             :     {
    1698                 :           0 :         ret = _IS_ERROR;
    1699                 :           0 :         goto exit_function;
    1700                 :             :     }
    1701                 :             : 
    1702                 :           1 :     context->out_file = context->inchi_file;
    1703                 :           1 :     context->log_file = context->inchi_file + 1;
    1704                 :           1 :     context->prb_file = context->inchi_file + 2;
    1705                 :             :     /* Initialize internal for this function output streams as string buffers */
    1706                 :           1 :     inchi_ios_init(context->out_file, INCHI_IOS_TYPE_STRING, NULL);
    1707                 :           1 :     inchi_ios_init(context->log_file, INCHI_IOS_TYPE_STRING, NULL);
    1708                 :           1 :     inchi_ios_init(context->prb_file, INCHI_IOS_TYPE_STRING, NULL);
    1709                 :           1 :     context->inp_file = NULL;
    1710         [ +  - ]:           1 :     if (inp_file)
    1711                 :             :     {
    1712                 :           1 :         context->inp_file = inp_file;
    1713                 :             :     }
    1714                 :             : 
    1715                 :           1 :     context->orig_inp_data = &context->OrigAtData;
    1716                 :           1 :     context->prep_inp_data = context->PrepAtData;
    1717                 :             : 
    1718         [ +  - ]:           1 :     if (orig_inp_data)
    1719                 :             :     {
    1720                 :           1 :         memset(context->orig_inp_data, 0, sizeof(*context->orig_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */
    1721                 :           1 :         res = OrigAtData_Duplicate(context->orig_inp_data, orig_inp_data);
    1722         [ -  + ]:           1 :         if (res)
    1723                 :             :         {
    1724                 :           0 :             ret = _IS_ERROR;
    1725                 :           0 :             goto exit_function;
    1726                 :             :         }
    1727                 :             :     }
    1728                 :             : 
    1729         [ +  - ]:           1 :     if (prep_inp_data)
    1730                 :             :     {
    1731                 :           1 :         memset(context->prep_inp_data, 0, 2 * sizeof(*context->prep_inp_data)); /* djb-rwth: memset_s C11/Annex K variant? */
    1732                 :           1 :         res = OrigAtData_Duplicate(context->prep_inp_data, prep_inp_data);
    1733         [ -  + ]:           1 :         if (res)
    1734                 :             :         {
    1735                 :           0 :             ret = _IS_ERROR;
    1736                 :           0 :             goto exit_function;
    1737                 :             :         }
    1738                 :             :     }
    1739                 :             : 
    1740                 :             :     /* num_inp, strbuf, save_opt_bits */
    1741                 :           1 :     context->num_inp = num_inp;
    1742                 :           1 :     context->save_opt_bits = save_opt_bits;
    1743                 :           1 :     context->strbuf = &context->temp_string_container;
    1744         [ +  - ]:           1 :     if (strbuf)
    1745                 :             :     {
    1746                 :           1 :         res = inchi_strbuf_create_copy(context->strbuf, strbuf);
    1747                 :             :     }
    1748                 :             :     else
    1749                 :             :     {
    1750                 :           0 :         res = inchi_strbuf_init(context->strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT);
    1751                 :             :     }
    1752         [ +  - ]:           1 :     if (res == -1)
    1753                 :             :     {
    1754                 :           0 :         ret = _IS_FATAL;
    1755                 :           0 :         goto exit_function;
    1756                 :             :     }
    1757                 :             : 
    1758                 :           1 : exit_function:
    1759                 :             : 
    1760                 :           1 :     return ret;
    1761                 :             : }
    1762                 :             : 
    1763                 :             : 
    1764                 :             : /****************************************************************************/
    1765                 :           1 : void POSEContext_Free(POSEContext *context)
    1766                 :             : {
    1767                 :             :     int i;
    1768         [ +  + ]:           5 :     for (i = 0; i < MAX_NUM_PATHS; i++)
    1769                 :             :     {
    1770         [ -  + ]:           4 :         if (context->ip.path[i])
    1771                 :             :         {
    1772         [ #  # ]:           0 :             inchi_free((void*)context->ip.path[i]);
    1773                 :             :             /*  cast deliberately discards 'const' qualifier */
    1774                 :           0 :             context->ip.path[i] = NULL;
    1775                 :             :         }
    1776                 :             :     }
    1777                 :           1 :     FreeAllINChIArrays(context->pINChI2, context->pINChI_Aux2, context->sd.num_components);
    1778                 :           1 :     if (context->inp_file)
    1779                 :             :     {
    1780                 :             :         ;
    1781                 :             :     }
    1782                 :             :     else
    1783                 :             :     {
    1784                 :             :         ;
    1785                 :             :     }
    1786                 :           1 :     inchi_ios_close(context->out_file);
    1787                 :           1 :     inchi_ios_close(context->log_file);
    1788                 :           1 :     inchi_ios_close(context->prb_file);
    1789                 :           1 :     FreeOrigAtData(context->orig_inp_data);
    1790                 :           1 :     FreeOrigAtData(context->prep_inp_data);
    1791                 :           1 :     FreeOrigAtData( context->prep_inp_data+1);
    1792                 :           1 :     context->num_inp = 0;
    1793                 :           1 :     context->save_opt_bits = 0;
    1794                 :           1 :     inchi_strbuf_close(context->strbuf);
    1795                 :             : 
    1796                 :           1 :     return;
    1797                 :             : }
    1798                 :             : 
    1799                 :             : 
    1800                 :             : /****************************************************************************/
    1801                 :           0 : void POSEContext_DebugPrint(POSEContext *context)
    1802                 :             : {
    1803                 :             :     ITRACE_("\nDUMP OF POSEContext OBJECT");
    1804                 :             :     /* sd */
    1805                 :             :     ;
    1806                 :             :     /* ip */
    1807                 :             :     ;
    1808                 :             :     /* szTitle */
    1809                 :             :     ITRACE_("\n\tszTitle = %-s", context->szTitle);
    1810                 :             :     /* pINChI2, pINChI_Aux2 */
    1811                 :             :     /* inp_file, log_file, out_file, prb_file */
    1812                 :           0 :     if (context->inp_file)
    1813                 :             :     {
    1814                 :             :         ;
    1815                 :             :     }
    1816                 :             :     else
    1817                 :             :     {
    1818                 :             :         ;
    1819                 :             :     }
    1820                 :           0 :     if (context->log_file)
    1821                 :             :     {
    1822                 :             :         ;
    1823                 :             :     }
    1824                 :             :     else
    1825                 :             :     {
    1826                 :             :         ;
    1827                 :             :     }
    1828                 :           0 :     if (context->out_file)
    1829                 :             :     {
    1830                 :             :         ;
    1831                 :             :     }
    1832                 :             :     else
    1833                 :             :     {
    1834                 :             :         ;
    1835                 :             :     }
    1836                 :           0 :     if (context->prb_file)
    1837                 :             :     {
    1838                 :             :         ;
    1839                 :             :     }
    1840                 :             :     else
    1841                 :             :     {
    1842                 :             :         ;
    1843                 :             :     }
    1844                 :             :     /* orig_inp_data, prep_inp_data, */
    1845                 :             :     /* num_inp, strbuf, save_opt_bits */
    1846                 :             :     ITRACE_("\n\tnum_inp = %-ld, ", context->num_inp);
    1847                 :             :     ITRACE_("\n\tsave_opt_bits = 0x%x, ", context->save_opt_bits);
    1848                 :             :     ITRACE_("\n\tsave_opt_bits = 0x%x, ", context->save_opt_bits);
    1849                 :           0 :     if (context->strbuf->nUsedLength > 0)
    1850                 :             :     {
    1851                 :             :         ITRACE_("\n\tstrbuf = %-s", context->strbuf->pStr);
    1852                 :             :     }
    1853                 :             :     else
    1854                 :             :     {
    1855                 :             :         ITRACE_("\n\tstrbuf = <empty>", context->strbuf);
    1856                 :             :     }
    1857                 :             :     ITRACE_("\n");
    1858                 :             : 
    1859                 :           0 :     return;
    1860                 :             : }
    1861                 :             : 
    1862                 :             : 
    1863                 :             : /****************************************************************************/
    1864                 :         242 : int OAD_StructureEdits_Init(OAD_StructureEdits *ed)
    1865                 :             : {
    1866                 :         242 :     ed->del_side_chains = 0; /* by default, do not delete */
    1867                 :             : 
    1868                 :         242 :     ed->del_atom = (INT_ARRAY *)inchi_calloc(1, sizeof(INT_ARRAY));
    1869         [ -  + ]:         242 :     if (!ed->del_atom)                                               goto exitf;
    1870         [ -  + ]:         242 :     if (0 != IntArray_Alloc(ed->del_atom, 2))        goto exitf;
    1871                 :             : 
    1872                 :         242 :     ed->del_bond = (INT_ARRAY *)inchi_calloc(1, sizeof(INT_ARRAY));
    1873         [ -  + ]:         242 :     if (!ed->del_bond)                                               goto exitf;
    1874         [ -  + ]:         242 :     if (0 != IntArray_Alloc(ed->del_bond, 2))        goto exitf;
    1875                 :             : 
    1876                 :         242 :     ed->new_bond = (INT_ARRAY *)inchi_calloc(1, sizeof(INT_ARRAY));
    1877         [ -  + ]:         242 :     if (!ed->new_bond)                                               goto exitf;
    1878         [ -  + ]:         242 :     if (0 != IntArray_Alloc(ed->new_bond, 2))        goto exitf;
    1879                 :             : 
    1880                 :         242 :     ed->mod_bond = (INT_ARRAY *)inchi_calloc(1, sizeof(INT_ARRAY));
    1881         [ -  + ]:         242 :     if (!ed->mod_bond)                                               goto exitf;
    1882         [ -  + ]:         242 :     if (0 != IntArray_Alloc(ed->mod_bond, 12))       goto exitf;
    1883                 :             : 
    1884                 :         242 :     ed->mod_coord = (INT_ARRAY *)inchi_calloc(1, sizeof(INT_ARRAY));
    1885         [ -  + ]:         242 :     if (!ed->mod_coord)                                              goto exitf;
    1886         [ -  + ]:         242 :     if (0 != IntArray_Alloc(ed->mod_coord, 4))       goto exitf;
    1887                 :             : 
    1888                 :             : 
    1889                 :         242 :     return 0;
    1890                 :             : 
    1891                 :           0 : exitf:
    1892                 :           0 :     OAD_StructureEdits_Clear(ed);
    1893                 :           0 :     return _IS_ERROR;
    1894                 :             : }
    1895                 :             : 
    1896                 :             : 
    1897                 :             : /****************************************************************************/
    1898                 :         242 : void OAD_StructureEdits_Clear(OAD_StructureEdits *ed)
    1899                 :             : {
    1900         [ +  - ]:         242 :     if (ed->del_atom)
    1901                 :             :     {
    1902                 :         242 :         IntArray_Free(ed->del_atom);
    1903         [ +  - ]:         242 :         inchi_free(ed->del_atom);
    1904                 :         242 :         ed->del_atom = NULL;
    1905                 :             :     }
    1906         [ +  - ]:         242 :     if (ed->del_bond)
    1907                 :             :     {
    1908                 :         242 :         IntArray_Free(ed->del_bond);
    1909         [ +  - ]:         242 :         inchi_free(ed->del_bond);
    1910                 :         242 :         ed->del_bond = NULL;
    1911                 :             :     }
    1912         [ +  - ]:         242 :     if (ed->mod_bond)
    1913                 :             :     {
    1914                 :         242 :         IntArray_Free(ed->mod_bond);
    1915         [ +  - ]:         242 :         inchi_free(ed->mod_bond);
    1916                 :         242 :         ed->mod_bond = NULL;
    1917                 :             :     }
    1918         [ +  - ]:         242 :     if (ed->new_bond)
    1919                 :             :     {
    1920                 :         242 :         IntArray_Free(ed->new_bond);
    1921         [ +  - ]:         242 :         inchi_free(ed->new_bond);
    1922                 :         242 :         ed->new_bond = NULL;
    1923                 :             :     }
    1924         [ +  - ]:         242 :     if (ed->mod_coord)
    1925                 :             :     {
    1926                 :         242 :         IntArray_Free(ed->mod_coord);
    1927         [ +  - ]:         242 :         inchi_free(ed->mod_coord);
    1928                 :         242 :         ed->mod_coord = NULL;
    1929                 :             :     }
    1930                 :             : 
    1931                 :         242 :     return;
    1932                 :             : }
    1933                 :             : 
    1934                 :             : 
    1935                 :             : /****************************************************************************/
    1936                 :           0 : void OAD_StructureEdits_DebugPrint(OAD_StructureEdits *ed)
    1937                 :             : {
    1938                 :             :     ITRACE_("\n*****************************\nOAD_StructureEdits @ %-p\n*****************************", ed);
    1939                 :             :     ITRACE_("\nDel_side_chains :\t%-d\n", ed->del_side_chains);
    1940                 :             :     ITRACE_("Del_atom:\t%-s", ed->del_atom->used ? "" : "(empty)\n");
    1941                 :           0 :     IntArray_DebugPrint(ed->del_atom);
    1942                 :             :     ITRACE_("Del_bond:\t%-s", ed->del_bond->used ? "" : "(empty)\n");
    1943                 :           0 :     IntArray_DebugPrint(ed->del_bond);
    1944                 :             :     ITRACE_("New_bond:\t%-s", ed->new_bond->used ? "" : "(empty)\n");
    1945                 :           0 :     IntArray_DebugPrint(ed->new_bond);
    1946                 :             :     ITRACE_("Mod_bond:\t%-s", ed->mod_bond->used ? "" : "(empty)\n");
    1947                 :           0 :     IntArray_DebugPrint(ed->mod_bond);
    1948                 :             :     ITRACE_("Mod_coord:\t%-s", ed->mod_coord->used ? "" : "(empty)\n");
    1949                 :           0 :     IntArray_DebugPrint(ed->mod_coord);
    1950                 :             : 
    1951                 :           0 : }
    1952                 :             : 
    1953                 :             : 
    1954                 :             : /****************************************************************************
    1955                 :             :  Prepare CRU fold edits as suggested by the strings with preliminary
    1956                 :             :  generated interim (1.05+ flavoured) InChI and AuxInfo
    1957                 :             : ****************************************************************************/
    1958                 :             : /* djb-rwth: placed as global variables to avoid function buffer issues */
    1959                 :             : int ec_opp[MAX_ATOMS],          /* equivalence classes for atoms, in order of 1-based orig nums */
    1960                 :             : ec_cano_opp[MAX_ATOMS], /* equivalence classes for atoms, in order of 1-based cano nums */
    1961                 :             : at_stereo_mark_orig_opp[MAX_ATOMS],     /* stereo parities, in order of 1-based orig nums       */
    1962                 :             : xc_opp[MAX_ATOMS];      /* Extended (stereo-aware) atom classes.
    1963                 :             :                             There are 'n_ec' non-stereo atom equivalence classes
    1964                 :             :                             For ec[i]=k, keep value k for no-stereo atoms while use
    1965                 :             :                             (k + neclasses)   for '-' parity
    1966                 :             :                             (k + 2*neclasses) for '+' parity                            */
    1967                 :           0 : int  OAD_Polymer_PrepareFoldCRUEdits( ORIG_ATOM_DATA *orig_at_data,
    1968                 :             :                                       char *sinchi_noedits,
    1969                 :             :                                       char *saux_noedits,
    1970                 :             :                                       char *sinchi,
    1971                 :             :                                       char *saux,
    1972                 :             :                                       OAD_StructureEdits *ed)
    1973                 :             : {
    1974                 :           0 :     int ret = _IS_OKAY;
    1975                 :             :     int i, j, k;
    1976                 :             :     int err;
    1977                 :             :     char pStrErr[STR_ERR_LEN];
    1978                 :           0 :     int *orig = NULL;
    1979                 :           0 :     int nat = orig_at_data->num_inp_atoms;
    1980                 :           0 :     int neclasses = 0;          /* No of constitutional equivalence classses for the atoms              */
    1981                 :           0 :     int nxclasses = 0;      /* No of extended (stereo-aware) atom classses == 3*neclasses   */
    1982                 :             : 
    1983                 :           0 :     int *all_bkb_orig = NULL, n_all_bkb_orig = 0;
    1984                 :           0 :     OAD_Polymer *p = orig_at_data->polymer;
    1985                 :           0 :     int nu = orig_at_data->polymer->n;
    1986                 :             : 
    1987                 :             :     /* Extract cano_nums-->orig_nums mapping from AuxInfo AuxInfo Main Layer */
    1988                 :           0 :     orig = (int*)inchi_calloc((long long)nat + 1, sizeof(int)); /* djb-rwth: cast operator added */
    1989         [ #  # ]:           0 :     if (!orig)
    1990                 :             :     {
    1991                 :           0 :         ret = _IS_ERROR;
    1992                 :           0 :         goto exit_function;
    1993                 :             :     }
    1994                 :           0 :     ret = extract_orig_nums_from_auxinfo_string(saux, orig);
    1995   [ #  #  #  # ]:           0 :     if (ret != _IS_OKAY && ret != _IS_WARNING)
    1996                 :             :     {
    1997                 :           0 :         ret = _IS_ERROR;
    1998                 :           0 :         goto exit_function;
    1999                 :             :     }
    2000                 :             :     /* Extract non-stereo eq. classes data from AuxInfo */
    2001                 :           0 :     ret = extract_nonstereo_eq_classes_from_auxinfo_string(saux, nat, orig, &neclasses, ec_cano_opp, ec_opp);
    2002   [ #  #  #  # ]:           0 :     if (ret != _IS_OKAY && ret != _IS_WARNING)
    2003                 :             :     {
    2004                 :           0 :         ret = _IS_ERROR;
    2005                 :           0 :         goto exit_function;
    2006                 :             :     }
    2007         [ #  # ]:           0 :     if (neclasses == 0)
    2008                 :             :     {
    2009                 :           0 :         goto exit_function;
    2010                 :             :     }
    2011                 :             :     /* Extract stereocenter data from InChI */
    2012                 :             : 
    2013                 :             :     /*ret = extract_stereo_info_from_inchi_string(sinchi, nat, orig, at_stereo_mark_orig);*/
    2014                 :           0 :     ret = extract_stereo_info_from_inchi_string(sinchi_noedits, nat, orig, at_stereo_mark_orig_opp);
    2015   [ #  #  #  # ]:           0 :     if (ret != _IS_OKAY && ret != _IS_WARNING)
    2016                 :             :     {
    2017                 :           0 :         ret = _IS_ERROR;
    2018                 :           0 :         goto exit_function;
    2019                 :             :     }
    2020                 :             :     /* Make extended stereo-aware atom classes */
    2021                 :           0 :     nxclasses = neclasses * 3;
    2022         [ #  # ]:           0 :     for (i = 1; i <= nat; i++)  /* orig # */
    2023                 :             :     {
    2024                 :           0 :         int atom_class = ec_opp[i];
    2025                 :             : 
    2026         [ #  # ]:           0 :         if (at_stereo_mark_orig_opp[i] == INCHI_PARITY_ODD)
    2027                 :             :         {
    2028                 :           0 :             atom_class += neclasses;
    2029                 :             :         }
    2030         [ #  # ]:           0 :         else if (at_stereo_mark_orig_opp[i] == INCHI_PARITY_EVEN)
    2031                 :             :         {
    2032                 :           0 :             atom_class += 2 * neclasses;
    2033                 :             :         }
    2034                 :           0 :         xc_opp[i] = atom_class;
    2035                 :             :     }
    2036                 :             :     /* Extract all backbone bonds, in all units, from InChI (z layer).
    2037                 :             :         NB: we assume that units are not 'inter-crossing' so
    2038                 :             :         any particular bkbond belongs to some unique CRU.
    2039                 :             :     */
    2040                 :           0 :     all_bkb_orig = (int*)inchi_calloc(2 * ((long long)orig_at_data->num_inp_bonds + 1), sizeof(int)); /* djb-rwth: cast operator added */
    2041         [ #  # ]:           0 :     if (!all_bkb_orig)
    2042                 :             :     {
    2043                 :           0 :         ret = _IS_ERROR;
    2044                 :           0 :         goto exit_function;
    2045                 :             :     }
    2046                 :           0 :     memset(all_bkb_orig, 0, ((long long)orig_at_data->num_inp_bonds + 1) * sizeof(int)); /* djb-rwth: cast operator added; memset_s C11/Annex K variant? */
    2047                 :           0 :     ret = extract_all_backbone_bonds_from_inchi_string(sinchi, &n_all_bkb_orig, orig, all_bkb_orig);
    2048   [ #  #  #  # ]:           0 :     if (ret != _IS_OKAY && ret != _IS_WARNING)
    2049                 :             :     {
    2050                 :           0 :         ret = _IS_ERROR;
    2051                 :           0 :         goto exit_function;
    2052                 :             :     }
    2053                 :             :     /* just for case, remove those bkbonds which are not single (alternate may be here) */
    2054         [ #  # ]:           0 :     for (k = n_all_bkb_orig - 1; k >= 0; k--)
    2055                 :             :     {
    2056                 :           0 :         int orig1 = all_bkb_orig[2 * k];
    2057                 :           0 :         int orig2 = all_bkb_orig[2 * k + 1];
    2058                 :           0 :         int bond_type = Inp_Atom_GetBondType(orig_at_data->at, orig1 - 1, orig2 - 1);
    2059         [ #  # ]:           0 :         if (bond_type > BOND_TYPE_SINGLE) /* not == intentionally, to keep -1 ("no bond") */
    2060                 :             :         {
    2061                 :             :             /* remove k-th bond and shift others to start of list */
    2062                 :             :             int kk;
    2063         [ #  # ]:           0 :             for (kk = k; kk < n_all_bkb_orig; kk++)
    2064                 :             :             {
    2065                 :           0 :                 all_bkb_orig[2 * kk] = all_bkb_orig[2 * (kk + 1)];
    2066                 :           0 :                 all_bkb_orig[2 * kk + 1] = all_bkb_orig[2 * (kk + 1) + 1];
    2067                 :             :             }
    2068                 :           0 :             all_bkb_orig[2 * n_all_bkb_orig] = 0;
    2069                 :           0 :             all_bkb_orig[2 * n_all_bkb_orig + 1] = 0;
    2070                 :           0 :             n_all_bkb_orig--;
    2071                 :             :         }
    2072                 :             :     }
    2073                 :             : 
    2074                 :           0 :     err = OAD_ValidatePolymerAndPseudoElementData(orig_at_data,
    2075                 :             :         POLYMERS_MODERN,
    2076                 :             :         1, /* ip->bNPZz,*/
    2077                 :             :         pStrErr,
    2078                 :             :         0 /*ip->bNoWarnings*/);
    2079         [ #  # ]:           0 :     if (err)
    2080                 :             :     {
    2081                 :           0 :         goto exit_function;
    2082                 :             :     }
    2083                 :             : 
    2084                 :             :     /* For each unit analyze a possibility of folding (i.e., removal of excess in-CRU repeats) */
    2085         [ #  # ]:           0 :     for (j = 0; j < nu; j++)
    2086                 :             :     {
    2087                 :           0 :         OAD_PolymerUnit* u = p->units[j];
    2088                 :             : 
    2089         [ #  # ]:           0 :         if (u->na < 2)
    2090                 :             :         {
    2091                 :           0 :             goto nextj;
    2092                 :             :         }
    2093         [ #  # ]:           0 :         if (u->nb < 2)
    2094                 :             :         {
    2095                 :           0 :             goto nextj;
    2096                 :             :         }
    2097                 :             :         /* this is only for bi-star CRU's */
    2098         [ #  # ]:           0 :         if (!u->cap1_is_undef)
    2099                 :             :         {
    2100                 :           0 :             goto nextj;
    2101                 :             :         }
    2102         [ #  # ]:           0 :         if (!u->cap2_is_undef)
    2103                 :             :         {
    2104                 :           0 :             goto nextj;
    2105                 :             :         }
    2106                 :             : 
    2107                 :           0 :         err = analyze_CRU_folding(orig_at_data, j,
    2108                 :             :             n_all_bkb_orig, all_bkb_orig,
    2109                 :             :             nxclasses, xc_opp,
    2110                 :             :             ed);
    2111         [ #  # ]:           0 :         if (err)
    2112                 :             :         {
    2113                 :           0 :             ret = inchi_max(_IS_WARNING, err);
    2114                 :           0 :             goto nextj;
    2115                 :             :         }
    2116                 :             : 
    2117                 :           0 :     nextj:;
    2118                 :             :     }
    2119                 :             : 
    2120                 :           0 : exit_function:
    2121         [ #  # ]:           0 :     if (orig)
    2122                 :             :     {
    2123         [ #  # ]:           0 :         inchi_free(orig);
    2124                 :             :     }
    2125         [ #  # ]:           0 :     if (all_bkb_orig)
    2126                 :             :     {
    2127         [ #  # ]:           0 :         inchi_free(all_bkb_orig);
    2128                 :             :     }
    2129                 :             : 
    2130                 :           0 :     return ret;
    2131                 :             : }
    2132                 :             : 
    2133                 :             : 
    2134                 :             : 
    2135                 :             : /***************************************************************************/
    2136                 :           0 : DiylFrag* DiylFrag_New(int na, int end1, int end2, char *s)
    2137                 :             : {
    2138                 :           0 :     int err = 0;
    2139                 :             : 
    2140                 :           0 :     DiylFrag *pfrag = NULL;
    2141                 :             : 
    2142                 :           0 :     pfrag = (DiylFrag *)inchi_calloc(1, sizeof(DiylFrag));
    2143         [ #  # ]:           0 :     if (NULL == pfrag)
    2144                 :             :     {
    2145                 :           0 :         err = 1;
    2146                 :           0 :         goto exit_function;
    2147                 :             :     }
    2148                 :             : 
    2149                 :           0 :     pfrag->na = na;
    2150                 :           0 :     pfrag->end1 = end1;
    2151                 :           0 :     pfrag->end2 = end2;
    2152                 :           0 :     pfrag->alist = NULL;
    2153                 :           0 :     pfrag->xclist = NULL;
    2154                 :             : 
    2155         [ #  # ]:           0 :     if (na > 0 )
    2156                 :             :     {
    2157                 :           0 :         pfrag->alist = (int *)inchi_calloc(na, sizeof(int));
    2158                 :           0 :         pfrag->xclist = (int *)inchi_calloc(na, sizeof(int));
    2159   [ #  #  #  # ]:           0 :         if (!pfrag->alist || !pfrag->xclist)
    2160                 :             :         {
    2161                 :           0 :             err = 2;
    2162                 :           0 :             goto exit_function;
    2163                 :             :         }
    2164                 :             :     }
    2165                 :             : 
    2166                 :           0 :     inchi_strbuf_printf(&pfrag->sig, "%-s", s);
    2167                 :             : 
    2168                 :           0 : exit_function:
    2169         [ #  # ]:           0 :     if (err)
    2170                 :             :     {
    2171                 :           0 :         DiylFrag_Free(pfrag);
    2172         [ #  # ]:           0 :         inchi_free(pfrag); /* djb-rwth: addressing coverity ID #499507 */
    2173                 :           0 :         return NULL;
    2174                 :             :     }
    2175                 :           0 :     return pfrag;
    2176                 :             : }
    2177                 :             : /***************************************************************************/
    2178                 :           0 : void DiylFrag_Free(DiylFrag *pfrag)
    2179                 :             : {
    2180         [ #  # ]:           0 :     if (!pfrag)
    2181                 :             :     {
    2182                 :           0 :         return;
    2183                 :             :     }
    2184         [ #  # ]:           0 :     if (pfrag->alist)
    2185                 :             :     {
    2186         [ #  # ]:           0 :         inchi_free(pfrag->alist);
    2187                 :           0 :         pfrag->alist = NULL;
    2188                 :             :     }
    2189         [ #  # ]:           0 :     if (pfrag->xclist)
    2190                 :             :     {
    2191         [ #  # ]:           0 :         inchi_free(pfrag->xclist);
    2192                 :           0 :         pfrag->xclist = NULL;
    2193                 :             :     }
    2194                 :           0 :     inchi_strbuf_close(&pfrag->sig);
    2195                 :           0 :     return;
    2196                 :             : }
    2197                 :             : /***************************************************************************/
    2198                 :           0 : void DiylFrag_MakeSignature(DiylFrag *pfrag,
    2199                 :             :                             int nxc,            /* n xclasses (molecule-wide)       */
    2200                 :             :                             int *xc,            /* xclasses (molecule-wide)         */
    2201                 :             :                             int *cnt )          /* temp storage: counts of xclasses */
    2202                 :             : {
    2203                 :             :     int i, k, nxc_frag; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    2204                 :             : 
    2205                 :           0 :     inchi_strbuf_printf(&pfrag->sig, "%-d,%-d,%-d{", pfrag->na, xc[pfrag->end1], xc[pfrag->end2]);
    2206         [ #  # ]:           0 :     for (i = 0; i < pfrag->na; i++)
    2207                 :             :     {
    2208                 :           0 :         pfrag->xclist[i] = xc[pfrag->alist[i]];
    2209                 :             :     }
    2210                 :           0 :     nxc_frag = count_colors_in_sequence(pfrag->xclist, pfrag->na, nxc+1, cnt); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    2211         [ #  # ]:           0 :     for (k = 0; k < nxc; k++)
    2212                 :             :     {
    2213         [ #  # ]:           0 :         if (cnt[k] > 0)
    2214                 :             :         {
    2215                 :             :             /* (xclass:cnt)*/
    2216                 :           0 :             inchi_strbuf_printf(&pfrag->sig, "(%-d:%-d)", k, cnt[k]);
    2217                 :             :         }
    2218                 :             :     }
    2219                 :             : 
    2220                 :           0 :     inchi_strbuf_printf(&pfrag->sig, "}");
    2221                 :             : 
    2222                 :           0 :     return;
    2223                 :             : }
    2224                 :             : /***************************************************************************
    2225                 :             :  Compare two fragments and return 1 if they are different, 0 if equal
    2226                 :             : ***************************************************************************/
    2227                 :           0 : int DiylFrag_Diff(DiylFrag *pfrag1, DiylFrag *pfrag2)
    2228                 :             : {
    2229         [ #  # ]:           0 :     if (pfrag1->na != pfrag2->na)
    2230                 :             :     {
    2231                 :           0 :         return 1;
    2232                 :             :     }
    2233         [ #  # ]:           0 :     if (pfrag1->nb != pfrag2->nb)
    2234                 :             :     {
    2235                 :           0 :         return 1;
    2236                 :             :     }
    2237   [ #  #  #  # ]:           0 :     if (pfrag1->sig.nUsedLength && pfrag2->sig.nUsedLength)
    2238                 :             :     {
    2239                 :           0 :         int cmp = strcmp(pfrag1->sig.pStr, pfrag2->sig.pStr);
    2240                 :           0 :         return cmp;
    2241                 :             :     }
    2242                 :             : 
    2243                 :           0 :     return 0;
    2244                 :             : }
    2245                 :             : /****************************************************************************
    2246                 :             : Debug print polymer data for a given SRU
    2247                 :             : ****************************************************************************/
    2248                 :           0 : void DiylFrag_DebugTrace(DiylFrag *pfrag)
    2249                 :             : {
    2250                 :             :     int k, na;
    2251                 :             : 
    2252         [ #  # ]:           0 :     if (!pfrag)
    2253                 :             :     {
    2254                 :           0 :         return;
    2255                 :             :     }
    2256                 :             : 
    2257                 :             :     ITRACE_("DiylFrag @ %-p ", pfrag);
    2258                 :           0 :     na = pfrag->na;
    2259                 :             :     ITRACE_("\n\t%-d atoms. List of atoms and their xclasses : { ", na);
    2260         [ #  # ]:           0 :     for (k = 0; k < na - 1; k++)
    2261                 :             :     {
    2262                 :             :         ITRACE_(" %-d(%-d), ", pfrag->alist[k], pfrag->xclist[k]);
    2263                 :             :     }
    2264                 :             :     ITRACE_(" %-d(%-d) }\n", pfrag->alist[na - 1], pfrag->xclist[na - 1]);
    2265                 :             : 
    2266                 :             :     ITRACE_("\tend1 = %-d, end2 = %-d, nb = %-d\n", pfrag->end1, pfrag->end2, pfrag->nb);
    2267                 :             : 
    2268                 :             :     ITRACE_("\tSignature = '%-s'\n", pfrag->sig.pStr);
    2269                 :             : 
    2270                 :           0 :     return;
    2271                 :             : }
    2272                 :             : 
    2273                 :             : 
    2274                 :             : /***************************************************************************/
    2275                 :           0 : int analyze_CRU_folding(ORIG_ATOM_DATA *orig_at_data,
    2276                 :             :                         int iunit,
    2277                 :             :                         int n_all_bkb,
    2278                 :             :                         int *all_bkb,
    2279                 :             :                         int nxclasses,
    2280                 :             :                         int *xc,
    2281                 :             :                         OAD_StructureEdits *ed)
    2282                 :             : {
    2283                 :           0 :     int ret = _IS_OKAY;
    2284                 :             :     int err, i, j, k, m, fail, a1, a2;
    2285                 :           0 :     int n_cuts = 0, n_frags = 0;
    2286                 :           0 :     int n_frags_in_repeating_subunit = 0;
    2287                 :           0 :     int n_fold, n_frag_classes = 0;
    2288                 :           0 :     int subunit_last_atom, next_subunit_first_atom = 0;
    2289                 :           0 :     int *cut = NULL;        /* [ bkbond1at1, bkbond1at2,  bkbond2at1,bkbond2at2, ... ]
    2290                 :             :                                these are (atoms of) backbone bonds which are non-cyclic and non-multiple ('breakable')      */
    2291                 :           0 :     DiylFrag **frag=NULL;   /* frag is divalent fragment surrounded by 'cut' bonds, so it may be a repeating CRU sub-unit   */
    2292                 :           0 :     int *frag_class=NULL;   /* fragments are classified, by their signatures, to produce unique labelling;
    2293                 :             :                             if the two fragments have the same class, they have the same signature and whence are equivalent */
    2294                 :           0 :     int *frag_xc_counts = NULL; /* counts of xclass atoms in CRU, order of class numbers    */
    2295                 :             :     char pStrErr[STR_ERR_LEN];
    2296                 :             : 
    2297                 :           0 :     OAD_PolymerUnit *u = orig_at_data->polymer->units[iunit];
    2298                 :             :     ITRACE_("\n\n%-s\t\t%-s:%-d", "analyze_CRU_folding()", __FILE__,__LINE__);
    2299                 :             : 
    2300                 :           0 :     pStrErr[0] = '\0'; /* djb-rwth: fixing coverity ID #499611; pStrErr is a dummy parameter in this function and is never used */
    2301                 :             : 
    2302                 :             :     /* Reserve space for frag-specific xclass counts */
    2303                 :           0 :     frag_xc_counts = (int *)inchi_calloc((long long)nxclasses + 1, sizeof(int)); /* djb-rwth: cast operator added */
    2304         [ #  # ]:           0 :     if (!frag_xc_counts)
    2305                 :             :     {
    2306                 :           0 :         ret = _IS_ERROR;
    2307                 :           0 :         goto exit_function;
    2308                 :             :     }
    2309                 :             : 
    2310                 :             : 
    2311                 :             :     /* Prepare list of cuts - backbone lying on the way from cap1 to cap2 */
    2312                 :           0 :     cut = (int *)inchi_calloc(2 * (long long)n_all_bkb, sizeof(int)); /* djb-rwth: cast operator added */
    2313         [ #  # ]:           0 :     if (!cut)
    2314                 :             :     {
    2315                 :           0 :         ret = _IS_ERROR;
    2316                 :           0 :         goto exit_function;
    2317                 :             :     }
    2318                 :             : 
    2319                 :           0 :     OAD_PolymerUnit_DebugTrace(u);
    2320                 :           0 :     OAD_CollectBackboneBonds(orig_at_data,
    2321                 :             :                             u->na, u->alist,
    2322                 :             :                             u->end_atom1, u->end_atom2,
    2323                 :             :                             &(u->nbkbonds), u->bkbonds,
    2324                 :             :                             &err, pStrErr);
    2325         [ #  # ]:           0 :     if (err)
    2326                 :             :     {
    2327                 :           0 :         ret = _IS_ERROR;
    2328                 :           0 :         goto exit_function;
    2329                 :             :     }
    2330                 :           0 :     OAD_PolymerUnit_DebugTrace(u);
    2331         [ #  # ]:           0 :     if (u->nbkbonds < 1)
    2332                 :             :     {
    2333                 :           0 :         goto exit_function;
    2334                 :             :     }
    2335                 :             : 
    2336                 :             :     /* Make 'cut' list from the bonds which are both in all_bkb and u->bkb
    2337                 :             :        (all_bkb eliminates bonds with order >1 and cyclic ones,
    2338                 :             :        but may contain artificial cyclizing bond)
    2339                 :             :     */
    2340         [ #  # ]:           0 :     for (i = 0; i <u->nbkbonds; i++)
    2341                 :             :     {
    2342                 :           0 :         a1 = u->bkbonds[i][0];
    2343                 :           0 :         a2 = u->bkbonds[i][1];
    2344         [ #  # ]:           0 :         for (j = 0; j < n_all_bkb; j++)
    2345                 :             :         {
    2346         [ #  # ]:           0 :             if (bIsSameBond(a1, a2, all_bkb[2 * j], all_bkb[2 * j + 1]))
    2347                 :             :             {
    2348                 :           0 :                 cut[2 * n_cuts] = a1; /* djb-rwth: buffer overrun implicitly avoided in loop condition */
    2349                 :           0 :                 cut[2 * n_cuts + 1] = a2;
    2350                 :           0 :                 n_cuts++;
    2351                 :           0 :                 break;
    2352                 :             :             }
    2353                 :             :         }
    2354                 :             :     }
    2355         [ #  # ]:           0 :     if (n_cuts < 1)
    2356                 :             :     {
    2357                 :             :         /* no valid sub-units is available */
    2358                 :           0 :         goto exit_function;
    2359                 :             :     }
    2360                 :             : 
    2361                 :             :     /* Collect fragments */
    2362                 :           0 :     n_frags = n_cuts + 1;
    2363                 :           0 :     frag = (DiylFrag**) inchi_calloc(n_frags, sizeof(DiylFrag *));
    2364         [ #  # ]:           0 :     if (!frag)
    2365                 :             :     {
    2366                 :           0 :         ret = _IS_ERROR;
    2367                 :           0 :         goto exit_function;
    2368                 :             :     }
    2369                 :           0 :     frag_class = (int *) inchi_calloc(n_frags, sizeof(int));
    2370         [ #  # ]:           0 :     if (!frag_class)
    2371                 :             :     {
    2372                 :           0 :         ret = _IS_ERROR;
    2373                 :           0 :         goto exit_function;
    2374                 :             :     }
    2375                 :           0 :     n_frag_classes = 0;
    2376         [ #  # ]:           0 :     for (i = 0; i < n_frags; i++)
    2377                 :             :     {
    2378                 :             :         /* Create fragment */
    2379                 :           0 :         int forbidden[4], novel=1;
    2380                 :           0 :         DiylFrag *pfrag = NULL;
    2381                 :             : 
    2382                 :             :         /* Calculate and store signature of the fragment */
    2383                 :             :         /*
    2384                 :             :             end_atom1...cut[i-1])---frag[i]---cut[i]---...end_atom2
    2385                 :             :         */
    2386         [ #  # ]:           0 :         if (i == 0)
    2387                 :             :         {
    2388                 :           0 :             a1 = u->end_atom1;
    2389                 :           0 :             forbidden[0] = u->cap1;
    2390                 :             :         }
    2391                 :             :         else
    2392                 :             :         {
    2393                 :           0 :             a1 = cut[2 * (i-1) + 1];            /* near end of prev cut */
    2394                 :           0 :             forbidden[0] = cut[2 * (i - 1) ];   /* far  end of prev cut */
    2395                 :             :         }
    2396                 :           0 :         forbidden[1] = a1;
    2397         [ #  # ]:           0 :         if (i==n_frags-1)
    2398                 :             :         {
    2399                 :           0 :             a2 = u->end_atom2;
    2400                 :           0 :             forbidden[2] = u->cap2;
    2401                 :             :         }
    2402                 :             :         else
    2403                 :             :         {
    2404                 :           0 :             a2 = cut[2 * i];                    /* near end of next cut */
    2405                 :           0 :             forbidden[2] = cut[2 * i + 1];      /* far  end of next cut */
    2406                 :             :         }
    2407                 :           0 :         forbidden[3] = a2;
    2408                 :             : 
    2409                 :           0 :         pfrag = DiylFrag_New(u->na, a1, a2, "");
    2410         [ #  # ]:           0 :         if (!pfrag)
    2411                 :             :         {
    2412                 :           0 :             ret = _IS_ERROR;
    2413                 :           0 :             goto exit_function;
    2414                 :             :         }
    2415                 :           0 :         frag[i] = pfrag;
    2416                 :             : 
    2417                 :           0 :         ret = OAD_CollectReachableAtoms(orig_at_data, a1, 2, forbidden,
    2418                 :             :                                   &pfrag->na, pfrag->alist, &err, pStrErr);
    2419         [ #  # ]:           0 :         if (ret==_IS_ERROR)
    2420                 :             :         {
    2421                 :           0 :             goto exit_function;
    2422                 :             :         }
    2423                 :             : 
    2424                 :           0 :         DiylFrag_MakeSignature(pfrag, nxclasses, xc, frag_xc_counts);
    2425                 :             : 
    2426                 :           0 :         novel = 1;
    2427         [ #  # ]:           0 :         for (j = 0; j < i; j++)
    2428                 :             :         {
    2429         [ #  # ]:           0 :             if ( !DiylFrag_Diff(frag[i], frag[j]) )
    2430                 :             :             {
    2431                 :           0 :                 frag_class[i] = frag_class[j];
    2432                 :           0 :                 novel = 0;
    2433                 :           0 :                 break;
    2434                 :             :             }
    2435                 :             :         }
    2436         [ #  # ]:           0 :         if (novel)
    2437                 :             :         {
    2438                 :           0 :             frag_class[i] = n_frag_classes++;
    2439                 :             :         }
    2440                 :             : 
    2441                 :             :         ITRACE_("\nCANDIDATE CRU SUBUNIT %-d/%-d (CLASS #%-d)\t", i+1, n_frags, frag_class[i]);
    2442                 :           0 :         DiylFrag_DebugTrace(pfrag);
    2443                 :             :     }
    2444                 :             : 
    2445         [ #  # ]:           0 :     if (n_frag_classes == n_frags)
    2446                 :             :     {
    2447                 :             :         /* All classes are distinct ==> no repeats, folding is impossible, skip the CRU */
    2448                 :           0 :         goto exit_function;
    2449                 :             :     }
    2450                 :             : 
    2451                 :           0 :     n_frags_in_repeating_subunit = len_repeating_subsequence(frag_class, NULL, n_frags);
    2452         [ #  # ]:           0 :     if (0 == n_frags_in_repeating_subunit)
    2453                 :             :     {
    2454                 :             :         /* valid repeating pattern not found */
    2455                 :           0 :         goto exit_function;
    2456                 :             :     }
    2457                 :           0 :     n_fold = n_frags / n_frags_in_repeating_subunit;
    2458   [ #  #  #  # ]:           0 :     if (1==n_fold || (0!=n_frags%n_frags_in_repeating_subunit) )
    2459                 :             :     {
    2460                 :             :         /* valid repeating pattern not found */
    2461                 :           0 :         goto exit_function;
    2462                 :             :     }
    2463                 :             :     ITRACE_("\n");
    2464                 :             : 
    2465                 :             :     /* {1...2}---{5...6}---{8...9} */
    2466                 :             : 
    2467                 :             :     ITRACE_("\n* Found %-d times foldable unit of %-d fragments\n* First repeating sub-unit formed by %-d-fragment backbone : ",
    2468                 :             :             n_fold, n_frags, n_frags_in_repeating_subunit);
    2469                 :             : 
    2470   [ #  #  #  #  :           0 :     for (k = 0; k < n_frags_in_repeating_subunit && n_frags_in_repeating_subunit < n_frags && frag[k]; k++) /* djb-rwth: fixing a NULL pointer dereference and buffer overflow */
                   #  # ]
    2471                 :             :     {
    2472                 :             :         if (frag[k]->end1 == frag[k]->end2)
    2473                 :             :         {
    2474                 :             :             ITRACE_("-{%-d}-", frag[k]->end1, frag[k]->end2);
    2475                 :             :         }
    2476                 :             :         else
    2477                 :             :         {
    2478                 :             :             ITRACE_("-{%-d...%-d}-", frag[k]->end1, frag[k]->end2);
    2479                 :             :         }
    2480                 :             :     }
    2481                 :             : 
    2482                 :             :     ITRACE_("\n");
    2483                 :             :     ITRACE_("* Backbone pattern for %-d fragments that may be removed :  ", n_frags - n_frags_in_repeating_subunit);
    2484         [ #  # ]:           0 :     for (k = n_frags_in_repeating_subunit; k < n_frags; k++)
    2485                 :             :     {
    2486                 :             :         if (frag[k]->end1 == frag[k]->end2)
    2487                 :             :         {
    2488                 :             :             ITRACE_("-{%-d}-", frag[k]->end1, frag[k]->end2);
    2489                 :             :         }
    2490                 :             :         else
    2491                 :             :         {
    2492                 :             :             ITRACE_("-{%-d...%-d}-", frag[k]->end1, frag[k]->end2);
    2493                 :             :         }
    2494                 :             :     }
    2495                 :             :     ITRACE_("\n");
    2496                 :             : 
    2497                 :             :     /* Folding is possible, prepare the edits
    2498                 :             :         Keep the least in-CRU repeating subunit
    2499                 :             :             { frag[0] ... frag[n_frags_in_repeating_subunit-1] }
    2500                 :             :         and remove
    2501                 :             :             { frag[n_frags_in_repeating_subunit]...frag[n_frags-1] } and all side chain attached to that
    2502                 :             : 
    2503                 :             :         NB: which bond is modified and which is broke is important for applying these edits further!
    2504                 :             :     */
    2505                 :             : 
    2506                 :             :     /* Break bond from the subunit to the next fragment and replace an original
    2507                 :             :        bond to "right" cap with bond from the subunit "right" atom
    2508                 :             :     */
    2509                 :             : 
    2510                 :             :     /*djb-rwth: the whole block had to be rewritten to fix NULL pointer dereference */
    2511   [ #  #  #  #  :           0 :     if (n_frags_in_repeating_subunit < n_frags && frag[n_frags_in_repeating_subunit] && frag[n_frags_in_repeating_subunit - 1]) /* djb-rwth: fixing a NULL pointer dereference and buffer overflow */
                   #  # ]
    2512                 :             :     {
    2513                 :           0 :         subunit_last_atom        = frag[n_frags_in_repeating_subunit - 1]->end2;
    2514                 :           0 :         next_subunit_first_atom  = frag[n_frags_in_repeating_subunit]->end1;
    2515                 :             : 
    2516                 :           0 :         fail = 0;
    2517                 :           0 :         fail += IntArray_Append(ed->del_bond, subunit_last_atom);
    2518                 :           0 :         fail += IntArray_Append(ed->del_bond, next_subunit_first_atom);
    2519                 :             : 
    2520                 :           0 :         fail += IntArray_Append(ed->mod_bond, u->end_atom2);
    2521                 :           0 :         fail += IntArray_Append(ed->mod_bond, u->cap2);
    2522                 :           0 :         fail += IntArray_Append(ed->mod_bond, subunit_last_atom);
    2523                 :           0 :         fail += IntArray_Append(ed->mod_bond, u->cap2);
    2524                 :             : 
    2525         [ #  # ]:           0 :         if (fail)
    2526                 :             :         {
    2527                 :           0 :             ret = _IS_ERROR;
    2528                 :           0 :             goto exit_function;
    2529                 :             :         }
    2530                 :             :     }
    2531                 :             : 
    2532                 :             :     /*  Now collect all backbone atoms to be deleted (we will then delete the
    2533                 :             :     associated side chains also, but no need to reveal them at the moment)      */
    2534                 :             : 
    2535         [ #  # ]:           0 :     for (k = n_frags_in_repeating_subunit; k < n_frags; k++)
    2536                 :             :     {
    2537         [ #  # ]:           0 :         if (frag[k]) /* djb-rwth: fixing a NULL pointer dereference */
    2538                 :             :         {
    2539         [ #  # ]:           0 :             for (m = 0; m < frag[k]->na; m++)
    2540                 :             :             {
    2541                 :           0 :                 fail = IntArray_AppendIfAbsent(ed->del_atom, frag[k]->alist[m]);
    2542         [ #  # ]:           0 :                 if (fail)
    2543                 :             :                 {
    2544                 :           0 :                     ret = _IS_ERROR;
    2545                 :           0 :                     goto exit_function;
    2546                 :             :                 }
    2547                 :             :             }
    2548                 :             :         }
    2549                 :             :     }
    2550                 :             :     /* Care on atom coordinates: as bond to cap2 changes,
    2551                 :             :        we use coordinates of next_subunit_first_atom for cap2
    2552                 :             :     */
    2553                 :           0 :     fail = 0;
    2554                 :           0 :     fail += IntArray_Append(ed->mod_coord, next_subunit_first_atom);
    2555                 :           0 :     fail += IntArray_Append(ed->mod_coord, u->cap2);
    2556         [ #  # ]:           0 :     if (fail)
    2557                 :             :     {
    2558                 :           0 :         ret = _IS_ERROR;
    2559                 :           0 :         goto exit_function;
    2560                 :             :     }
    2561                 :             : 
    2562                 :           0 : exit_function:
    2563         [ #  # ]:           0 :     if (cut)
    2564                 :             :     {
    2565         [ #  # ]:           0 :         inchi_free(cut);
    2566                 :             :     }
    2567         [ #  # ]:           0 :     if (frag)
    2568                 :             :     {
    2569         [ #  # ]:           0 :         for (i = 0; i < n_frags; i++)
    2570                 :             :         {
    2571                 :           0 :             DiylFrag_Free(frag[i]);
    2572         [ #  # ]:           0 :             inchi_free(frag[i]);
    2573                 :             :         }
    2574         [ #  # ]:           0 :         inchi_free(frag);
    2575                 :             :     }
    2576         [ #  # ]:           0 :     if (frag_class)
    2577                 :             :     {
    2578         [ #  # ]:           0 :         inchi_free(frag_class);
    2579                 :             :     }
    2580         [ #  # ]:           0 :     if (frag_xc_counts)
    2581                 :             :     {
    2582         [ #  # ]:           0 :         inchi_free(frag_xc_counts);
    2583                 :             :     }
    2584                 :             : 
    2585                 :           0 :     return ret;
    2586                 :             : }
    2587                 :             : 
    2588                 :             : /***************************************************************************
    2589                 :             :  Return number of colors ncol<=maxcol in the sequence of n colored entries
    2590                 :             :  and counts of individiual colors
    2591                 :             : ***************************************************************************/
    2592                 :           0 : int count_colors_in_sequence( int *color, int n, int maxcol, int *counts)
    2593                 :             : {
    2594                 :           0 :     int i, ncol=0;
    2595                 :           0 :     memset(counts, 0, maxcol * sizeof(int)); /* djb-rwth: memset_s C11/Annex K variant? */
    2596         [ #  # ]:           0 :     for (i = 0; i<n; i++)
    2597                 :             :     {
    2598                 :           0 :         int colori = color[i];
    2599         [ #  # ]:           0 :         if (colori < 0) /* removed orig atom (H D etc.) */
    2600                 :             :         {
    2601                 :           0 :             continue;
    2602                 :             :         }
    2603         [ #  # ]:           0 :         if (0==counts[colori ])
    2604                 :             :         {
    2605                 :           0 :             ncol++;
    2606                 :             :         }
    2607                 :           0 :         counts[ color[i] ]++;
    2608                 :             :     }
    2609                 :           0 :     return ncol;
    2610                 :             : }
    2611                 :             : 
    2612                 :             : 
    2613                 :             : /***************************************************************************
    2614                 :             :  Find repeating starting subsequence in the sequence of n entries
    2615                 :             :  and return its length m
    2616                 :             :  each i-th entry, 0<i<m, is characterized by color[i] and optional color2[i]
    2617                 :             : ***************************************************************************/
    2618                 :           0 : int len_repeating_subsequence(int *color, int *color2, int n)
    2619                 :             : {
    2620                 :             :     int m, k;
    2621                 :             : 
    2622   [ #  #  #  # ]:           0 :     if (n < 2 || !color)
    2623                 :             :     {
    2624                 :           0 :         return 0;
    2625                 :             :     }
    2626                 :             : 
    2627         [ #  # ]:           0 :     for (m = 0; m < (n + 1) / 2; m++)
    2628                 :             :     {
    2629         [ #  # ]:           0 :         for (k = m + 1; k < n; k++)
    2630                 :             :         {
    2631         [ #  # ]:           0 :             if (color[k] != color[k - m - 1])
    2632                 :             :             {
    2633                 :           0 :                 goto nextm;
    2634                 :             :             }
    2635   [ #  #  #  # ]:           0 :             if (color2 && color2[k] != color2[k - m - 1])
    2636                 :             :             {
    2637                 :           0 :                 goto nextm;
    2638                 :             :             }
    2639                 :             :         }
    2640                 :           0 :         return (m + 1);
    2641                 :           0 : nextm:  ;
    2642                 :             :     }
    2643                 :             : 
    2644                 :           0 :     return 0;
    2645                 :             : }
    2646                 :             : 
    2647                 :             : 
    2648                 :             : /****************************************************************************
    2649                 :             :  Prepare CRU edits suggested by the string containing  preliminary generated
    2650                 :             :  interim (1.05+ flavoured) InChI and AuxInfo
    2651                 :             : ****************************************************************************/
    2652                 :           0 : int  OAD_Polymer_PrepareFrameShiftEdits( ORIG_ATOM_DATA *orig_at_data,
    2653                 :             :                                          char *sinchi,
    2654                 :             :                                          char *saux,
    2655                 :             :                                          OAD_StructureEdits *ed)
    2656                 :             : {
    2657                 :           0 :     int ret = _IS_OKAY;
    2658                 :           0 :     int *orig = NULL, *frame_shift_info = NULL;
    2659                 :             :     int n_frame_shifts, j;
    2660                 :           0 :     ModSCenterInfo *scinfo = NULL;              /* 4 elements; [0]th for old_end1, [1] old_end2, [2] end1, [3] end2     */
    2661                 :             : 
    2662                 :           0 :     OAD_Polymer *p = orig_at_data->polymer;
    2663                 :           0 :     int nu = orig_at_data->polymer->n;
    2664                 :           0 :     int nat = orig_at_data->num_inp_atoms;
    2665                 :             : 
    2666                 :             :     /* Extract cano_nums-->orig_nums mapping for InChI AuxInfo Main Layer */
    2667                 :           0 :     orig = (int *)inchi_calloc((long long)nat + 1, sizeof(int)); /* djb-rwth: cast operator added */
    2668         [ #  # ]:           0 :     if (!orig)
    2669                 :             :     {
    2670                 :           0 :         ret = _IS_ERROR;
    2671                 :           0 :         goto exit_function;
    2672                 :             :     }
    2673                 :           0 :     ret = extract_orig_nums_from_auxinfo_string(saux, orig);
    2674   [ #  #  #  # ]:           0 :     if (ret != _IS_OKAY && ret != _IS_WARNING)
    2675                 :             :     {
    2676                 :           0 :         ret = _IS_ERROR;
    2677                 :           0 :         goto exit_function;
    2678                 :             :     }
    2679                 :             : 
    2680                 :           0 :     scinfo = (ModSCenterInfo *)inchi_calloc(4, sizeof(scinfo[0]));
    2681         [ #  # ]:           0 :     if (!scinfo)
    2682                 :             :     {
    2683                 :           0 :         ret = _IS_ERROR;
    2684                 :           0 :         goto exit_function;
    2685                 :             :     }
    2686                 :             : 
    2687                 :             : 
    2688                 :             :     /* Parse InChI and extract, for each 'bistar' CRU, the senior bkbond (to frame-shift brackets to its ends) */
    2689                 :           0 :     frame_shift_info = (int *)inchi_calloc(3 * ((long long)nu + 1), sizeof(int)); /* djb-rwth: cast operator added */
    2690         [ #  # ]:           0 :     if (!frame_shift_info)
    2691                 :             :     {
    2692                 :           0 :         ret = _IS_ERROR;
    2693                 :           0 :         goto exit_function;
    2694                 :             :     }
    2695                 :           0 :     n_frame_shifts = GetFrameShiftInfoFrom105PlusInChI(sinchi, frame_shift_info, nu);
    2696                 :             :     /* translate atom numbers to orig numbers */
    2697         [ #  # ]:           0 :     for (j = 0; j < n_frame_shifts; j++)
    2698                 :             :     {
    2699                 :           0 :         frame_shift_info[3 * j + 1] = orig[frame_shift_info[3 * j + 1]];
    2700                 :           0 :         frame_shift_info[3 * j + 2] = orig[frame_shift_info[3 * j + 2]];
    2701                 :             :     }
    2702                 :             : 
    2703                 :             :     /* Collect OAD edits */
    2704         [ #  # ]:           0 :     for (j = 0; j < n_frame_shifts; j++)
    2705                 :             :     {
    2706                 :           0 :         OAD_PolymerUnit *u = NULL;
    2707                 :           0 :         int k, iu = -1; /*int iu = frame_shift_info[3 * j];*/
    2708                 :           0 :         int end1, cap1, cap1_is_star, end2, cap2, cap2_is_star, old_end1, old_end2, err, fail = 0;
    2709                 :             : 
    2710                 :           0 :         end1 = frame_shift_info[3 * j + 1];
    2711                 :           0 :         end2 = frame_shift_info[3 * j + 2];
    2712                 :             : 
    2713                 :             :         /* Find the unit to edit (== that unit whose alist contains the new end atoms) */
    2714         [ #  # ]:           0 :         for (k = 0; k < p->n; k++)
    2715                 :             :         {
    2716                 :           0 :             int ak, present=0;
    2717                 :             : 
    2718   [ #  #  #  # ]:           0 :             if (NULL == p->units[k]->blist || p->units[k]->nb < 2 )
    2719                 :             :             {
    2720                 :             :                 /* No crossing bonds in the unit */
    2721                 :           0 :                 continue;
    2722                 :             :             }
    2723                 :             :             /* Find the unit to edit (== that unit whose backbone contains the new end atoms)
    2724                 :             :             for (bk = 0; bk < p->units[k]->nbkbonds; bk++ )
    2725                 :             :             {
    2726                 :             :                 if ( bIsSameBond(end1, end2, p->units[k]->bkbonds[bk][0], p->units[k]->bkbonds[bk][1] ) )
    2727                 :             :                 {
    2728                 :             :                     iu = k;
    2729                 :             :                     break;
    2730                 :             :                 }
    2731                 :             :             }*/
    2732         [ #  # ]:           0 :             for (ak = 0; ak < p->units[k]->na; ak++ )
    2733                 :             :             {
    2734   [ #  #  #  # ]:           0 :                 if (p->units[k]->alist[ak] == end1 || p->units[k]->alist[ak] == end2)
    2735                 :             :                 {
    2736                 :           0 :                     present++;
    2737                 :             :                 }
    2738         [ #  # ]:           0 :                 if (present==2)
    2739                 :             :                 {
    2740                 :           0 :                     iu = k;
    2741                 :           0 :                     break;
    2742                 :             :                 }
    2743                 :             :             }
    2744                 :             :         }
    2745         [ #  # ]:           0 :         if (iu < 0)
    2746                 :             :         {
    2747                 :             :             /* Unit to edit unexpectedly not found, that's an error */
    2748                 :           0 :             ret = _IS_ERROR;
    2749                 :           0 :             goto exit_function;
    2750                 :             :         }
    2751                 :             : 
    2752                 :           0 :         u = p->units[iu];
    2753                 :             : 
    2754                 :           0 :         OAD_PolymerUnit_FindEndsAndCaps(u, orig_at_data,
    2755                 :             :                                         &old_end1, &cap1, &cap1_is_star,
    2756                 :             :                                         &old_end2, &cap2, &cap2_is_star,
    2757                 :             :                                         &err, NULL);
    2758                 :             : 
    2759   [ #  #  #  #  :           0 :         if (!err && cap1_is_star && cap2_is_star && end1 && end2 && cap1 && cap2)
          #  #  #  #  #  
             #  #  #  #  
                      # ]
    2760                 :             :         {
    2761                 :             :             /* find old CRU ends */
    2762         [ #  # ]:           0 :             if (cap1 == u->blist[0])         old_end1 = u->blist[1];
    2763         [ #  # ]:           0 :             else if (cap1 == u->blist[1])    old_end1 = u->blist[0];
    2764         [ #  # ]:           0 :             else if (cap1 == u->blist[2])    old_end1 = u->blist[3];
    2765         [ #  # ]:           0 :             else if (cap1 == u->blist[3])    old_end1 = u->blist[2];
    2766                 :             :             else /* something wrong */
    2767                 :           0 :                 continue;
    2768         [ #  # ]:           0 :             if (cap2 == u->blist[0])         old_end2 = u->blist[1];
    2769         [ #  # ]:           0 :             else if (cap2 == u->blist[1])    old_end2 = u->blist[0];
    2770         [ #  # ]:           0 :             else if (cap2 == u->blist[2])    old_end2 = u->blist[3];
    2771         [ #  # ]:           0 :             else if (cap2 == u->blist[3])    old_end2 = u->blist[2];
    2772                 :             :             else /* something wrong */
    2773                 :           0 :                 continue;
    2774                 :             : 
    2775   [ #  #  #  #  :           0 :             if (!old_end1 || !old_end2 || old_end1 == old_end2)
                   #  # ]
    2776                 :             :             {
    2777                 :           0 :                 continue;
    2778                 :             :             }
    2779   [ #  #  #  # ]:           0 :             if (bIsSameBond(old_end1, cap1, end1, cap1) && bIsSameBond(old_end2, cap2, end2, cap2))
    2780                 :             :             {
    2781                 :           0 :                 continue; /* ignore swaps for now */
    2782                 :             :             }
    2783                 :             : 
    2784                 :             :             /*  If applicable, collect bonds to modify */
    2785                 :             : 
    2786                 :             :             /* Check if atoms involved in modifications are stereocenters (needs additional care) */
    2787                 :           0 :             ModSCenter_Init(&scinfo[0], orig_at_data->at, old_end1 - 1);
    2788                 :           0 :             ModSCenter_Init(&scinfo[1], orig_at_data->at, old_end2 - 1);
    2789                 :           0 :             ModSCenter_Init(&scinfo[2], orig_at_data->at, end1 - 1);
    2790                 :           0 :             ModSCenter_Init(&scinfo[3], orig_at_data->at, end2 - 1);
    2791                 :             : 
    2792                 :             :             /* djb-rwth: removing redundant code */
    2793         [ #  # ]:           0 :             if (!bIsSameBond(old_end1, cap1, end1, cap1))
    2794                 :             :             {
    2795                 :             :                 /* Modify bond: (old_end1-cap1) --> (end1-cap1) */
    2796                 :           0 :                 fail = 0;
    2797                 :           0 :                 fail += IntArray_Append(ed->mod_bond, old_end1);
    2798                 :           0 :                 fail += IntArray_Append(ed->mod_bond, cap1);
    2799                 :           0 :                 fail += IntArray_Append(ed->mod_bond, end1);
    2800                 :           0 :                 fail += IntArray_Append(ed->mod_bond, cap1);
    2801         [ #  # ]:           0 :                 if (fail)
    2802                 :             :                 {
    2803                 :           0 :                     ret = _IS_ERROR;
    2804                 :           0 :                     goto exit_function;
    2805                 :             :                 }
    2806                 :           0 :                 ModSCenter_DelFrom(&scinfo[0], cap1 - 1);
    2807                 :           0 :                 ModSCenter_AddTo(&scinfo[2], cap1-1 );
    2808                 :             :             }
    2809         [ #  # ]:           0 :             if (!bIsSameBond(old_end2, cap2, end2, cap2))
    2810                 :             :             {
    2811                 :             :                 /* Modify bond: (old_end2-cap2) --> (end2-cap2) */
    2812                 :           0 :                 fail = 0;
    2813                 :           0 :                 fail += IntArray_Append(ed->mod_bond, old_end2);
    2814                 :           0 :                 fail += IntArray_Append(ed->mod_bond, cap2);
    2815                 :           0 :                 fail += IntArray_Append(ed->mod_bond, end2);
    2816                 :           0 :                 fail += IntArray_Append(ed->mod_bond, cap2);
    2817         [ #  # ]:           0 :                 if (fail)
    2818                 :             :                 {
    2819                 :           0 :                     ret = _IS_ERROR;
    2820                 :           0 :                     goto exit_function;
    2821                 :             :                 }
    2822                 :           0 :                 ModSCenter_DelFrom(&scinfo[1], cap2 - 1);
    2823                 :           0 :                 ModSCenter_AddTo(&scinfo[3], cap2 - 1);
    2824                 :             :             }
    2825                 :             :             /* Modify bond: (end1-end2) --> (old_end1-old_end2) */
    2826                 :           0 :             fail = 0;
    2827                 :           0 :             fail += IntArray_Append(ed->mod_bond, end1);
    2828                 :           0 :             fail += IntArray_Append(ed->mod_bond, end2);
    2829                 :           0 :             fail += IntArray_Append(ed->mod_bond, old_end1);
    2830                 :           0 :             fail += IntArray_Append(ed->mod_bond, old_end2);
    2831         [ #  # ]:           0 :             if (fail)
    2832                 :             :             {
    2833                 :           0 :                 ret = _IS_ERROR;
    2834                 :           0 :                 goto exit_function;
    2835                 :             :             }
    2836                 :           0 :             ModSCenter_DelFrom(&scinfo[2], end2 - 1);
    2837                 :           0 :             ModSCenter_DelFrom(&scinfo[3], end1 - 1);
    2838                 :           0 :             ModSCenter_AddTo(&scinfo[0], old_end2 - 1);
    2839                 :           0 :             ModSCenter_AddTo(&scinfo[1], old_end1 - 1);
    2840                 :             : 
    2841                 :             :         }
    2842                 :             : 
    2843                 :             :         /* djb-rwth: n_flip and ModSCenter_IsChanged function completely redundant? -- discussion required */
    2844         [ #  # ]:           0 :         if (orig_at_data->num_dimensions)
    2845                 :             :         {
    2846                 :             :             /* Check if we must flip stereocenter configuration */
    2847                 :             :             /* (ignore errrors signaled by returning -1)                */
    2848                 :           0 :             int n_flip = 0;
    2849         [ #  # ]:           0 :             if (0 < ModSCenter_IsChanged(&scinfo[0], orig_at_data->at))
    2850                 :             :             {
    2851                 :           0 :                 n_flip++;
    2852                 :             :             }
    2853         [ #  # ]:           0 :             if (0 < ModSCenter_IsChanged(&scinfo[1], orig_at_data->at))
    2854                 :             :             {
    2855                 :           0 :                 n_flip++;
    2856                 :             :             }
    2857         [ #  # ]:           0 :             if (0 < ModSCenter_IsChanged(&scinfo[2], orig_at_data->at))
    2858                 :             :             {
    2859                 :           0 :                 n_flip++;
    2860                 :             :             }
    2861         [ #  # ]:           0 :             if (0 < ModSCenter_IsChanged(&scinfo[3], orig_at_data->at))
    2862                 :             :             {
    2863                 :           0 :                 n_flip++;
    2864                 :             :             }
    2865                 :           0 :             n_flip = 1;
    2866                 :             :         }
    2867                 :             :     }
    2868                 :             : 
    2869                 :           0 : exit_function:
    2870         [ #  # ]:           0 :     if (orig)
    2871                 :             :     {
    2872         [ #  # ]:           0 :         inchi_free(orig);
    2873                 :             :     }
    2874         [ #  # ]:           0 :     if (frame_shift_info)
    2875                 :             :     {
    2876         [ #  # ]:           0 :         inchi_free(frame_shift_info);
    2877                 :             :     }
    2878         [ #  # ]:           0 :     if (scinfo)
    2879                 :             :     {
    2880         [ #  # ]:           0 :         inchi_free(scinfo);
    2881                 :             :     }
    2882                 :             : 
    2883                 :           0 :     return ret;
    2884                 :             : }
    2885                 :             : 
    2886                 :             : /****************************************************************************
    2887                 :             :  Initialize modifiable stereo center
    2888                 :             : ****************************************************************************/
    2889                 :           0 : void ModSCenter_Init(ModSCenterInfo *scinfo, inp_ATOM *at, int iatom)
    2890                 :             : {
    2891                 :             :     int i;
    2892                 :           0 :     scinfo->num = iatom;
    2893                 :           0 :     scinfo->valence = at[iatom].valence;
    2894                 :           0 :     scinfo->n_stereo = NDefStereoBonds(at, iatom, 1); /* , bOnlyPointedEndMatters=1 */
    2895         [ #  # ]:           0 :     for (i = 0; i < scinfo->valence; i++)
    2896                 :             :     {
    2897                 :           0 :         scinfo->nbr[i] = at[iatom].neighbor[i];
    2898                 :           0 :         scinfo->new_nbr[i] = scinfo->nbr[i];
    2899                 :             :     }
    2900                 :             : 
    2901                 :           0 :     return;
    2902                 :             : }
    2903                 :             : /****************************************************************************/
    2904                 :           0 : int NDefStereoBonds(inp_ATOM *at, int iatom, int bOnlyPointedEndMatters)
    2905                 :             : {
    2906                 :           0 :     int i, n_stereo = 0;
    2907                 :             :     int stereo_value, stereo_type;
    2908         [ #  # ]:           0 :     for (i = 0; i < at[iatom].valence; i++)
    2909                 :             :     {
    2910                 :           0 :         stereo_value = at[iatom].bond_stereo[i];
    2911         [ #  # ]:           0 :         if (bOnlyPointedEndMatters)
    2912                 :             :         {
    2913                 :             :             /* establish the stereo considering only the pointed end of stereo bond */
    2914                 :           0 :             stereo_type = stereo_value;
    2915                 :             :         }
    2916                 :             :         else
    2917                 :             :         {
    2918                 :           0 :             stereo_type = abs(stereo_value);
    2919                 :             :         }
    2920   [ #  #  #  # ]:           0 :         if (stereo_type == STEREO_SNGL_UP || stereo_type == STEREO_SNGL_DOWN)
    2921                 :             :         {
    2922                 :           0 :             n_stereo++;
    2923                 :             :         }
    2924                 :             :     }
    2925                 :           0 :     return n_stereo;
    2926                 :             : }
    2927                 :             : 
    2928                 :             : 
    2929                 :             : /****************************************************************************
    2930                 :             :  Add atom to modifiable stereo center
    2931                 :             : ****************************************************************************/
    2932                 :           0 : void ModSCenter_AddTo(ModSCenterInfo *scinfo, int iadd)
    2933                 :             : {
    2934         [ #  # ]:           0 :     if (!is_in_the_ilist(scinfo->new_nbr, iadd, scinfo->valence))
    2935                 :             :     {
    2936                 :           0 :         scinfo->new_nbr[scinfo->valence] = iadd;
    2937                 :           0 :         scinfo->valence++;
    2938                 :             :     }
    2939                 :           0 :     return;
    2940                 :             : }
    2941                 :             : /****************************************************************************
    2942                 :             :  Delete atom from modifiable stereo center
    2943                 :             : ****************************************************************************/
    2944                 :           0 : void ModSCenter_DelFrom(ModSCenterInfo *scinfo, int idel)
    2945                 :             : {
    2946                 :             :     int i, j;
    2947         [ #  # ]:           0 :     for (i = 0; i < scinfo->valence; i++)
    2948                 :             :     {
    2949         [ #  # ]:           0 :         if (scinfo->nbr[i]==idel )
    2950                 :             :         {
    2951         [ #  # ]:           0 :             for (j=i+1; j < scinfo->valence; j++)
    2952                 :             :             {
    2953                 :           0 :                 scinfo->new_nbr[j-1] = scinfo->new_nbr[j];
    2954                 :             :             }
    2955                 :           0 :             scinfo->valence--;
    2956                 :           0 :             return;
    2957                 :             :         }
    2958                 :             :     }
    2959                 :           0 :     return;
    2960                 :             : }
    2961                 :             : /****************************************************************************
    2962                 :             :  Check if stereo configuration of modifiable stereo center changed
    2963                 :             : ****************************************************************************/
    2964                 :             : /* djb-rwth: n_flip and ModSCenter_IsChanged function completely redundant? -- discussion required */
    2965                 :           0 : int ModSCenter_IsChanged(ModSCenterInfo *scinfo, inp_ATOM *at)
    2966                 :             : {
    2967                 :           0 :     int i, ns, base1=-1, base2=-1, new_base2=-1, n_changed=0;
    2968                 :             :     double a[3], b[3], new_b[3], z[3], new_z[3], zz; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    2969                 :             : 
    2970         [ #  # ]:           0 :     if (scinfo->n_stereo < 1)
    2971                 :             :     {
    2972                 :           0 :         return 0;
    2973                 :             :     }
    2974         [ #  # ]:           0 :     if (scinfo->valence != at[scinfo->num].valence )
    2975                 :             :     {
    2976                 :           0 :         return -1; /* something went wrong */
    2977                 :             :     }
    2978                 :           0 :     iisort(scinfo->nbr, scinfo->valence);
    2979                 :           0 :     iisort(scinfo->new_nbr, scinfo->valence);
    2980                 :             :     /* Find the kept stereo base atom */
    2981         [ #  # ]:           0 :     for (i = 0; i < at[scinfo->num].valence; i++)
    2982                 :             :     {
    2983         [ #  # ]:           0 :         if ( is_in_the_ilist(scinfo->nbr, scinfo->new_nbr[i], scinfo->valence) )
    2984                 :             :         {
    2985                 :           0 :             ns = NDefStereoBonds(at, scinfo->new_nbr[i], 0); /* bOnlyPointedEndMatters=0 */
    2986         [ #  # ]:           0 :             if (ns==0)
    2987                 :             :             {
    2988                 :           0 :                 base1 = scinfo->new_nbr[i];
    2989                 :           0 :                 break;
    2990                 :             :             }
    2991                 :             :         }
    2992                 :             :     }
    2993         [ #  # ]:           0 :     if (base1==-1)
    2994                 :             :     {
    2995                 :           0 :         return -1; /* something went wrong */
    2996                 :             :     }
    2997                 :             :     /* Find the newly appeared stereo base atom */
    2998         [ #  # ]:           0 :     for (i = 0; i < at[scinfo->num].valence; i++)
    2999                 :             :     {
    3000                 :             :         /*!!! TUT NADO NE TAK
    3001                 :             :          base2 tot, kogo net v new_nbr
    3002                 :             :          new_base2 - tot, kogo net v  nbr
    3003                 :             :         */
    3004         [ #  # ]:           0 :         if ( !is_in_the_ilist(scinfo->nbr, scinfo->new_nbr[i], scinfo->valence))
    3005                 :             :         {
    3006                 :           0 :             ns = NDefStereoBonds(at, scinfo->nbr[i], 0);
    3007         [ #  # ]:           0 :             if (ns == 0)
    3008                 :             :             {
    3009                 :           0 :                 new_base2 = scinfo->new_nbr[i];
    3010                 :           0 :                 base2 = scinfo->nbr[i];
    3011                 :           0 :                 n_changed++;
    3012                 :             :             }
    3013                 :             :         }
    3014                 :             :     }
    3015   [ #  #  #  #  :           0 :     if (n_changed > 1 || new_base2 == -1 || base2 == -1)
                   #  # ]
    3016                 :             :     {
    3017                 :           0 :         return -1; /* something went wrong */
    3018                 :             :     }
    3019                 :           0 :     a[0] = at[base1].x - at[scinfo->num].x; a[1] = at[base1].y - at[scinfo->num].y; a[2] = at[base1].z - at[scinfo->num].z;
    3020                 :           0 :     b[0] = at[base2].x - at[scinfo->num].x; b[1] = at[base2].y - at[scinfo->num].y; b[2] = at[base2].z - at[scinfo->num].z;
    3021                 :           0 :     new_b[0] = at[new_base2].x - at[scinfo->num].x; new_b[1] = at[new_base2].y - at[scinfo->num].y; new_b[2] = at[new_base2].z - at[scinfo->num].z;
    3022                 :             : 
    3023                 :           0 :     cross_prod3(a, b, z);
    3024                 :           0 :     cross_prod3(a, new_b, new_z);
    3025                 :           0 :     zz = dot_prod3(z, new_z); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    3026                 :             : 
    3027                 :           0 :     return -1;
    3028                 :             : }
        

Generated by: LCOV version 2.0-1