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

Generated by: LCOV version 2.0-1