LCOV - code coverage report
Current view: top level - src - mol_fmt3.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 59.2 % 758 449
Test Date: 2026-05-04 07:05:02 Functions: 81.2 % 16 13
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 40.2 % 522 210

             Branch data     Line data    Source code
       1                 :             : /*
       2                 :             :  * International Chemical Identifier (InChI)
       3                 :             :  * Version 1
       4                 :             :  * Software version 1.07
       5                 :             :  * April 30, 2024
       6                 :             :  *
       7                 :             :  * MIT License
       8                 :             :  *
       9                 :             :  * Copyright (c) 2024 IUPAC and InChI Trust
      10                 :             :  *
      11                 :             :  * Permission is hereby granted, free of charge, to any person obtaining a copy
      12                 :             :  * of this software and associated documentation files (the "Software"), to deal
      13                 :             :  * in the Software without restriction, including without limitation the rights
      14                 :             :  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
      15                 :             :  * copies of the Software, and to permit persons to whom the Software is
      16                 :             :  * furnished to do so, subject to the following conditions:
      17                 :             :  *
      18                 :             :  * The above copyright notice and this permission notice shall be included in all
      19                 :             :  * copies or substantial portions of the Software.
      20                 :             :  *
      21                 :             :  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
      22                 :             :  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
      23                 :             :  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
      24                 :             :  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
      25                 :             :  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
      26                 :             :  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
      27                 :             :  * SOFTWARE.
      28                 :             :  *
      29                 :             :  * The InChI library and programs are free software developed under the
      30                 :             :  * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
      31                 :             :  * Originally developed at NIST.
      32                 :             :  * Modifications and additions by IUPAC and the InChI Trust.
      33                 :             :  * Some portions of code were developed/changed by external contributors
      34                 :             :  * (either contractor or volunteer) which are listed in the file
      35                 :             :  * 'External-contributors' included in this distribution.
      36                 :             :  *
      37                 :             :  * info@inchi-trust.org
      38                 :             :  *
      39                 :             :  */
      40                 :             : 
      41                 :             : #include <stdlib.h>
      42                 :             : #include <ctype.h>
      43                 :             : #include <string.h>
      44                 :             : #include <math.h>
      45                 :             : #include <float.h>
      46                 :             : #include <limits.h>
      47                 :             : 
      48                 :             : #include "mode.h"
      49                 :             : #include "mol_fmt.h"
      50                 :             : 
      51                 :             : #include "ichierr.h"
      52                 :             : #include "util.h"
      53                 :             : #include "ichi_io.h"
      54                 :             : 
      55                 :             : #include "bcf_s.h"
      56                 :             : #include "stb_sprintf.h"
      57                 :             : 
      58                 :             : /*
      59                 :             :     Molfile V3000 related procedures
      60                 :             : 
      61                 :             : */
      62                 :             : 
      63                 :             : static int get_actual_atom_number(int index, int n, int *orig, int *fin);
      64                 :             : 
      65                 :             : /****************************************************************************
      66                 :             :  Init V3000 reader
      67                 :             : ****************************************************************************/
      68                 :          48 : int MolfileV3000Init(MOL_FMT_CTAB *ctab,
      69                 :             :                      char *pStrErr)
      70                 :             : {
      71                 :          48 :     int ret = 0;
      72                 :             :     int i;
      73                 :             : 
      74                 :             :     /* STAR ATOMS */
      75                 :          48 :     ctab->v3000->n_star_atoms = 0;
      76                 :          48 :     ctab->v3000->n_non_star_atoms = 0;
      77                 :             : 
      78         [ +  - ]:          48 :     if (ctab->n_atoms)
      79                 :             :     {
      80                 :          48 :         ctab->v3000->atom_index_orig = (int *)inchi_calloc(ctab->n_atoms, sizeof(int));
      81                 :          48 :         ctab->v3000->atom_index_fin = (int *)inchi_calloc(ctab->n_atoms, sizeof(int));
      82   [ +  -  +  - ]:          48 :         if (ctab->v3000->atom_index_orig && ctab->v3000->atom_index_fin) /* djb-rwth: fixing a NULL pointer dereference */
      83                 :             :         {
      84         [ +  + ]:         635 :             for (i = 0; i < ctab->n_atoms; i++) /* protective */
      85                 :             :             {
      86                 :         587 :                 ctab->v3000->atom_index_orig[i] = -1;
      87                 :         587 :                 ctab->v3000->atom_index_fin[i] = -1;
      88                 :             :             }
      89                 :             :         }
      90                 :             :     }
      91                 :             :     else
      92                 :             :     {
      93                 :           0 :         ctab->v3000->atom_index_orig = NULL;
      94                 :           0 :         ctab->v3000->atom_index_fin = NULL;
      95                 :             :     }
      96                 :             : 
      97                 :             :     /* HAPTIC BONDS */
      98                 :          48 :     ctab->v3000->n_haptic_bonds = 0;
      99                 :          48 :     ctab->v3000->haptic_bonds = (NUM_LISTS *)inchi_calloc(1, sizeof(NUM_LISTS));
     100         [ -  + ]:          48 :     if (!ctab->v3000->haptic_bonds)
     101                 :             :     {
     102                 :           0 :         AddErrorMessage(pStrErr, "Out of RAM");
     103                 :           0 :         return -1;
     104                 :             :     }
     105                 :          48 :     ret = NumLists_Alloc(ctab->v3000->haptic_bonds, 8);
     106         [ -  + ]:          48 :     if (ret < 0)
     107                 :             :     {
     108                 :           0 :         ctab->v3000->haptic_bonds = NULL;
     109                 :           0 :         AddErrorMessage(pStrErr, "Out of RAM");
     110                 :           0 :         return -1;
     111                 :             :     }
     112                 :             : 
     113                 :             :     /* STEABS */
     114                 :          48 :     ctab->v3000->n_steabs = 0;
     115                 :          48 :     ctab->v3000->steabs = (NUM_LISTS *)inchi_calloc(1, sizeof(NUM_LISTS));
     116         [ -  + ]:          48 :     if (!ctab->v3000->steabs)
     117                 :             :     {
     118                 :           0 :         AddErrorMessage(pStrErr, "Out of RAM");
     119                 :           0 :         return -1;
     120                 :             :     }
     121                 :          48 :     ret = NumLists_Alloc(ctab->v3000->steabs, 1);
     122         [ -  + ]:          48 :     if (ret < 0)
     123                 :             :     {
     124                 :           0 :         ctab->v3000->steabs = NULL;
     125                 :           0 :         AddErrorMessage(pStrErr, "Out of RAM");
     126                 :           0 :         return -1;
     127                 :             :     }
     128                 :             :     /* STEREL */
     129                 :          48 :     ctab->v3000->n_sterel = 0;
     130                 :          48 :     ctab->v3000->sterel = (NUM_LISTS *)inchi_calloc(1, sizeof(NUM_LISTS));
     131         [ -  + ]:          48 :     if (!ctab->v3000->sterel)
     132                 :             :     {
     133                 :           0 :         AddErrorMessage(pStrErr, "Out of RAM");
     134                 :           0 :         return -1;
     135                 :             :     }
     136                 :          48 :     ret = NumLists_Alloc(ctab->v3000->sterel, 4);
     137         [ -  + ]:          48 :     if (ret < 0)
     138                 :             :     {
     139                 :           0 :         ctab->v3000->sterel = NULL;
     140                 :           0 :         AddErrorMessage(pStrErr, "Out of RAM");
     141                 :           0 :         return -1;
     142                 :             :     }
     143                 :             :     /* STERAC */
     144                 :          48 :     ctab->v3000->n_sterac = 0;
     145                 :          48 :     ctab->v3000->sterac = (NUM_LISTS *)inchi_calloc(1, sizeof(NUM_LISTS));
     146         [ -  + ]:          48 :     if (!ctab->v3000->sterac)
     147                 :             :     {
     148                 :           0 :         AddErrorMessage(pStrErr, "Out of RAM");
     149                 :           0 :         return -1;
     150                 :             :     }
     151                 :          48 :     ret = NumLists_Alloc(ctab->v3000->sterac, 4);
     152         [ -  + ]:          48 :     if (ret < 0)
     153                 :             :     {
     154                 :           0 :         ctab->v3000->sterac = NULL;
     155                 :           0 :         AddErrorMessage(pStrErr, "Out of RAM");
     156                 :           0 :         return -1;
     157                 :             :     }
     158                 :             : 
     159                 :          48 :     return ret;
     160                 :             : }
     161                 :             : 
     162                 :             : /****************************************************************************
     163                 :             :  Delete V3000 reader data
     164                 :             : ****************************************************************************/
     165                 :          48 : int DeleteMolfileV3000Info(MOL_FMT_v3000 *v3000)
     166                 :             : {
     167         [ +  - ]:          48 :     if (v3000)
     168                 :             :     {
     169                 :             : 
     170         [ +  - ]:          48 :         if (v3000->atom_index_orig)
     171                 :             :         {
     172         [ +  - ]:          48 :             inchi_free(v3000->atom_index_orig);
     173                 :             :         }
     174                 :             : 
     175         [ +  - ]:          48 :         if (v3000->atom_index_fin)
     176                 :             :         {
     177         [ +  - ]:          48 :             inchi_free(v3000->atom_index_fin);
     178                 :             :         }
     179                 :             : 
     180         [ +  - ]:          48 :         if (v3000->haptic_bonds)
     181                 :             :         {
     182                 :          48 :             NumLists_Free(v3000->haptic_bonds);
     183                 :          48 :             free(v3000->haptic_bonds);
     184                 :             :         }
     185                 :             : 
     186         [ +  - ]:          48 :         if (v3000->steabs)
     187                 :             :         {
     188                 :          48 :             NumLists_Free(v3000->steabs);
     189                 :          48 :             free(v3000->steabs);
     190                 :             :         }
     191                 :             : 
     192         [ +  - ]:          48 :         if (v3000->sterel)
     193                 :             :         {
     194                 :          48 :             NumLists_Free(v3000->sterel);
     195                 :          48 :             free(v3000->sterel);
     196                 :             :         }
     197                 :             : 
     198         [ +  - ]:          48 :         if (v3000->sterac)
     199                 :             :         {
     200                 :          48 :             NumLists_Free(v3000->sterac);
     201                 :          48 :             free(v3000->sterac);
     202                 :             :         }
     203                 :             : 
     204         [ +  - ]:          48 :         inchi_free(v3000);
     205                 :          48 :         v3000 = NULL;
     206                 :             :     }
     207                 :             : 
     208                 :          48 :     return 0;
     209                 :             : }
     210                 :             : 
     211                 :             : /****************************************************************************
     212                 :             :     Extended version of inchi_fgetsLf which is able of reading
     213                 :             :     concatenated lines (ending with '-') of V3000 Molfile.
     214                 :             :     Also removes "M  V30 " prefix" and normalizes the rest of string
     215                 :             : ****************************************************************************/
     216                 :           0 : char *inchi_fgetsLf_V3000(char *line, INCHI_IOSTREAM *inp_stream)
     217                 :             : {
     218                 :           0 :     char *p = NULL;
     219                 :           0 :     int len = 0;
     220                 :             : 
     221                 :           0 :     p = inchi_fgetsLf(line, MOL_FMT_V3000_INPLINELEN, inp_stream);
     222         [ #  # ]:           0 :     if (!p)
     223                 :             :     {
     224                 :           0 :         return NULL;
     225                 :             :     }
     226                 :             : 
     227                 :           0 :     len = (int)strlen(p);
     228         [ #  # ]:           0 :     if (len < 7)
     229                 :             :     {
     230                 :           0 :         return NULL;
     231                 :             :     }
     232                 :             : 
     233         [ #  # ]:           0 :     if (strncmp(p, "M  V30 ", 7))
     234                 :             :     {
     235                 :           0 :         return NULL;
     236                 :             :     }
     237                 :             : 
     238                 :           0 :     p += 7;
     239                 :           0 :     len = normalize_string(p); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     240                 :             : 
     241                 :           0 :     return p;
     242                 :             : }
     243                 :             : 
     244                 :             : /****************************************************************************
     245                 :             :     Read V3000 field.
     246                 :             : 
     247                 :             :     It is MolfileReadField updated for V3000.
     248                 :             :     It considers right whitespace as stop sign,
     249                 :             :     no predefined len is used.
     250                 :             : 
     251                 :             :     Returns -1 on error otherwise number of bytes read.
     252                 :             : 
     253                 :             :     NB: ASSUMES THAT STRING HAS BEEN NORMALIZED with normalize_string()
     254                 :             : 
     255                 :             :     TODO: treat strings with spaces in double quotes
     256                 :             : ****************************************************************************/
     257                 :        6531 : int MolfileV3000ReadField(void *data,
     258                 :             :                           int data_type,
     259                 :             :                           char **line_ptr)
     260                 :             : {
     261                 :        6531 :     int nread = 0;
     262                 :             :     char field[MOL_FMT_V3000_MAXFIELDLEN];
     263                 :        6531 :     const int max_field_len = sizeof(field);
     264                 :        6531 :     long ldata = 0L;
     265                 :        6531 :     double ddata = 0.0;
     266                 :             :     char *p_end;
     267                 :             : 
     268                 :        6531 :     memset(field, 0, max_field_len); /* djb-rwth: memset_s C11/Annex K variant? */
     269                 :             : 
     270                 :        6531 :     nread = read_upto_delim(line_ptr, field, max_field_len, " \t\n\v\f\r");
     271                 :             : 
     272   [ +  +  +  - ]:        6531 :     switch (data_type)
     273                 :             :     {
     274                 :         635 :     case MOL_FMT_STRING_DATA:
     275                 :             :     {
     276   [ +  -  +  - ]:         635 :         if (nread && (nread <= ATOM_EL_LEN)) /* djb-rwth: fixing GHI #133 -- updated 28/09/2025 */
     277                 :             :         {
     278                 :         635 :             mystrncpy((char *)data, field, nread + 1);
     279                 :             :         }
     280                 :             :         else
     281                 :             :         {
     282                 :           0 :             ((char *)data)[0] = '\0';
     283                 :             :         }
     284                 :             :     }
     285                 :         635 :     break;
     286                 :             : 
     287                 :        4135 :     case MOL_FMT_CHAR_INT_DATA:
     288                 :             :     case MOL_FMT_SHORT_INT_DATA:
     289                 :             :     case MOL_FMT_LONG_INT_DATA:
     290                 :             :     case MOL_FMT_INT_DATA:
     291                 :             :     {
     292                 :             :         /* assume that field ends at first non-digit */
     293                 :        4135 :         ldata = strtol(field, &p_end, 10);
     294                 :             : 
     295         [ +  + ]:        4135 :         if (p_end == field)
     296                 :             :         {
     297                 :           3 :             nread = 0;
     298                 :             :         }
     299                 :             : 
     300         [ -  + ]:        4135 :         if (data_type == MOL_FMT_LONG_INT_DATA)
     301                 :             :         {
     302   [ #  #  #  # ]:           0 :             if (LONG_MIN < ldata && ldata < LONG_MAX)
     303                 :             :             {
     304                 :           0 :                 *(long *)data = (long)ldata;
     305                 :             :             }
     306                 :             :             else
     307                 :             :             {
     308                 :           0 :                 *(long *)data = 0L;
     309                 :           0 :                 nread = -1;
     310                 :             :             }
     311                 :             :         }
     312         [ +  + ]:        4135 :         else if (data_type == MOL_FMT_INT_DATA)
     313                 :             :         {
     314   [ +  -  +  - ]:        2091 :             if (INT_MIN <= ldata && ldata <= INT_MAX) /* djb-rwth: addressing coverity ID #499496/499553 -- ldata check seems to be necessary */
     315                 :             :             {
     316                 :        2091 :                 *(int *)data = (int)ldata;
     317                 :             :             }
     318                 :             :             else
     319                 :             :             {
     320                 :           0 :                 *(int *)data = (int)0;
     321                 :           0 :                 nread = -1;
     322                 :             :             }
     323                 :             :         }
     324                 :             : 
     325         [ +  + ]:        2044 :         else if (data_type == MOL_FMT_CHAR_INT_DATA)
     326                 :             :         {
     327   [ +  -  +  - ]:         960 :             if (SCHAR_MIN <= ldata && ldata <= SCHAR_MAX)
     328                 :             :             {
     329                 :         960 :                 *(S_CHAR *)data = (S_CHAR)ldata;
     330                 :             :             }
     331                 :             :             else
     332                 :             :             {
     333                 :           0 :                 *(S_CHAR *)data = (S_CHAR)0;
     334                 :           0 :                 nread = -1;
     335                 :             :             }
     336                 :             :         }
     337                 :             : 
     338         [ +  - ]:        1084 :         else if (data_type == MOL_FMT_SHORT_INT_DATA)
     339                 :             :         {
     340   [ +  -  +  - ]:        1084 :             if (SHRT_MIN <= ldata && ldata <= SHRT_MAX)
     341                 :             :             {
     342                 :        1084 :                 *(S_SHORT *)data = (S_SHORT)ldata;
     343                 :             :             }
     344                 :             :             else
     345                 :             :             {
     346                 :           0 :                 *(S_SHORT *)data = (S_SHORT)0;
     347                 :           0 :                 nread = -1;
     348                 :             :             }
     349                 :             :         }
     350                 :             :         else
     351                 :             :         {
     352                 :           0 :             nread = -1;
     353                 :             :         }
     354                 :             :     }
     355                 :        4135 :     break; /* INT's */
     356                 :             : 
     357                 :        1761 :     case MOL_FMT_DOUBLE_DATA:
     358                 :             :     case MOL_FMT_FLOAT_DATA:
     359                 :             :     {
     360                 :             :         /* assume that field ends at first non-digit */
     361                 :        1761 :         ddata = strtod(field, &p_end);
     362                 :             : 
     363         [ -  + ]:        1761 :         if (p_end == field)
     364                 :             :         {
     365                 :           0 :             nread = 0;
     366                 :             :         }
     367                 :             : 
     368         [ +  - ]:        1761 :         if (data_type == MOL_FMT_DOUBLE_DATA)
     369                 :             :         {
     370   [ +  -  +  - ]:        1761 :             if (ddata != HUGE_VAL && /*ldata*/ ddata != -HUGE_VAL)
     371                 :             :             {
     372                 :        1761 :                 *(double *)data = ddata;
     373                 :             :             }
     374                 :             :             else
     375                 :             :             {
     376                 :           0 :                 *(double *)data = 0.0;
     377                 :           0 :                 nread = -1;
     378                 :             :             }
     379                 :             :         }
     380         [ #  # ]:           0 :         else if (data_type == MOL_FMT_FLOAT_DATA)
     381                 :             :         {
     382         [ #  # ]:           0 :             if (fabs(ddata) <= (double)FLT_MIN)
     383                 :             :             {
     384                 :           0 :                 *(float *)data = 0.0;
     385                 :             :             }
     386         [ #  # ]:           0 :             else if (fabs(ddata) >= (double)FLT_MAX)
     387                 :             :             {
     388                 :           0 :                 *(float *)data = 0.0;
     389                 :           0 :                 nread = -1;
     390                 :             :             }
     391                 :             :         }
     392                 :             :         else
     393                 :             :         {
     394                 :           0 :             *(float *)data = (float)ddata; /* djb-rwth: addressing coverity ID #499519 -- probably never reached */
     395                 :             :         }
     396                 :             :     }
     397                 :        1761 :     break; /* REAL's */
     398                 :             : 
     399                 :           0 :     default:
     400                 :           0 :         nread = -1;
     401                 :             :     }
     402                 :             : 
     403                 :        6531 :     return nread;
     404                 :             : }
     405                 :             : 
     406                 :             : /****************************************************************************
     407                 :             :     Read V3000 keyword.
     408                 :             :     TODO: treat strings with spaces in double quotes
     409                 :             : ****************************************************************************/
     410                 :         396 : int MolfileV3000ReadKeyword(char *key,
     411                 :             :                             char **line_ptr)
     412                 :             : {
     413                 :         396 :     int nread = 0;
     414                 :             :     char field[MOL_FMT_V3000_MAXFIELDLEN];
     415                 :         396 :     const int max_field_len = sizeof(field);
     416                 :             : 
     417                 :         396 :     memset(field, 0, max_field_len); /* djb-rwth: memset_s C11/Annex K variant? */
     418                 :             : 
     419                 :         396 :     nread = read_upto_delim(line_ptr, field, max_field_len, "= \t\n\v\f\r");
     420                 :             : 
     421         [ +  - ]:         396 :     if (nread)
     422                 :             :     {
     423                 :         396 :         mystrncpy(key, field, nread + 1);
     424                 :             :         /* consume '=' sign if present */
     425         [ +  - ]:         396 :         if (*line_ptr)
     426                 :             :         {
     427         [ +  - ]:         396 :             if (*line_ptr[0] == '=')
     428                 :             :             {
     429                 :         396 :                 *line_ptr = *line_ptr + 1;
     430                 :             :             }
     431                 :             :         }
     432                 :             :     }
     433                 :             :     else
     434                 :             :     {
     435                 :           0 :         key[0] = '\0';
     436                 :             :     }
     437                 :             : 
     438                 :         396 :     return nread;
     439                 :             : }
     440                 :             : 
     441                 :             : /****************************************************************************
     442                 :             :  Read V3000 head of CTab
     443                 :             : ****************************************************************************/
     444                 :          48 : int MolfileV3000ReadCTABBeginAndCountsLine(MOL_FMT_CTAB *ctab,
     445                 :             :                                            INCHI_IOSTREAM *inp_file,
     446                 :             :                                            char *pStrErr)
     447                 :             : {
     448                 :             :     char field[MOL_FMT_V3000_MAXFIELDLEN];
     449                 :          48 :     int err = 0, len; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     450                 :          48 :     int failed = 0;
     451                 :             : 
     452                 :             :     int nc;
     453                 :          48 :     char *p = NULL, *line = NULL;
     454                 :             :     INCHI_IOSTREAM tmpin;
     455                 :          48 :     INCHI_IOS_STRING *pin = &tmpin.s;
     456                 :          48 :     inchi_ios_init(&tmpin, INCHI_IOS_TYPE_STRING, NULL);
     457                 :             : 
     458                 :          48 :     field[0] = '\0'; /* djb-rwth: adding zero termination */
     459                 :             : 
     460                 :             :     /* Check for proper start */
     461                 :             : 
     462                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     463                 :          48 :     inchi_strbuf_reset(pin);
     464                 :          48 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     465         [ -  + ]:          48 :     if (nc < 1)
     466                 :             :     {
     467                 :           0 :         p = NULL;
     468                 :             :     }
     469                 :             :     else
     470                 :             :     {
     471                 :          48 :         p = line = pin->pStr;
     472                 :             :     }
     473   [ +  -  -  + ]:          48 :     if (!p || strcmp(p, "BEGIN CTAB"))
     474                 :             :     {
     475         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Error: No V3000 CTab start marker");
     476                 :             :     }
     477                 :          48 :     remove_one_lf(line);
     478                 :             : 
     479                 :             :     /* Reset all previosly read data from quasi-counts line            */
     480                 :             :     /* (which contains only single meaningful value, 'V3000' marker    */
     481                 :          48 :     ctab->n_atoms = -1;
     482                 :          48 :     ctab->n_bonds = -1;
     483                 :          48 :     ctab->chiral_flag = -1;
     484                 :          48 :     ctab->n_stext_entries = -1;
     485                 :             :     /* Relax stricthness of V3000 conformance: */
     486                 :             :     /* Do not check if '999' supplied, just use this. */
     487                 :          48 :     ctab->n_property_lines = 999;
     488                 :             : 
     489                 :             :     /* Read counts line */
     490                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     491                 :          48 :     inchi_strbuf_reset(pin);
     492                 :          48 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     493         [ -  + ]:          48 :     if (nc < 1)
     494                 :             :     {
     495                 :           0 :         p = NULL;
     496                 :             :     }
     497                 :             :     else
     498                 :             :     {
     499                 :          48 :         p = line = pin->pStr;
     500                 :             :     }
     501         [ -  + ]:          48 :     if (!p)
     502                 :             :     {
     503         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Cannot read V3000 counts line");
     504                 :             :     }
     505                 :          48 :     remove_one_lf(line);
     506                 :             : 
     507                 :             :     /* Parse counts line */
     508                 :          48 :     len = MolfileV3000ReadField(field, MOL_FMT_STRING_DATA, &p); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     509         [ -  + ]:          48 :     if (strcmp(field, "COUNTS"))
     510                 :             :     {
     511         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Cannot read V3000 counts line");
     512                 :             :     }
     513                 :          48 :     failed = 0;
     514         [ -  + ]:          48 :     if (0 > MolfileV3000ReadField(&ctab->n_atoms, MOL_FMT_INT_DATA, &p))
     515                 :             :     {
     516                 :           0 :         failed = 2;
     517                 :             :     }
     518         [ -  + ]:          48 :     else if (0 > MolfileV3000ReadField(&ctab->n_bonds, MOL_FMT_INT_DATA, &p))
     519                 :             :     {
     520                 :           0 :         failed = 1;
     521                 :             :     }
     522         [ -  + ]:          48 :     else if (0 > MolfileV3000ReadField(&ctab->v3000->n_sgroups, MOL_FMT_INT_DATA, &p))
     523                 :             :     {
     524                 :           0 :         failed = 1;
     525                 :             :     }
     526         [ -  + ]:          48 :     else if (0 > MolfileV3000ReadField(&ctab->v3000->n_3d_constraints, MOL_FMT_INT_DATA, &p))
     527                 :             :     {
     528                 :           0 :         failed = 1;
     529                 :             :     }
     530         [ -  + ]:          48 :     else if (0 > MolfileV3000ReadField(&ctab->chiral_flag, MOL_FMT_CHAR_INT_DATA, &p))
     531                 :             :     {
     532                 :           0 :         failed = 1;
     533                 :             :     }
     534                 :             : 
     535         [ +  - ]:          48 :     if (failed)
     536                 :             :     {
     537                 :           0 :         err = 3;
     538         [ #  # ]:           0 :         if (failed == 2)
     539                 :             :         {
     540         [ #  # ]:           0 :             TREAT_ERR(err, 3, "Number of atoms too large. V3000 counts line:");
     541                 :             :         }
     542                 :             :         else
     543                 :             :         {
     544                 :             :             /* too long input file line or other value min-max range mismatch */
     545         [ #  # ]:           0 :             TREAT_ERR(err, 3, "Cannot interpret V3000 counts line:");
     546                 :             :         }
     547                 :           0 :         dotify_non_printable_chars(line);
     548                 :           0 :         AddErrorMessage(pStrErr, line);
     549                 :           0 :         goto err_fin;
     550                 :             :     }
     551                 :             : 
     552                 :          48 : err_fin:
     553                 :          48 :     inchi_strbuf_close(pin);
     554                 :             : 
     555                 :          48 :     return err;
     556                 :             : }
     557                 :             : 
     558                 :             : /****************************************************************************
     559                 :             :  Read V3000 SGroup
     560                 :             : ****************************************************************************/
     561                 :           0 : int MolfileV3000ReadSGroup(MOL_FMT_CTAB *ctab,
     562                 :             :                            INCHI_IOSTREAM *inp_file,
     563                 :             :                            int err,
     564                 :             :                            char *pStrErr)
     565                 :             : {
     566                 :             :     int nc;
     567                 :           0 :     char *p = NULL, *line = NULL;
     568                 :             :     INCHI_IOSTREAM tmpin;
     569                 :           0 :     INCHI_IOS_STRING *pin = &tmpin.s;
     570                 :             : 
     571                 :           0 :     inchi_ios_init(&tmpin, INCHI_IOS_TYPE_STRING, NULL);
     572                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     573                 :             : 
     574                 :             :     while (1)
     575                 :             :     {
     576                 :           0 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     577                 :             : 
     578         [ #  # ]:           0 :         if (nc < 1)
     579                 :             :         {
     580                 :           0 :             p = NULL;
     581                 :             :         }
     582                 :             :         else
     583                 :             :         {
     584                 :           0 :             p = line = pin->pStr;
     585                 :           0 :             remove_one_lf(line);
     586                 :             :         }
     587   [ #  #  #  # ]:           0 :         if (p && !strcmp(p, "END SGROUP"))
     588                 :             :         {
     589                 :           0 :             inchi_ios_close(&tmpin); /* ricrogz: fixing memory leak */
     590                 :           0 :             return 0;
     591                 :             :         }
     592                 :             :     }
     593                 :             : 
     594                 :             :     /* if (  !p  || strcmp(p, "END SGROUP") ) */
     595                 :             :     {
     596                 :             :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Error: No V3000 SGroup end marker");
     597                 :             :     }
     598                 :             : 
     599                 :             : err_fin:
     600                 :             : 
     601                 :             :     inchi_ios_close(&tmpin); /* ricrogz: fixing memory leak */
     602                 :             :     return err;
     603                 :             : }
     604                 :             : 
     605                 :             : /****************************************************************************
     606                 :             :  Read V3000 3DBlock
     607                 :             : ****************************************************************************/
     608                 :           0 : int MolfileV3000Read3DBlock(MOL_FMT_CTAB *ctab,
     609                 :             :                             INCHI_IOSTREAM *inp_file,
     610                 :             :                             int err,
     611                 :             :                             char *pStrErr)
     612                 :             : {
     613                 :             :     int nc;
     614                 :           0 :     char *p = NULL, *line = NULL;
     615                 :             :     INCHI_IOSTREAM tmpin;
     616                 :           0 :     INCHI_IOS_STRING *pin = &tmpin.s;
     617                 :           0 :     inchi_ios_init(&tmpin, INCHI_IOS_TYPE_STRING, NULL);
     618                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     619                 :             : 
     620                 :           0 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     621                 :             : 
     622         [ #  # ]:           0 :     if (nc < 1)
     623                 :             :     {
     624                 :           0 :         p = NULL;
     625                 :             :     }
     626                 :             :     else
     627                 :             :     {
     628                 :           0 :         p = line = pin->pStr;
     629                 :             :     }
     630                 :           0 :     remove_one_lf(line);
     631                 :             : 
     632   [ #  #  #  # ]:           0 :     if (!p || strcmp(p, "END OBJ3D"))
     633                 :             :     {
     634         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Error: No V3000 3DBlock end marker");
     635                 :             :     }
     636                 :           0 :     goto err_fin;
     637                 :             : 
     638                 :           0 : err_fin:
     639                 :             : 
     640                 :           0 :     inchi_ios_close(&tmpin); /* ricrogz: fixing memory leak */
     641                 :           0 :     return err;
     642                 :             : }
     643                 :             : 
     644                 :             : /****************************************************************************
     645                 :             :  Read V3000 collections
     646                 :             : ****************************************************************************/
     647                 :          37 : int MolfileV3000ReadCollections(MOL_FMT_CTAB *ctab,
     648                 :             :                                 INCHI_IOSTREAM *inp_file,
     649                 :             :                                 int err,
     650                 :             :                                 char *pStrErr)
     651                 :             : {
     652                 :             :     char field[MOL_FMT_V3000_MAXFIELDLEN];
     653                 :          37 :     const int max_field_len = sizeof(field);
     654                 :          37 :     int nread, len, n_coll = 0;
     655                 :          37 :     int failed = 0;
     656                 :             :     int nc;
     657                 :          37 :     char *p = NULL, *line = NULL;
     658                 :             :     INCHI_IOSTREAM tmpin;
     659                 :          37 :     INCHI_IOS_STRING *pin = &tmpin.s;
     660                 :             : 
     661                 :          37 :     inchi_ios_init(&tmpin, INCHI_IOS_TYPE_STRING, NULL);
     662                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     663                 :             : 
     664                 :          37 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     665                 :             : 
     666         [ -  + ]:          37 :     if (nc < 1)
     667                 :             :     {
     668                 :           0 :         p = NULL;
     669                 :             :     }
     670                 :             :     else
     671                 :             :     {
     672                 :          37 :         p = line = pin->pStr;
     673                 :             :     }
     674                 :          37 :     remove_one_lf(line);
     675                 :             : 
     676   [ +  -  +  + ]:         138 :     while (p && strcmp(p, "END COLLECTION"))
     677                 :             :     {
     678                 :         101 :         int stereo_kind = MOL_FMT_V3000_STENON;
     679                 :             :         /* stereo collection of interest */
     680                 :         101 :         NUM_LISTS *ste_coll = NULL;
     681                 :             : 
     682                 :         101 :         nread = read_upto_delim(&p, field, max_field_len, "/");
     683         [ -  + ]:         101 :         if (nread < 6)
     684                 :             :         {
     685                 :           0 :             failed = 1;
     686                 :           0 :             break;
     687                 :             :         }
     688         [ -  + ]:         101 :         if (strcmp(field, "MDLV30"))
     689                 :             :         {
     690                 :           0 :             failed = 1;
     691                 :           0 :             break;
     692                 :             :         }
     693                 :             : 
     694                 :         101 :         nread = read_upto_delim(&p, field, max_field_len, "1234567890 \t\n\v\f\r"); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     695         [ +  + ]:         101 :         if (!strcmp(field, "/STEABS"))
     696                 :             :         {
     697                 :          23 :             n_coll = 1;
     698                 :          23 :             stereo_kind = MOL_FMT_V3000_STEABS;
     699                 :          23 :             ste_coll = ctab->v3000->steabs;
     700                 :             :         }
     701         [ +  + ]:          78 :         else if (!strcmp(field, "/STEREL"))
     702                 :             :         {
     703                 :             :             /* get number of collection */
     704         [ -  + ]:          31 :             if (0 > MolfileV3000ReadField(&n_coll, MOL_FMT_CHAR_INT_DATA, &p))
     705                 :             :             {
     706                 :           0 :                 failed = 1;
     707                 :           0 :                 break;
     708                 :             :             }
     709                 :          31 :             stereo_kind = MOL_FMT_V3000_STEREL;
     710                 :          31 :             ste_coll = ctab->v3000->sterel;
     711                 :             :         }
     712         [ +  - ]:          47 :         else if (!strcmp(field, "/STERAC"))
     713                 :             :         {
     714                 :             :             /* get number of collection */
     715         [ -  + ]:          47 :             if (0 > MolfileV3000ReadField(&n_coll, MOL_FMT_CHAR_INT_DATA, &p))
     716                 :             :             {
     717                 :           0 :                 failed = 1;
     718                 :           0 :                 break;
     719                 :             :             }
     720                 :          47 :             stereo_kind = MOL_FMT_V3000_STERAC;
     721                 :          47 :             ste_coll = ctab->v3000->sterac;
     722                 :             :         }
     723                 :             :         else
     724                 :             :         {
     725                 :             :             ;
     726                 :             :         }
     727                 :             : 
     728         [ +  - ]:         101 :         if (stereo_kind != MOL_FMT_V3000_STENON)
     729                 :             :         /* currently skip non-stereo collections */
     730                 :             :         {
     731                 :             :             /* consume atoms= */
     732         [ +  - ]:         101 :             if ((len = MolfileV3000ReadKeyword(field, &p) > 0)) /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
     733                 :             :             {
     734         [ +  - ]:         101 :                 if (!strcmp(field, "ATOMS"))
     735                 :             :                 {
     736                 :         101 :                     int res, *num_list = NULL;
     737                 :             : 
     738         [ -  + ]:         101 :                     if (0 > MolfileV3000ReadStereoCollection(ctab, &p, &num_list, pStrErr))
     739                 :             :                     {
     740                 :           0 :                         failed = 1;
     741                 :             :                     }
     742         [ -  + ]:         101 :                     else if (!num_list)
     743                 :             :                     {
     744                 :           0 :                         failed = 1;
     745                 :             :                     }
     746                 :             :                     else
     747                 :             :                     {
     748                 :             :                         int k, nnum;
     749                 :         101 :                         num_list[0] = n_coll;
     750                 :         101 :                         nnum = num_list[1];
     751         [ +  + ]:         125 :                         for (k = 2; k < nnum; k++)
     752                 :             :                         {
     753                 :          24 :                             num_list[k] =
     754                 :          24 :                                 get_actual_atom_number(num_list[k],
     755                 :          24 :                                                        ctab->v3000->n_non_star_atoms + ctab->v3000->n_star_atoms,
     756                 :          24 :                                                        ctab->v3000->atom_index_orig,
     757                 :          24 :                                                        ctab->v3000->atom_index_fin);
     758                 :             :                         }
     759                 :         101 :                         res = NumLists_Append(ste_coll, num_list);
     760         [ -  + ]:         101 :                         if (res < 0)
     761                 :             :                         {
     762                 :           0 :                             failed = 1;
     763                 :             :                         }
     764                 :             :                         else
     765                 :             :                         {
     766         [ +  + ]:         101 :                             if (stereo_kind == MOL_FMT_V3000_STEABS)
     767                 :             :                             {
     768                 :          23 :                                 ctab->v3000->n_steabs++;
     769                 :          23 :                                 ctab->v3000->n_collections++;
     770                 :             :                             }
     771         [ +  + ]:          78 :                             else if (stereo_kind == MOL_FMT_V3000_STEREL)
     772                 :             :                             {
     773                 :          31 :                                 ctab->v3000->n_sterel++;
     774                 :          31 :                                 ctab->v3000->n_collections++;
     775                 :             :                             }
     776         [ +  - ]:          47 :                             else if (stereo_kind == MOL_FMT_V3000_STERAC)
     777                 :             :                             {
     778                 :          47 :                                 ctab->v3000->n_sterac++;
     779                 :          47 :                                 ctab->v3000->n_collections++;
     780                 :             :                             }
     781                 :             :                         }
     782                 :             :                     }
     783                 :             :                 }
     784                 :             :             }
     785                 :             :             else
     786                 :             :             {
     787                 :           0 :                 failed = 1;
     788                 :           0 :                 break;
     789                 :             :             }
     790                 :             :         }
     791                 :             : 
     792                 :             :         /*next_line:*/
     793                 :             :         /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     794                 :         101 :         inchi_strbuf_reset(pin);
     795                 :             : 
     796                 :         101 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     797                 :             : 
     798         [ -  + ]:         101 :         if (nc < 1)
     799                 :             :         {
     800                 :           0 :             p = NULL;
     801                 :             :         }
     802                 :             :         else
     803                 :             :         {
     804                 :         101 :             p = line = pin->pStr;
     805                 :         101 :             remove_one_lf(line);
     806                 :             :         }
     807                 :             :     }
     808                 :             : 
     809         [ -  + ]:          37 :     if (failed)
     810                 :             :     {
     811                 :             :         /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     812                 :           0 :         inchi_strbuf_reset(pin);
     813                 :           0 :         line = NULL; /* Reset line pointer since buffer was freed */
     814                 :             : 
     815                 :           0 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     816                 :             : 
     817         [ #  # ]:           0 :         if (nc < 1)
     818                 :             :         {
     819                 :           0 :             p = NULL;
     820                 :             :         }
     821                 :             :         else
     822                 :             :         {
     823                 :           0 :             p = line = pin->pStr;
     824                 :           0 :             remove_one_lf(line);
     825                 :             :         }
     826                 :             :     }
     827                 :             : 
     828         [ -  + ]:          37 :     if (!p)
     829                 :             :     {
     830                 :           0 :         failed = 1;
     831                 :             :     }
     832                 :             : 
     833         [ +  - ]:          37 :     if (failed)
     834                 :             :     {
     835                 :           0 :         err = 7;
     836         [ #  # ]:           0 :         TREAT_ERR(err, 7, "Cannot interpret V3000 collection line(s)"); /* djb-rwth: addressing coverity ID #499531 -- TREAT_ERR properly used */
     837         [ #  # ]:           0 :         if (line)
     838                 :             :         {
     839                 :           0 :             dotify_non_printable_chars(line);
     840                 :           0 :             AddErrorMessage(pStrErr, line);
     841                 :             :         }
     842                 :           0 :         goto err_fin;
     843                 :             :     }
     844                 :             : 
     845                 :             :     // /* Error: No V3000 Collection end marker */
     846                 :             :     // if (ctab->v3000->n_steabs ||
     847                 :             :     //     ctab->v3000->n_sterel ||
     848                 :             :     //     ctab->v3000->n_sterac)
     849                 :             :     // {
     850                 :             :     //     AddErrorMessage(pStrErr, "V3000 enhanced stereo read/stored but ignored");
     851                 :             :     // }
     852                 :             : 
     853                 :          37 : err_fin:
     854                 :             : 
     855                 :          37 :     inchi_ios_close(&tmpin); /* ricrogz: fixing memory leak */
     856                 :          37 :     return err;
     857                 :             : }
     858                 :             : 
     859                 :             : /****************************************************************************
     860                 :             :  Read V3000 atoms
     861                 :             : ****************************************************************************/
     862                 :          48 : int MolfileV3000ReadAtomsBlock(MOL_FMT_CTAB *ctab,
     863                 :             :                                INCHI_IOSTREAM *inp_file,
     864                 :             :                                int err,
     865                 :             :                                char *pStrErr)
     866                 :             : {
     867                 :             :     int i;
     868                 :             :     /* djb-rwth: removing redundant variables */
     869                 :             :     char field[MOL_FMT_V3000_MAXFIELDLEN];
     870                 :          48 :     int nc, failed = 0;
     871                 :          48 :     char *p = NULL, *line = NULL;
     872                 :             :     INCHI_IOSTREAM tmpin;
     873                 :          48 :     INCHI_IOS_STRING *pin = &tmpin.s;
     874                 :          48 :     inchi_ios_init(&tmpin, INCHI_IOS_TYPE_STRING, NULL);
     875                 :             : 
     876                 :             :     /* Check for proper start */
     877                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     878                 :             : 
     879                 :          48 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     880                 :             : 
     881         [ -  + ]:          48 :     if (nc < 1)
     882                 :             :     {
     883                 :           0 :         p = NULL;
     884                 :             :     }
     885                 :             :     else
     886                 :             :     {
     887                 :          48 :         p = line = pin->pStr;
     888                 :             :     }
     889   [ +  -  -  + ]:          48 :     if (!p || strcmp(p, "BEGIN ATOM"))
     890                 :             :     {
     891         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Error: No V3000 Atom block start marker");
     892                 :             :     }
     893                 :          48 :     remove_one_lf(line);
     894                 :             : 
     895                 :          48 :     ctab->v3000->n_non_star_atoms = 0;
     896         [ +  + ]:         635 :     for (i = 0; i < ctab->n_atoms; i++)
     897                 :             :     {
     898                 :         587 :         int ii = -1;
     899                 :             : 
     900                 :             :         /*p = inchi_fgetsLf_V3000( line, inp_file );*/
     901                 :         587 :         inchi_strbuf_reset(pin);
     902                 :             : 
     903                 :         587 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
     904                 :             : 
     905         [ -  + ]:         587 :         if (nc < 1)
     906                 :             :         {
     907                 :           0 :             p = NULL;
     908                 :             :         }
     909                 :             :         else
     910                 :             :         {
     911                 :         587 :             p = line = pin->pStr;
     912                 :             :         }
     913         [ -  + ]:         587 :         if (!p)
     914                 :             :         {
     915         [ #  # ]:           0 :             if (!err)
     916                 :             :             {
     917         [ #  # ]:           0 :                 TREAT_ERR(err, 2, "Cannot read V3000 atom block line");
     918                 :             :             }
     919                 :           0 :             break;
     920                 :             :         }
     921                 :         587 :         remove_one_lf(line);
     922                 :             : 
     923         [ -  + ]:         587 :         if (err)
     924                 :             :         {
     925         [ #  # ]:           0 :             if (!strcmp(line, SD_FMT_END_OF_DATA))
     926                 :             :             {
     927                 :           0 :                 err = -abs(err);
     928                 :           0 :                 break;
     929                 :             :             }
     930                 :           0 :             continue; /* bypass the rest of the Atom block */
     931                 :             :         }
     932                 :             : 
     933         [ +  - ]:         587 :         if (ctab->atoms)
     934                 :             :         {
     935                 :             :             int index, aamap; /* not used actually, just read them */
     936                 :             :             int len;
     937                 :             :             char symbol[6]; /* TODO: treat possibly long V3000 atom names */
     938                 :         587 :             double fx = 0.0, fy = 0.0, fz = 0.0;
     939                 :             : #ifdef GHI100_FIX
     940                 :             : #if (SPRINTF_FLAG == 2)
     941                 :             :             char *fxs, *fys, *fzs;
     942                 :             :             int rfxs, rfys, rfzs;
     943                 :             : 
     944                 :             :             fxs = (char *)inchi_malloc((10 + 3) * sizeof(double));
     945                 :             :             fys = (char *)inchi_malloc((10 + 3) * sizeof(double));
     946                 :             :             fzs = (char *)inchi_malloc((10 + 3) * sizeof(double));
     947                 :             : 
     948                 :             :             if (fxs || fys || fzs)
     949                 :             :             {
     950                 :             :                 failed = 1;
     951                 :             :             }
     952                 :             : #endif
     953                 :             : #endif
     954                 :         587 :             symbol[0] = '\0'; /* djb-rwth: adding zero termination */
     955                 :             : 
     956                 :             :             /* Read positional parameters */
     957                 :         587 :             failed = 0;
     958                 :             : 
     959         [ -  + ]:         587 :             if (0 > MolfileV3000ReadField(&index, MOL_FMT_INT_DATA, &p))
     960                 :             :             {
     961                 :           0 :                 failed = 1;
     962                 :             :             }
     963         [ -  + ]:         587 :             else if (0 > MolfileV3000ReadField(&symbol, MOL_FMT_STRING_DATA, &p))
     964                 :             :             {
     965                 :           0 :                 failed = 1;
     966                 :             :             }
     967         [ -  + ]:         587 :             else if (0 > MolfileV3000ReadField(&fx, MOL_FMT_DOUBLE_DATA, &p))
     968                 :             :             {
     969                 :           0 :                 failed = 1;
     970                 :             :             }
     971         [ -  + ]:         587 :             else if (0 > MolfileV3000ReadField(&fy, MOL_FMT_DOUBLE_DATA, &p))
     972                 :             :             {
     973                 :           0 :                 failed = 1;
     974                 :             :             }
     975         [ -  + ]:         587 :             else if (0 > MolfileV3000ReadField(&fz, MOL_FMT_DOUBLE_DATA, &p))
     976                 :             :             {
     977                 :           0 :                 failed = 1;
     978                 :             :             }
     979         [ -  + ]:         587 :             else if (0 > MolfileV3000ReadField(&aamap, MOL_FMT_INT_DATA, &p))
     980                 :             :             {
     981                 :           0 :                 failed = 1;
     982                 :             :             }
     983                 :             : 
     984         [ -  + ]:         587 :             if (failed)
     985                 :             :             {
     986                 :             : 
     987                 :           0 :                 err = 4;
     988         [ #  # ]:           0 :                 TREAT_ERR(err, 4, "Cannot interpret V3000 atom block line:"); /* djb-rwth: addressing coverity ID #499547 -- TREAT_ERR properly used */
     989                 :           0 :                 dotify_non_printable_chars(line);
     990                 :           0 :                 AddErrorMessage(pStrErr, line);
     991                 :             : 
     992         [ #  # ]:           0 :                 if (!strcmp(line, SD_FMT_END_OF_DATA))
     993                 :             :                 {
     994                 :           0 :                     err = -abs(err);
     995                 :           0 :                     break;
     996                 :             :                 }
     997                 :           3 :                 continue; /* can't interpret a first half of atom block line */
     998                 :             :             }
     999                 :             : 
    1000                 :             :             /* emulate V2000 coordinates substring */
    1001         [ +  - ]:         587 :             if (ctab->coords)
    1002                 :             :             {
    1003                 :             :                 char szcoords[40];
    1004                 :             : #ifdef GHI100_FIX
    1005                 :             : #if (SPRINTF_FLAG == 2)
    1006                 :             :                 if (fxs)
    1007                 :             :                 {
    1008                 :             :                     rfxs = dbl2int(fxs, 10, -1, 'g', fx);
    1009                 :             :                 }
    1010                 :             :                 if (fys)
    1011                 :             :                 {
    1012                 :             :                     rfys = dbl2int(fys, 10, -1, 'g', fy);
    1013                 :             :                 }
    1014                 :             :                 if (fzs)
    1015                 :             :                 {
    1016                 :             :                     rfzs = dbl2int(fzs, 10, -1, 'g', fz);
    1017                 :             :                 }
    1018                 :             :                 if ((rfxs >= 0) && (rfys >= 0) && (rfzs >= 0))
    1019                 :             :                 {
    1020                 :             :                     sprintf(szcoords, "%s%s%s", fxs, fys, fzs);
    1021                 :             :                 }
    1022                 :             :                 else
    1023                 :             :                 {
    1024                 :             :                     failed = 1;
    1025                 :             :                 }
    1026                 :             :                 inchi_free(fxs);
    1027                 :             :                 inchi_free(fys);
    1028                 :             :                 inchi_free(fzs);
    1029                 :             : #elif (SPRINTF_FLAG == 2)
    1030                 :             :                 stbsp_sprintf(szcoords, "%10g%10g%10g", fx, fy, fz);
    1031                 :             : #else
    1032                 :             :                 sprintf(szcoords, "%10g%10g%10g", fx, fy, fz);
    1033                 :             : #endif
    1034                 :             : #endif
    1035                 :         587 :                 sprintf(szcoords, "%10g%10g%10g", fx, fy, fz);
    1036                 :         587 :                 strcpy(ctab->coords[i], szcoords);
    1037                 :             :             }
    1038                 :             : 
    1039         [ +  + ]:         587 :             if (!strcmp(symbol, "*"))
    1040                 :             :             {
    1041                 :             :                 /* ignore star atoms but save index info */
    1042                 :           3 :                 ctab->v3000->atom_index_orig[i] = index;
    1043                 :           3 :                 ctab->v3000->atom_index_fin[i] = -1;
    1044                 :           3 :                 ctab->v3000->n_star_atoms++;
    1045                 :           3 :                 continue;
    1046                 :             :             }
    1047                 :             : 
    1048                 :         584 :             ctab->v3000->n_non_star_atoms++;
    1049                 :         584 :             ctab->v3000->atom_index_orig[i] = index;
    1050                 :         584 :             ctab->v3000->atom_index_fin[i] = ctab->v3000->n_non_star_atoms;
    1051                 :         584 :             ii = ctab->v3000->n_non_star_atoms - 1;
    1052                 :             : 
    1053                 :         584 :             mystrncpy(ctab->atoms[ii].symbol, symbol, sizeof(ctab->atoms[ii].symbol));
    1054   [ +  +  -  + ]:         584 :             if (2 == strlen(ctab->atoms[ii].symbol) && isupper(UCINT ctab->atoms[ii].symbol[1]))
    1055                 :             :             {
    1056                 :           0 :                 ctab->atoms[ii].symbol[1] = (char)tolower(UCINT ctab->atoms[ii].symbol[1]); /* 5-4-99 DCh*/
    1057                 :             :             }
    1058                 :         584 :             ctab->atoms[ii].fx = fx;
    1059                 :         584 :             ctab->atoms[ii].fy = fy;
    1060                 :         584 :             ctab->atoms[ii].fz = fz;
    1061                 :             : 
    1062                 :             :             /* Read key-val pairs if any */
    1063   [ +  +  +  - ]:         697 :             while (p && (len = MolfileV3000ReadKeyword(field, &p)) > 0) /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1064                 :             :             {
    1065                 :             : 
    1066                 :             :                 int itmp;
    1067                 :             :                 char ctmp;
    1068                 :             :                 char stmp[MOL_FMT_V3000_MAXFIELDLEN];
    1069                 :             : 
    1070                 :         113 :                 failed = 0;
    1071         [ +  + ]:         113 :                 if (!strcmp(field, "CHG"))
    1072                 :             :                 {
    1073         [ -  + ]:           3 :                     if (0 > MolfileV3000ReadField(&ctab->atoms[ii].charge, MOL_FMT_CHAR_INT_DATA, &p))
    1074                 :             :                     {
    1075                 :           0 :                         failed = 1;
    1076                 :             :                     }
    1077                 :             :                 }
    1078         [ -  + ]:         110 :                 else if (!strcmp(field, "RAD"))
    1079                 :             :                 {
    1080         [ #  # ]:           0 :                     if (0 > MolfileV3000ReadField(&ctab->atoms[ii].radical, MOL_FMT_CHAR_INT_DATA, &p))
    1081                 :             :                     {
    1082                 :           0 :                         failed = 1;
    1083                 :             :                     }
    1084                 :             :                 }
    1085         [ +  - ]:         110 :                 else if (!strcmp(field, "CFG"))
    1086                 :             :                 {
    1087         [ -  + ]:         110 :                     if (0 > MolfileV3000ReadField(&ctab->atoms[ii].stereo_parity, MOL_FMT_CHAR_INT_DATA, &p))
    1088                 :             :                     {
    1089                 :           0 :                         failed = 1;
    1090                 :             :                     }
    1091                 :             :                 }
    1092                 :             : 
    1093         [ #  # ]:           0 :                 else if (!strcmp(field, "MASS"))
    1094                 :             :                 {
    1095                 :             :                     /*
    1096                 :             :                         Default = natural abundance
    1097                 :             :                         A specified value indicates the absolute
    1098                 :             :                         atomic weight of the designated atom.
    1099                 :             :                     */
    1100                 :             :                     S_SHORT iso_mass;
    1101         [ #  # ]:           0 :                     if (0 > MolfileV3000ReadField(&iso_mass, MOL_FMT_SHORT_INT_DATA, &p))
    1102                 :             :                     {
    1103                 :           0 :                         failed = 1;
    1104                 :           0 :                         TREAT_ERR(err, 0, "Isotopic data not recognized:");
    1105                 :           0 :                         AddErrorMessage(pStrErr, line);
    1106                 :             :                         /* ignore isotopic error for now */
    1107                 :             :                     }
    1108                 :             :                     else
    1109                 :             :                     {
    1110                 :             :                         /*  What we read is an absolute isotopic mass, by V3000 spec.
    1111                 :             :                             Adjust this to old convention for further processing:
    1112                 :             :                             set 'ctab->atoms[ii].mass_difference' to 127
    1113                 :             :                             if isotopic mass is the same as element mass
    1114                 :             :                             in Periodic Table (rounded avg by all isotopes), 'atw'
    1115                 :             :                             delta otherwise, the value of difference 'delta' = ( isotopic mass - 'atw')
    1116                 :             :                         */
    1117                 :             :                         int atw, delta;
    1118                 :           0 :                         atw = get_atomic_mass(ctab->atoms[ii].symbol);
    1119                 :           0 :                         delta = (int)iso_mass - atw;
    1120         [ #  # ]:           0 :                         ctab->atoms[ii].mass_difference = (char)(delta ? delta : ZERO_ATW_DIFF);
    1121                 :             :                     }
    1122                 :             :                 }
    1123                 :             : 
    1124         [ #  # ]:           0 :                 else if (!strcmp(field, "VAL"))
    1125                 :             :                 {
    1126         [ #  # ]:           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1127                 :             :                     {
    1128                 :           0 :                         failed = 1;
    1129                 :             :                     }
    1130                 :             :                     else
    1131                 :             :                     {
    1132                 :             :                         /* adjust to old convention: was 15 for zero, now -1 for zero */
    1133         [ #  # ]:           0 :                         if (itmp == -1)
    1134                 :             :                         {
    1135                 :           0 :                             ctmp = 15;
    1136                 :             :                         }
    1137                 :             :                         else
    1138                 :             :                         {
    1139                 :           0 :                             ctmp = (char)itmp;
    1140                 :             :                         }
    1141                 :           0 :                         ctab->atoms[ii].valence = ctmp;
    1142                 :             :                     }
    1143                 :             :                 }
    1144         [ #  # ]:           0 :                 else if (!strcmp(field, "HCOUNT"))
    1145                 :             :                 {
    1146                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1147                 :             :                     {
    1148                 :             :                         ; /* skip query-related stuff */
    1149                 :             :                     }
    1150                 :             :                 }
    1151         [ #  # ]:           0 :                 else if (!strcmp(field, "STBOX"))
    1152                 :             :                 {
    1153                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1154                 :             :                     {
    1155                 :             :                         ; /* skip for now */
    1156                 :             :                     }
    1157                 :             :                 }
    1158   [ #  #  #  # ]:           0 :                 else if (!strcmp(field, "INVRET") || !strcmp(field, "EXACHG"))
    1159                 :             :                 {
    1160                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1161                 :             :                     {
    1162                 :             :                         ; /* skip reaction-related stuff */
    1163                 :             :                     }
    1164                 :             :                 }
    1165   [ #  #  #  #  :           0 :                 else if (!strcmp(field, "SUBST") || !strcmp(field, "UNSAT") || !strcmp(field, "RBCNT"))
                   #  # ]
    1166                 :             :                 {
    1167                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1168                 :             :                     {
    1169                 :             :                         ; /* skip query-related stuff */
    1170                 :             :                     }
    1171                 :             :                 }
    1172         [ #  # ]:           0 :                 else if (!strcmp(field, "ATTCHPT"))
    1173                 :             :                 {
    1174                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1175                 :             :                     {
    1176                 :             :                         ;
    1177                 :             :                     }
    1178                 :             :                 }
    1179         [ #  # ]:           0 :                 else if (!strcmp(field, "RGROUPS"))
    1180                 :             :                 {
    1181                 :           0 :                     if (0 > MolfileV3000ReadField(&stmp, MOL_FMT_STRING_DATA, &p))
    1182                 :             :                     {
    1183                 :             :                         ;
    1184                 :             :                     }
    1185                 :             :                 }
    1186         [ #  # ]:           0 :                 else if (!strcmp(field, "ATTCHORD"))
    1187                 :             :                 {
    1188                 :           0 :                     if (0 > MolfileV3000ReadField(&stmp, MOL_FMT_STRING_DATA, &p))
    1189                 :             :                     {
    1190                 :             :                         ;
    1191                 :             :                     }
    1192                 :             :                 }
    1193         [ #  # ]:           0 :                 else if (!strcmp(field, "CLASS"))
    1194                 :             :                 {
    1195                 :           0 :                     if (0 > MolfileV3000ReadField(&stmp, MOL_FMT_STRING_DATA, &p))
    1196                 :             :                     {
    1197                 :             :                         ;
    1198                 :             :                     }
    1199                 :             :                 }
    1200         [ #  # ]:           0 :                 else if (!strcmp(field, "SEQID"))
    1201                 :             :                 {
    1202                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1203                 :             :                     {
    1204                 :             :                         ;
    1205                 :             :                     }
    1206                 :             :                 }
    1207                 :             : 
    1208         [ -  + ]:         113 :                 if (failed)
    1209                 :             :                 {
    1210                 :           0 :                     err = 4;
    1211         [ #  # ]:           0 :                     TREAT_ERR(err, 4, "Cannot interpret V3000 atom block key-value pair");
    1212                 :           0 :                     dotify_non_printable_chars(line);
    1213                 :           0 :                     AddErrorMessage(pStrErr, line);
    1214                 :             : 
    1215         [ #  # ]:           0 :                     if (!strcmp(line, SD_FMT_END_OF_DATA))
    1216                 :             :                     {
    1217                 :           0 :                         err = -abs(err);
    1218                 :           0 :                         break;
    1219                 :             :                     }
    1220                 :           0 :                     continue;
    1221                 :             :                 }
    1222                 :             :             }
    1223                 :             :         } /* if ( NULL != ctab->atoms )  */
    1224                 :             :     } /* for ( i = 0; i < ctab->n_atoms; i++ )  */
    1225                 :             : 
    1226         [ +  + ]:          48 :     if (ctab->v3000->n_star_atoms)
    1227                 :             :     {
    1228                 :           2 :         AddErrorMessage(pStrErr, "V3000 star atoms ignored if MolecularInorganics or NPZz parameter not used");        /* @nnuk : when using /MolecularInorganics or /NPZz, star atoms will not be ignored */
    1229                 :           2 :         ctab->n_atoms = ctab->v3000->n_non_star_atoms;
    1230                 :             :     }
    1231                 :             : 
    1232                 :             :     /* Check for proper finish */
    1233                 :             : 
    1234                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1235                 :          48 :     inchi_strbuf_reset(pin);
    1236                 :             : 
    1237                 :          48 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1238                 :             : 
    1239         [ -  + ]:          48 :     if (nc < 1)
    1240                 :             :     {
    1241                 :           0 :         p = NULL;
    1242                 :             :     }
    1243                 :             :     else
    1244                 :             :     {
    1245                 :          48 :         p = line = pin->pStr;
    1246                 :             :     }
    1247   [ +  -  -  + ]:          48 :     if (!p || strcmp(p, "END ATOM"))
    1248                 :             :     {
    1249         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Error: No V3000 Atom block end marker");
    1250                 :             :     }
    1251                 :          48 :     remove_one_lf(line);
    1252                 :             : 
    1253                 :          48 : err_fin:
    1254                 :          48 :     inchi_strbuf_close(pin);
    1255                 :             : 
    1256                 :          48 :     return err;
    1257                 :             : }
    1258                 :             : 
    1259                 :             : /****************************************************************************
    1260                 :             :  Read V3000 bonds
    1261                 :             : ****************************************************************************/
    1262                 :          48 : int MolfileV3000ReadBondsBlock(MOL_FMT_CTAB *ctab,
    1263                 :             :                                INCHI_IOSTREAM *inp_file,
    1264                 :             :                                int err,
    1265                 :             :                                char *pStrErr)
    1266                 :             : {
    1267                 :             :     int i;
    1268                 :             :     char field[MOL_FMT_V3000_MAXFIELDLEN];
    1269                 :             :     int nc;
    1270                 :          48 :     char *p = NULL, *line = NULL;
    1271                 :             :     INCHI_IOSTREAM tmpin;
    1272                 :          48 :     INCHI_IOS_STRING *pin = &tmpin.s;
    1273                 :             : 
    1274         [ -  + ]:          48 :     if (!ctab->n_bonds)
    1275                 :             :     {
    1276                 :           0 :         return 0;
    1277                 :             :     }
    1278                 :          48 :     inchi_ios_init(&tmpin, INCHI_IOS_TYPE_STRING, NULL);
    1279                 :             : 
    1280                 :             :     /* Check for proper start */
    1281                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1282                 :             : 
    1283                 :          48 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1284                 :             : 
    1285         [ -  + ]:          48 :     if (nc < 1)
    1286                 :             :     {
    1287                 :           0 :         p = NULL;
    1288                 :             :     }
    1289                 :             :     else
    1290                 :             :     {
    1291                 :          48 :         p = line = pin->pStr;
    1292                 :             :     }
    1293   [ +  -  -  + ]:          48 :     if (!p || strcmp(p, "BEGIN BOND"))
    1294                 :             :     {
    1295         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Error: No V3000 Bond block start marker");
    1296                 :             :     }
    1297                 :          48 :     remove_one_lf(line);
    1298                 :             : 
    1299                 :          48 :     ctab->v3000->n_haptic_bonds = 0;
    1300                 :          48 :     ctab->v3000->n_non_haptic_bonds = 0;
    1301                 :             : 
    1302         [ +  + ]:         590 :     for (i = 0; i < ctab->n_bonds; i++)
    1303                 :             :     {
    1304                 :         542 :         int is_haptic = 0;
    1305                 :             : 
    1306                 :             :         /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1307                 :         542 :         inchi_strbuf_reset(pin);
    1308                 :             : 
    1309                 :         542 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1310                 :             : 
    1311         [ -  + ]:         542 :         if (nc < 1)
    1312                 :             :         {
    1313                 :           0 :             p = NULL;
    1314                 :             :         }
    1315                 :             :         else
    1316                 :             :         {
    1317                 :         542 :             p = line = pin->pStr;
    1318                 :             :         }
    1319         [ -  + ]:         542 :         if (!p)
    1320                 :             :         {
    1321         [ #  # ]:           0 :             if (!err)
    1322                 :             :             {
    1323         [ #  # ]:           0 :                 TREAT_ERR(err, 2, "Cannot read V3000 bond block line"); /* djb-rwth: addressing coverity ID #499565 -- TREAT_ERR properly used */
    1324                 :             :             }
    1325                 :           0 :             break;
    1326                 :             :         }
    1327                 :         542 :         remove_one_lf(line);
    1328                 :             : 
    1329         [ -  + ]:         542 :         if (err)
    1330                 :             :         {
    1331         [ #  # ]:           0 :             if (!strcmp(line, SD_FMT_END_OF_DATA))
    1332                 :             :             {
    1333                 :           0 :                 err = -abs(err);
    1334                 :           0 :                 break;
    1335                 :             :             }
    1336                 :           0 :             continue;
    1337                 :             :         }
    1338                 :             : 
    1339         [ +  - ]:         542 :         if (ctab->bonds)
    1340                 :             :         {
    1341                 :             :             int index, n_orig_at, len;
    1342                 :         542 :             short int atnum1 = -1, atnum2 = -1;
    1343                 :         542 :             char bond_type = 0, stereo = 0;
    1344                 :         542 :             int failed = 0;
    1345                 :             :             /* djb-rwth: removing redundant variables */
    1346                 :             : 
    1347                 :         542 :             n_orig_at = ctab->v3000->n_non_star_atoms + ctab->v3000->n_star_atoms;
    1348                 :             : 
    1349                 :             :             /* read positional parameters */
    1350         [ -  + ]:         542 :             if (0 > MolfileV3000ReadField(&index, MOL_FMT_INT_DATA, &p))
    1351                 :             :             {
    1352                 :           0 :                 failed = 1;
    1353                 :             :             }
    1354         [ -  + ]:         542 :             else if (0 > MolfileV3000ReadField(&bond_type, MOL_FMT_CHAR_INT_DATA, &p))
    1355                 :             :             {
    1356                 :           0 :                 failed = 1;
    1357                 :             :             }
    1358         [ -  + ]:         542 :             else if (0 > MolfileV3000ReadField(&atnum1, MOL_FMT_SHORT_INT_DATA, &p))
    1359                 :             :             {
    1360                 :           0 :                 failed = 1;
    1361                 :             :             }
    1362         [ -  + ]:         542 :             else if (0 > MolfileV3000ReadField(&atnum2, MOL_FMT_SHORT_INT_DATA, &p))
    1363                 :             :             {
    1364                 :           0 :                 failed = 1;
    1365                 :             :             }
    1366                 :             : 
    1367                 :        1084 :             atnum1 = get_actual_atom_number(atnum1, n_orig_at,
    1368                 :         542 :                                             ctab->v3000->atom_index_orig,
    1369                 :         542 :                                             ctab->v3000->atom_index_fin);
    1370                 :             : 
    1371                 :        1084 :             atnum2 = get_actual_atom_number(atnum2, n_orig_at,
    1372                 :         542 :                                             ctab->v3000->atom_index_orig,
    1373                 :         542 :                                             ctab->v3000->atom_index_fin);
    1374                 :             : 
    1375   [ -  +  -  - ]:         542 :             if ((atnum1 < 0) && (atnum2 < 0))
    1376                 :             :             {
    1377                 :           0 :                 failed = 1;
    1378                 :             :             }
    1379                 :             :             /* djb-rwth: removing redundant code */
    1380                 :             : 
    1381         [ -  + ]:         542 :             if (failed)
    1382                 :             :             {
    1383                 :             : 
    1384         [ #  # ]:           0 :                 if (!err)
    1385                 :             :                 {
    1386                 :             :                     /* can't interpret bonds block line */
    1387         [ #  # ]:           0 :                     TREAT_ERR(err, 4, "Cannot interpret V3000 bond block line:");
    1388                 :           0 :                     dotify_non_printable_chars(line);
    1389                 :           0 :                     AddErrorMessage(pStrErr, line);
    1390                 :             :                 }
    1391         [ #  # ]:           0 :                 if (!strcmp(line, SD_FMT_END_OF_DATA))
    1392                 :             :                 {
    1393                 :           0 :                     err = -abs(err);
    1394                 :           0 :                     break;
    1395                 :             :                 }
    1396                 :             :             }
    1397                 :             : 
    1398                 :             :             /* TODO: treat new bond types  9 10 */
    1399                 :             :             /* read key-val pairs if any */
    1400   [ +  +  +  - ]:         724 :             while (p && (len = MolfileV3000ReadKeyword(field, &p)) > 0) /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1401                 :             :             {
    1402                 :             : 
    1403                 :             :                 int itmp;
    1404                 :             :                 char stmp[MOL_FMT_V3000_MAXFIELDLEN];
    1405                 :         182 :                 failed = 0;
    1406                 :             : 
    1407         [ +  + ]:         182 :                 if (!strcmp(field, "CFG"))
    1408                 :             :                 {
    1409         [ -  + ]:         179 :                     if (0 > MolfileV3000ReadField(&stereo, MOL_FMT_CHAR_INT_DATA, &p))
    1410                 :             :                     {
    1411                 :           0 :                         failed = 1;
    1412                 :             :                     }
    1413                 :             :                     else
    1414                 :             :                     {
    1415                 :             :                         /*    adjust stereo to old convention for wedges which was:
    1416                 :             :                                 0 = not stereo, 1 = Up,  4 = Either, 6 = Down
    1417                 :             :                             now:
    1418                 :             :                                 0 = none (default), 1 = up, 2 = either, 3 = down
    1419                 :             :                         */
    1420         [ -  + ]:         179 :                         if (stereo == 2)
    1421                 :             :                         {
    1422                 :           0 :                             stereo = 4;
    1423                 :             :                         }
    1424         [ +  + ]:         179 :                         else if (stereo == 3)
    1425                 :             :                         {
    1426                 :          31 :                             stereo = 6;
    1427                 :             :                         }
    1428                 :             :                     }
    1429                 :             :                 }
    1430         [ -  + ]:           3 :                 else if (!strcmp(field, "TOPO"))
    1431                 :             :                 {
    1432                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1433                 :             :                     {
    1434                 :             :                         ; /* skip query-related stuff */
    1435                 :             :                     }
    1436                 :             :                 }
    1437         [ -  + ]:           3 :                 else if (!strcmp(field, "RXCTR"))
    1438                 :             :                 {
    1439                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1440                 :             :                     {
    1441                 :             :                         ; /* skip reaction-related stuff */
    1442                 :             :                     }
    1443                 :             :                 }
    1444         [ -  + ]:           3 :                 else if (!strcmp(field, "STBOX"))
    1445                 :             :                 {
    1446                 :           0 :                     if (0 > MolfileV3000ReadField(&itmp, MOL_FMT_INT_DATA, &p))
    1447                 :             :                     {
    1448                 :             :                         ; /* skip for now */
    1449                 :             :                     }
    1450                 :             :                 }
    1451         [ +  - ]:           3 :                 else if (!strcmp(field, "ENDPTS"))
    1452                 :             :                 {
    1453                 :           3 :                     int res, *num_list = NULL;
    1454         [ -  + ]:           3 :                     if (0 > MolfileV3000ReadHapticBond(ctab, &p, &num_list, pStrErr))
    1455                 :             :                     {
    1456                 :           0 :                         failed = 1;
    1457                 :             :                     }
    1458         [ -  + ]:           3 :                     else if (!num_list)
    1459                 :             :                     {
    1460                 :           0 :                         failed = 1;
    1461                 :             :                     }
    1462                 :             :                     else
    1463                 :             :                     {
    1464                 :           3 :                         int existent_atom = atnum1;
    1465         [ -  + ]:           3 :                         if (existent_atom < 0)
    1466                 :             :                         {
    1467                 :           0 :                             existent_atom = atnum2;
    1468                 :             :                         }
    1469         [ -  + ]:           3 :                         if (existent_atom < 0) /* should not be here */
    1470                 :             :                          {
    1471                 :           0 :                             failed = 1;
    1472                 :             :                         }
    1473                 :             :                         else
    1474                 :             :                         {
    1475                 :             :                             int k, nnum;
    1476                 :           3 :                             nnum = num_list[2];
    1477                 :           3 :                             num_list[1] = existent_atom;
    1478         [ +  + ]:          15 :                             for (k = 3; k < nnum + 3; k++)              /* @nnuk : wrong mapping of endpoints (+3 added for full endpoints mapping for all haptic bonds) */
    1479                 :             :                             {
    1480                 :          12 :                                 num_list[k] = get_actual_atom_number(num_list[k],
    1481                 :             :                                                                      n_orig_at,
    1482                 :          12 :                                                                      ctab->v3000->atom_index_orig,
    1483                 :          12 :                                                                      ctab->v3000->atom_index_fin);
    1484                 :             :                             }
    1485                 :           3 :                             res = NumLists_Append(ctab->v3000->haptic_bonds, num_list);
    1486         [ -  + ]:           3 :                             if (res < 0)
    1487                 :             :                             {
    1488                 :           0 :                                 failed = 1;
    1489                 :             :                             }
    1490                 :             :                             else
    1491                 :             :                             {
    1492                 :           3 :                                 is_haptic = 1;
    1493                 :             :                             }
    1494                 :             :                         }
    1495                 :             :                     }
    1496                 :             :                     /* djb-rwth: addressing coverity ID #499489 -- false positive as num_atoms allocated in MolfileV3000ReadHapticBond and returns a value in this block */
    1497                 :             :                 }
    1498         [ #  # ]:           0 :                 else if (!strcmp(field, "DISP"))
    1499                 :             :                 {
    1500                 :           0 :                     if (0 > MolfileV3000ReadField(&stmp, MOL_FMT_STRING_DATA, &p))
    1501                 :             :                     {
    1502                 :             :                         ;
    1503                 :             :                     }
    1504                 :             :                 }
    1505         [ #  # ]:           0 :                 else if (!strcmp(field, "ATTACH"))
    1506                 :             :                 {
    1507                 :           0 :                     if (0 > MolfileV3000ReadField(&stmp, MOL_FMT_STRING_DATA, &p))
    1508                 :             :                     {
    1509                 :             :                         ;
    1510                 :             :                     }
    1511                 :             :                 }
    1512                 :             : 
    1513         [ -  + ]:         182 :                 if (failed)
    1514                 :             :                 {
    1515         [ #  # ]:           0 :                     if (!err)
    1516                 :             :                     {
    1517                 :             :                         /* can't interpret bonds block line */
    1518         [ #  # ]:           0 :                         TREAT_ERR(err, 4, "Cannot interpret V3000 bond block line:");
    1519                 :           0 :                         dotify_non_printable_chars(line);
    1520                 :           0 :                         AddErrorMessage(pStrErr, line);
    1521                 :             :                     }
    1522         [ #  # ]:           0 :                     if (!strcmp(line, SD_FMT_END_OF_DATA))
    1523                 :             :                     {
    1524                 :           0 :                         err = -abs(err);
    1525                 :           0 :                         break;
    1526                 :             :                     }
    1527                 :             :                 }
    1528                 :             :             } /* while ( p && (len=MolfileV3000ReadKeyword(field, &p)) > 0 ) */
    1529                 :             : 
    1530         [ +  + ]:         542 :             if (is_haptic)
    1531                 :           3 :             {
    1532                 :           3 :                 int ii = ctab->v3000->n_haptic_bonds;
    1533                 :           3 :                 ctab->v3000->haptic_bonds->lists[ii][0] = bond_type;
    1534                 :           3 :                 ctab->v3000->n_haptic_bonds++;
    1535                 :           3 :                 continue;
    1536                 :             :             }
    1537                 :             :             else
    1538                 :             :             {
    1539                 :         539 :                 int ii = ctab->v3000->n_non_haptic_bonds;
    1540                 :         539 :                 ctab->bonds[ii].atnum1 = atnum1;
    1541                 :         539 :                 ctab->bonds[ii].atnum2 = atnum2;
    1542                 :         539 :                 ctab->bonds[ii].bond_type = bond_type;
    1543                 :         539 :                 ctab->bonds[ii].bond_stereo = stereo;
    1544                 :         539 :                 ctab->v3000->n_non_haptic_bonds++;
    1545                 :             :             }
    1546                 :             :         } /* if ctab->bonds */
    1547                 :             :     } /* for ( i = 0; i < ctab->n_bonds; i++ )  */
    1548                 :             : 
    1549         [ +  + ]:          48 :     if (ctab->v3000->n_haptic_bonds)
    1550                 :             :     {
    1551                 :           2 :         AddErrorMessage(pStrErr, "V3000 haptic bonds read/stored and ignored if MolecularInorganics or NPZz parameter is not used");    /* @nnuk : when using /MolecularInorganics or /NPZz, haptic bonds will not be ignored */
    1552                 :           2 :         ctab->n_bonds = ctab->v3000->n_non_haptic_bonds;
    1553                 :             :     }
    1554                 :             : 
    1555                 :             :     /* Check for proper finish */
    1556                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1557                 :          48 :     inchi_strbuf_reset(pin);
    1558                 :             : 
    1559                 :          48 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1560                 :             : 
    1561         [ -  + ]:          48 :     if (nc < 1)
    1562                 :             :     {
    1563                 :           0 :         p = NULL;
    1564                 :             :     }
    1565                 :             :     else
    1566                 :             :     {
    1567                 :          48 :         p = line = pin->pStr;
    1568                 :             :     }
    1569   [ +  -  -  + ]:          48 :     if (!p || strcmp(p, "END BOND"))
    1570                 :             :     {
    1571         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Error: No V3000 Bond block end marker");
    1572                 :             :     }
    1573                 :          48 :     remove_one_lf(line);
    1574                 :             : 
    1575                 :          48 : err_fin:
    1576                 :             : 
    1577                 :          48 :     inchi_ios_close(&tmpin); /* ricrogz: fixing memory leak */
    1578                 :          48 :     return err;
    1579                 :             : }
    1580                 :             : 
    1581                 :             : /****************************************************************************
    1582                 :             :  Convert atom index to the final consequitive atom number (starting from 1)
    1583                 :             :  Returns -1 for star atom or not found index
    1584                 :             : ****************************************************************************/
    1585                 :        1120 : int get_actual_atom_number(int index, int n, int *orig, int *fin)
    1586                 :             : {
    1587                 :             :     int i;
    1588         [ +  - ]:       11958 :     for (i = 0; i < n; i++)
    1589                 :             :     {
    1590         [ +  + ]:       11958 :         if (orig[i] == index)
    1591                 :             :         {
    1592                 :        1120 :             return fin[i];
    1593                 :             :         }
    1594                 :             :     }
    1595                 :             : 
    1596                 :           0 :     return -1;
    1597                 :             : }
    1598                 :             : 
    1599                 :             : /****************************************************************************
    1600                 :             :  Read V3000 tail of CTab
    1601                 :             : ****************************************************************************/
    1602                 :          48 : int MolfileV3000ReadTailOfCTAB(MOL_FMT_CTAB *ctab,
    1603                 :             :                                INCHI_IOSTREAM *inp_file,
    1604                 :             :                                int err,
    1605                 :             :                                char *pStrErr)
    1606                 :             : {
    1607                 :          48 :     int retcode = err;
    1608                 :             :     int nc;
    1609                 :          48 :     char *p = NULL, *line = NULL;
    1610                 :             :     INCHI_IOSTREAM tmpin;
    1611                 :          48 :     INCHI_IOS_STRING *pin = &tmpin.s;
    1612                 :          48 :     inchi_ios_init(&tmpin, INCHI_IOS_TYPE_STRING, NULL);
    1613                 :             : 
    1614                 :             :     /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1615                 :             : 
    1616                 :          48 :     nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1617                 :             : 
    1618         [ -  + ]:          48 :     if (nc < 1)
    1619                 :             :     {
    1620                 :           0 :         p = NULL;
    1621                 :             :     }
    1622                 :             :     else
    1623                 :             :     {
    1624                 :          48 :         p = line = pin->pStr;
    1625                 :             :     }
    1626                 :          48 :     remove_one_lf(line);
    1627                 :             : 
    1628   [ +  -  -  + ]:          48 :     if (p && !strcmp(p, "BEGIN SGROUP"))
    1629                 :             :     {
    1630                 :           0 :         retcode = MolfileV3000ReadSGroup(ctab, inp_file, retcode, pStrErr);
    1631         [ #  # ]:           0 :         if (retcode)
    1632                 :             :         {
    1633                 :           0 :             retcode += 70;
    1634         [ #  # ]:           0 :             TREAT_ERR_AND_FIN(retcode, 1, err_fin, pStrErr);
    1635                 :             :         }
    1636                 :             :         /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1637                 :           0 :         inchi_strbuf_reset(pin);
    1638                 :           0 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1639         [ #  # ]:           0 :         if (nc < 1)
    1640                 :             :         {
    1641                 :           0 :             p = NULL;
    1642                 :             :         }
    1643                 :             :         else
    1644                 :             :         {
    1645                 :           0 :             p = line = pin->pStr;
    1646                 :           0 :             remove_one_lf(line);
    1647                 :             :         }
    1648                 :             :     }
    1649                 :             : 
    1650   [ +  -  -  + ]:          48 :     if (p && !strcmp(p, "BEGIN OBJ3D"))
    1651                 :             :     {
    1652                 :           0 :         retcode = MolfileV3000Read3DBlock(ctab, inp_file, retcode, pStrErr);
    1653         [ #  # ]:           0 :         if (retcode)
    1654                 :             :         {
    1655                 :           0 :             retcode += 70;
    1656         [ #  # ]:           0 :             TREAT_ERR_AND_FIN(retcode, 1, err_fin, pStrErr);
    1657                 :             :         }
    1658                 :             :         /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1659                 :           0 :         inchi_strbuf_reset(pin);
    1660                 :             : 
    1661                 :           0 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1662         [ #  # ]:           0 :         if (nc < 1)
    1663                 :             :         {
    1664                 :           0 :             p = NULL;
    1665                 :             :         }
    1666                 :             :         else
    1667                 :             :         {
    1668                 :           0 :             p = line = pin->pStr;
    1669                 :           0 :             remove_one_lf(line);
    1670                 :             :         }
    1671                 :             :     }
    1672                 :             : 
    1673   [ +  -  -  + ]:          48 :     while (p && !strcmp(p, "LINKNODE"))
    1674                 :             :     {
    1675                 :             :         /* skip for now */
    1676                 :             :         /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1677                 :           0 :         inchi_strbuf_reset(pin);
    1678                 :             : 
    1679                 :           0 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1680         [ #  # ]:           0 :         if (nc < 1)
    1681                 :             :         {
    1682                 :           0 :             p = NULL;
    1683                 :             :         }
    1684                 :             :         else
    1685                 :             :         {
    1686                 :           0 :             p = line = pin->pStr;
    1687                 :           0 :             remove_one_lf(line);
    1688                 :             :         }
    1689                 :             :     }
    1690                 :             : 
    1691                 :             :     /* Collections */
    1692   [ +  -  +  + ]:          85 :     while (p && !strcmp(p, "BEGIN COLLECTION"))
    1693                 :             :     {
    1694                 :          37 :         retcode = MolfileV3000ReadCollections(ctab, inp_file, retcode, pStrErr);
    1695         [ -  + ]:          37 :         if (retcode)
    1696                 :             :         {
    1697                 :           0 :             retcode += 70;
    1698         [ #  # ]:           0 :             TREAT_ERR_AND_FIN(retcode, 1, err_fin, pStrErr);
    1699                 :             :         }
    1700                 :             :         /*p = inchi_fgetsLf_V3000( line, inp_file );*/
    1701                 :          37 :         inchi_strbuf_reset(pin);
    1702                 :             : 
    1703                 :          37 :         nc = get_V3000_input_line_to_strbuf(pin, inp_file);
    1704                 :             : 
    1705         [ -  + ]:          37 :         if (nc < 1)
    1706                 :             :         {
    1707                 :           0 :             p = NULL;
    1708                 :             :         }
    1709                 :             :         else
    1710                 :             :         {
    1711                 :          37 :             p = line = pin->pStr;
    1712                 :          37 :             remove_one_lf(line);
    1713                 :             :         }
    1714                 :             :     }
    1715                 :             : 
    1716   [ +  -  -  + ]:          48 :     if (!p || strcmp(p, "END CTAB"))
    1717                 :             :     {
    1718         [ #  # ]:           0 :         TREAT_ERR_AND_FIN(err, 1, err_fin, "Error: No V3000 CTAB end marker");
    1719                 :             :     }
    1720                 :             : 
    1721                 :          48 :     remove_one_lf(line);
    1722                 :             : 
    1723                 :          48 : err_fin:
    1724                 :          48 :     inchi_strbuf_close(pin);
    1725                 :             : 
    1726                 :          48 :     return err;
    1727                 :             : }
    1728                 :             : 
    1729                 :             : /****************************************************************************
    1730                 :             :  Read haptic bond info
    1731                 :             : ****************************************************************************/
    1732                 :           3 : int MolfileV3000ReadHapticBond(MOL_FMT_CTAB *ctab,
    1733                 :             :                                char **line_ptr,
    1734                 :             :                                int **num_list,
    1735                 :             :                                char *pStrErr)
    1736                 :             : {
    1737                 :           3 :     int nread = 0;
    1738                 :             :     char field[MOL_FMT_V3000_MAXFIELDLEN];
    1739                 :           3 :     const int max_field_len = sizeof(field);
    1740                 :             :     char *p_end;
    1741                 :           3 :     int i, nnum = 0;
    1742                 :             : 
    1743                 :           3 :     *num_list = NULL;
    1744                 :             : 
    1745                 :           3 :     memset(field, 0, max_field_len); /* djb-rwth: memset_s C11/Annex K variant? */
    1746                 :             : 
    1747                 :           3 :     nread = read_upto_delim(line_ptr, field, max_field_len, "1234567890 \t\n\v\f\r"); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1748         [ -  + ]:           3 :     if (strcmp(field, "("))
    1749                 :             :     {
    1750                 :           0 :         return -1;
    1751                 :             :     }
    1752                 :             : 
    1753                 :           3 :     nread = read_upto_delim(line_ptr, field, max_field_len, " \t\n\v\f\r"); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1754                 :             : 
    1755                 :           3 :     nnum = strtol(field, &p_end, 10);
    1756                 :             : 
    1757         [ -  + ]:           3 :     if (p_end == field)
    1758                 :             :     {
    1759                 :           0 :         return -1; /* paranoia */
    1760                 :             :     }
    1761         [ -  + ]:           3 :     if (nnum < 0)
    1762                 :             :     {
    1763                 :           0 :         return -1;
    1764                 :             :     }
    1765                 :             : 
    1766                 :           3 :     *num_list = (int *)inchi_calloc((long long)nnum + 3, sizeof(int)); /* djb-rwth: cast operator added */
    1767                 :             : 
    1768         [ -  + ]:           3 :     if (!*num_list)
    1769                 :             :     {
    1770                 :           0 :         nread = -1;
    1771                 :           0 :         goto ret;
    1772                 :             :     }
    1773                 :             : 
    1774                 :           3 :     (*num_list)[0] = -1; /* will be bond type, to be filled by caller */
    1775                 :           3 :     (*num_list)[1] = -1; /* will be atom number, to be filled by caller */
    1776                 :           3 :     (*num_list)[2] = nnum;
    1777                 :             : 
    1778         [ +  + ]:          15 :     for (i = 3; i < nnum + 3; i++)
    1779                 :             :     {
    1780         [ -  + ]:          12 :         if (0 > MolfileV3000ReadField(&((*num_list)[i]), MOL_FMT_INT_DATA, line_ptr))
    1781                 :             :         {
    1782                 :           0 :             nread = -1;
    1783                 :           0 :             goto ret;
    1784                 :             :         }
    1785                 :             :     }
    1786                 :             : 
    1787                 :             :     /* ')' should have been consumed  by strtol */
    1788                 :             : 
    1789                 :             :     /* check for ATTACH=ALL */
    1790                 :             : 
    1791                 :           3 :     nread = read_upto_delim(line_ptr, field, max_field_len, " \t\n\v\f\r");
    1792         [ -  + ]:           3 :     if (nread > 0)
    1793                 :             :     {
    1794         [ +  - ]:           3 :         if (strcmp(field, "ATTACH=ALL"))
    1795                 :             :         {
    1796                 :           0 :             nread = -1;
    1797                 :           0 :             goto ret;
    1798                 :             :         }
    1799                 :             :     }
    1800                 :             : 
    1801                 :           3 : ret:
    1802         [ -  + ]:           3 :     if (nread < 0)
    1803                 :             :     {
    1804         [ #  # ]:           0 :         if (*num_list)
    1805                 :             :         {
    1806         [ #  # ]:           0 :             inchi_free(*num_list);
    1807                 :           0 :             *num_list = NULL;
    1808                 :             :         }
    1809                 :             :     }
    1810                 :             : 
    1811                 :           3 :     return nread;
    1812                 :             : }
    1813                 :             : 
    1814                 :             : /****************************************************************************
    1815                 :             :  Read V3000 stereo collection
    1816                 :             : ****************************************************************************/
    1817                 :         101 : int MolfileV3000ReadStereoCollection(MOL_FMT_CTAB *ctab,
    1818                 :             :                                      char **line_ptr,
    1819                 :             :                                      int **num_list,
    1820                 :             :                                      char *pStrErr)
    1821                 :             : {
    1822                 :         101 :     int nread = 0;
    1823                 :             :     char field[MOL_FMT_V3000_MAXFIELDLEN];
    1824                 :         101 :     const int max_field_len = sizeof(field);
    1825                 :             :     char *p_end;
    1826                 :         101 :     int i, nnum = 0;
    1827                 :             : 
    1828                 :         101 :     *num_list = NULL;
    1829                 :             : 
    1830                 :         101 :     memset(field, 0, max_field_len); /* djb-rwth: memset_s C11/Annex K variant? */
    1831                 :             : 
    1832                 :         101 :     nread = read_upto_delim(line_ptr, field, max_field_len, "1234567890 \t\n\v\f\r"); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
    1833         [ -  + ]:         101 :     if (strcmp(field, "("))
    1834                 :             :     {
    1835                 :           0 :         return -1;
    1836                 :             :     }
    1837                 :             : 
    1838                 :         101 :     nread = read_upto_delim(line_ptr, field, max_field_len, " \t\n\v\f\r");
    1839                 :             : 
    1840                 :         101 :     nnum = strtol(field, &p_end, 10);
    1841                 :             : 
    1842         [ -  + ]:         101 :     if (p_end == field)
    1843                 :             :     {
    1844                 :           0 :         return -1; /* paranoia */
    1845                 :             :     }
    1846         [ -  + ]:         101 :     if (nnum < 0)
    1847                 :             :     {
    1848                 :           0 :         return -1;
    1849                 :             :     }
    1850                 :             : 
    1851                 :         101 :     *num_list = (int *)inchi_calloc((long long)nnum + 3, sizeof(int)); /* djb-rwth: cast operator added */
    1852                 :             : 
    1853         [ -  + ]:         101 :     if (!*num_list)
    1854                 :             :     {
    1855                 :           0 :         nread = -1;
    1856                 :           0 :         goto ret;
    1857                 :             :     }
    1858                 :             : 
    1859                 :         101 :     (*num_list)[0] = -1; /* reserved, may be filled by caller */
    1860                 :         101 :     (*num_list)[1] = nnum;
    1861                 :             : 
    1862         [ +  + ]:         272 :     for (i = 2; i < nnum + 2; i++)
    1863                 :             :     {
    1864         [ -  + ]:         171 :         if (0 > MolfileV3000ReadField(&((*num_list)[i]), MOL_FMT_INT_DATA, line_ptr))
    1865                 :             :         {
    1866                 :           0 :             nread = -1;
    1867                 :           0 :             goto ret;
    1868                 :             :         }
    1869                 :             :     }
    1870                 :             : 
    1871                 :             :     /* ')' should have been consumed  by strtol */
    1872                 :             : 
    1873                 :         101 : ret:
    1874         [ -  + ]:         101 :     if (nread < 0)
    1875                 :             :     {
    1876         [ #  # ]:           0 :         if (*num_list)
    1877                 :             :         {
    1878         [ #  # ]:           0 :             inchi_free(*num_list);
    1879                 :           0 :             *num_list = NULL;
    1880                 :             :         }
    1881                 :             :     }
    1882                 :             : 
    1883                 :         101 :     return nread;
    1884                 :             : }
    1885                 :             : 
    1886                 :             : /****************************************************************************
    1887                 :             :     Returns -1 @ error
    1888                 :             : ****************************************************************************/
    1889                 :        1640 : int get_V3000_input_line_to_strbuf(INCHI_IOS_STRING *buf,
    1890                 :             :                                    INCHI_IOSTREAM *inp_stream)
    1891                 :             : {
    1892                 :        1640 :     const int prefix_len = 7; /* "M  V30 " */
    1893                 :        1640 :     int old_used, crlf2lf = 1, preserve_lf = 0;
    1894                 :             : 
    1895                 :        1640 :     inchi_strbuf_reset(buf);
    1896                 :             : 
    1897                 :        1640 :     old_used = buf->nUsedLength;
    1898                 :             :     while (1)
    1899                 :             :     {
    1900                 :        1640 :         inchi_strbuf_addline(buf, inp_stream, crlf2lf, preserve_lf);
    1901                 :             : 
    1902         [ -  + ]:        1640 :         if (buf->nUsedLength - old_used < 8)
    1903                 :             :         {
    1904                 :           0 :             return -1;
    1905                 :             :         }
    1906         [ -  + ]:        1640 :         if (strncmp(buf->pStr + old_used, "M  V30 ", prefix_len))
    1907                 :             :         {
    1908                 :           0 :             return -1;
    1909                 :             :         }
    1910                 :             : 
    1911                 :        1640 :         memmove((void *)(buf->pStr + old_used), (void *)(buf->pStr + old_used + prefix_len), (long long)buf->nUsedLength - (long long)old_used - (long long)prefix_len + 1); /* djb-rwth: cast operators added */ /* ricrogz: fixing memory overflow error */
    1912                 :        1640 :         buf->nUsedLength -= prefix_len;
    1913                 :             : 
    1914         [ +  - ]:        1640 :         if (buf->pStr[buf->nUsedLength - 1] != '-')
    1915                 :             :         {
    1916                 :        1640 :             break;
    1917                 :             :         }
    1918                 :           0 :         buf->pStr[--buf->nUsedLength] = '\0';
    1919                 :             : 
    1920                 :           0 :         old_used = buf->nUsedLength;
    1921                 :             :     }
    1922                 :             : 
    1923                 :        1640 :     remove_trailing_spaces(buf->pStr);
    1924                 :        1640 :     buf->nUsedLength = strlen(buf->pStr);
    1925                 :             : 
    1926                 :        1640 :     return buf->nUsedLength;
    1927                 :             : }
        

Generated by: LCOV version 2.0-1