LCOV - code coverage report
Current view: top level - src - runichi2.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 11.1 % 995 110
Test Date: 2026-05-04 07:05:02 Functions: 20.0 % 30 6
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 6.1 % 960 59

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

Generated by: LCOV version 2.0-1