LCOV - code coverage report
Current view: top level - src - ichi_io.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 38.8 % 614 238
Test Date: 2026-08-20 14:32:48 Functions: 45.9 % 37 17
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 23.9 % 468 112

             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 <string.h>
      42                 :             : #include <stdlib.h>
      43                 :             : #include <ctype.h>
      44                 :             : #include <stdarg.h>
      45                 :             : #include <time.h>
      46                 :             : 
      47                 :             : #include "mode.h"
      48                 :             : #include "ichi_io.h"
      49                 :             : #include "ichicomp.h"
      50                 :             : #include "ichidrp.h"
      51                 :             : #include "strutil.h"
      52                 :             : #include "util.h"
      53                 :             : 
      54                 :             : #include "bcf_s.h"
      55                 :             : 
      56                 :             : #ifndef INCHI_ADD_STR_LEN
      57                 :             : #define INCHI_ADD_STR_LEN   32768
      58                 :             : #endif
      59                 :             : 
      60                 :             : #ifdef TARGET_LIB_FOR_WINCHI
      61                 :             : extern void(*FWPRINT) (const char* format, va_list argptr);
      62                 :             : extern void(*FWPUSH) (const char* s);
      63                 :             : 
      64                 :             : #endif
      65                 :             : 
      66                 :             : 
      67                 :             : /* Internal functions */
      68                 :             : 
      69                 :             : int inchi_ios_str_getc(INCHI_IOSTREAM* ios);
      70                 :             : char* inchi_ios_str_gets(char* szLine, int len, INCHI_IOSTREAM* ios);
      71                 :             : char* inchi_ios_str_getsTab(char* szLine, int len, INCHI_IOSTREAM* ios);
      72                 :             : int GetMaxPrintfLength(const char* lpszFormat, va_list argList);
      73                 :             : char* inchi_fgetsTab(char* szLine, int len, FILE* f);
      74                 :             : int inchi_vfprintf(FILE* f, const char* lpszFormat, va_list argList);
      75                 :             : 
      76                 :             : 
      77                 :             : /*
      78                 :             :     INCHI_IOSTREAM OPERATIONS
      79                 :             : */
      80                 :             : 
      81                 :             : 
      82                 :             : /****************************************************************************
      83                 :             :  Init INCHI_IOSTREAM
      84                 :             : ****************************************************************************/
      85                 :         759 : void inchi_ios_init(INCHI_IOSTREAM* ios, int io_type, FILE* f)
      86                 :             : {
      87                 :         759 :     memset(ios, 0, sizeof(*ios)); /* djb-rwth: memset_s C11/Annex K variant? */
      88         [ -  + ]:         759 :     switch (io_type)
      89                 :             :     {
      90                 :           0 :     case INCHI_IOS_TYPE_FILE:
      91                 :           0 :         ios->type = INCHI_IOS_TYPE_FILE;
      92                 :           0 :         break;
      93                 :         759 :     case INCHI_IOS_TYPE_STRING:
      94                 :             :     default:
      95                 :         759 :         ios->type = INCHI_IOS_TYPE_STRING;
      96                 :         759 :         break;
      97                 :             :     }
      98                 :         759 :     ios->f = f;
      99                 :         759 :     return;
     100                 :             : }
     101                 :             : 
     102                 :             : 
     103                 :             : /****************************************************************************
     104                 :             :  Make a copy of INCHI_IOSTREAM
     105                 :             : ****************************************************************************/
     106                 :           0 : int inchi_ios_create_copy(INCHI_IOSTREAM* ios, INCHI_IOSTREAM* ios0)
     107                 :             : {
     108         [ #  # ]:           0 :     if (ios) /* djb-rwth: fixing a NULL pointer dereference */
     109                 :             :     {
     110                 :           0 :         memset(ios, 0, sizeof(*ios)); /* djb-rwth: memset_s C11/Annex K variant? */
     111                 :           0 :         ios->type = ios0->type;
     112                 :             : 
     113         [ #  # ]:           0 :         if (ios->type == INCHI_IOS_TYPE_STRING)
     114                 :             :         {
     115         [ #  # ]:           0 :             if (ios->s.pStr)
     116                 :             :             {
     117         [ #  # ]:           0 :                 inchi_free(ios->s.pStr);
     118                 :             :             }
     119                 :           0 :             ios->s.pStr = (char*)inchi_calloc(ios0->s.nAllocatedLength, sizeof(char));
     120         [ #  # ]:           0 :             if (ios->s.pStr)
     121                 :             :             {
     122                 :           0 :                 ios->s.nUsedLength = ios0->s.nUsedLength;
     123                 :           0 :                 ios->s.nPtr = ios0->s.nPtr;
     124                 :             :             }
     125                 :             :             else
     126                 :             :             {
     127                 :           0 :                 return -1; /* no memory */
     128                 :             :             }
     129                 :             :         }
     130                 :           0 :         ios->f = ios0->f;
     131                 :             :     }
     132                 :             : 
     133                 :           0 :     return 0;
     134                 :             : }
     135                 :             : 
     136                 :             : 
     137                 :             : /****************************************************************************
     138                 :             :     If INCHI_IOSTREAM type is INCHI_IOS_TYPE_STRING
     139                 :             :     and associated file exists, flush the string buffer
     140                 :             :     to that file, then free the buffer.
     141                 :             :     If INCHI_IOSTREAM type is INCHI_IOS_TYPE_FILE,
     142                 :             :     just flush the file.
     143                 :             : ****************************************************************************/
     144                 :           0 : void inchi_ios_flush(INCHI_IOSTREAM* ios)
     145                 :             : {
     146                 :             : 
     147         [ #  # ]:           0 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     148                 :             :     {
     149         [ #  # ]:           0 :         if (ios->s.pStr)
     150                 :             :         {
     151         [ #  # ]:           0 :             if (ios->s.nUsedLength > 0)
     152                 :             :             {
     153         [ #  # ]:           0 :                 if (ios->f)
     154                 :             :                 {
     155                 :           0 :                     fprintf(ios->f, "%-s", ios->s.pStr);
     156                 :           0 :                     fflush(ios->f);
     157                 :             :                 }
     158         [ #  # ]:           0 :                 inchi_free(ios->s.pStr);
     159                 :           0 :                 ios->s.pStr = NULL;
     160                 :           0 :                 ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
     161                 :             :             }
     162                 :             :         }
     163                 :             :     }
     164                 :             : 
     165         [ #  # ]:           0 :     else if (ios->type == INCHI_IOS_TYPE_FILE)
     166                 :             :     {
     167                 :             :         /* output to plain file: just flush it. */
     168                 :           0 :         fflush(ios->f);
     169                 :             :     }
     170                 :             : 
     171                 :           0 :     return;
     172                 :             : }
     173                 :             : 
     174                 :             : 
     175                 :             : /****************************************************************************
     176                 :             :     If INCHI_IOSTREAM type is INCHI_IOS_TYPE_STRING,
     177                 :             :     flush INCHI_IOSTREAM string buffer to associated file
     178                 :             :     (if non-NULL) echoing to another file (supplied as
     179                 :             :     parameter; typically, stderr); then free buffer.
     180                 :             :     If INCHI_IOSTREAM type is INCHI_IOS_TYPE_FILE,
     181                 :             :     just flush the both files.
     182                 :             : ****************************************************************************/
     183                 :           0 : void inchi_ios_flush2(INCHI_IOSTREAM* ios, FILE* f2)
     184                 :             : {
     185                 :             : 
     186         [ #  # ]:           0 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     187                 :             :     {
     188         [ #  # ]:           0 :         if (ios->s.pStr)
     189                 :             :         {
     190         [ #  # ]:           0 :             if (ios->s.nUsedLength > 0)
     191                 :             :             {
     192         [ #  # ]:           0 :                 if (ios->f)
     193                 :             :                 {
     194                 :           0 :                     fprintf(ios->f, "%-s", ios->s.pStr);
     195                 :           0 :                     fflush(ios->f);
     196                 :             :                 }
     197         [ #  # ]:           0 :                 if (f2 != ios->f)
     198                 :             :                 {
     199                 :           0 :                     fprintf(f2, "%-s", ios->s.pStr);
     200                 :             :                 }
     201                 :             : 
     202         [ #  # ]:           0 :                 inchi_free(ios->s.pStr);
     203                 :           0 :                 ios->s.pStr = NULL;
     204                 :           0 :                 ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
     205                 :             :             }
     206                 :             :         }
     207                 :             :     }
     208                 :             : 
     209         [ #  # ]:           0 :     else if (ios->type == INCHI_IOS_TYPE_FILE)
     210                 :             :     {
     211                 :             :         /* Output to plain file: just flush it. */
     212   [ #  #  #  #  :           0 :         if ((ios->f) && (ios->f != stderr) && (ios->f != stdout))
                   #  # ]
     213                 :             :         {
     214                 :           0 :             fflush(ios->f);
     215                 :             :         }
     216   [ #  #  #  #  :           0 :         if (f2 && f2 != stderr && f2 != stdout)
                   #  # ]
     217                 :             :         {
     218                 :           0 :             fflush(f2);
     219                 :             :         }
     220                 :             :     }
     221                 :             : 
     222                 :           0 :     return;
     223                 :             : }
     224                 :             : 
     225                 :             : 
     226                 :             : /****************************************************************************
     227                 :             :     Close INCHI_IOSTREAM: free string buffer and close associated file.
     228                 :             : ****************************************************************************/
     229                 :         344 : void inchi_ios_close(INCHI_IOSTREAM* ios)
     230                 :             : {
     231         [ -  + ]:         344 :     if (NULL == ios)
     232                 :             :     {
     233                 :           0 :         return;
     234                 :             :     }
     235         [ +  + ]:         344 :     if (ios->s.pStr)
     236                 :             :     {
     237         [ +  - ]:          96 :         inchi_free(ios->s.pStr);
     238                 :             :     }
     239                 :         344 :     ios->s.pStr = NULL;
     240                 :         344 :     ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
     241                 :             : 
     242   [ -  +  -  -  :         344 :     if (NULL != ios->f && stdout != ios->f && stderr != ios->f && stdin != ios->f)
             -  -  -  - ]
     243                 :             :     {
     244                 :           0 :         fclose(ios->f);
     245                 :             :     }
     246                 :             : 
     247                 :         344 :     return;
     248                 :             : }
     249                 :             : 
     250                 :             : 
     251                 :             : /****************************************************************************
     252                 :             :     Reset INCHI_IOSTREAM: set string buffer ptr to NULL
     253                 :             :     (but do _not_ free memory)and close associated file.
     254                 :             : ****************************************************************************/
     255                 :           1 : void inchi_ios_reset(INCHI_IOSTREAM* ios)
     256                 :             : {
     257                 :           1 :     ios->s.pStr = NULL;
     258                 :           1 :     ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
     259   [ -  +  -  -  :           1 :     if (NULL != ios->f && stdout != ios->f && stderr != ios->f && stdin != ios->f)
             -  -  -  - ]
     260                 :             :     {
     261                 :           0 :         fclose(ios->f);
     262                 :             :     }
     263                 :             : 
     264                 :           1 :     return;
     265                 :             : }
     266                 :             : 
     267                 :             : 
     268                 :             : /****************************************************************************
     269                 :             :     Reset INCHI_IOSTREAM: set string buffer ptr to NULL
     270                 :             :     (after freeing memory) but do not close associated file.
     271                 :             : ****************************************************************************/
     272                 :           0 : void inchi_ios_free_str(INCHI_IOSTREAM* ios)
     273                 :             : {
     274         [ #  # ]:           0 :     if (NULL == ios)
     275                 :             :     {
     276                 :           0 :         return;
     277                 :             :     }
     278         [ #  # ]:           0 :     if (ios->s.pStr) /* && ios->s.nAllocatedLength)*/
     279                 :             :     {
     280         [ #  # ]:           0 :         inchi_free(ios->s.pStr);
     281                 :             :     }
     282                 :           0 :     ios->s.pStr = NULL;
     283                 :           0 :     ios->s.nUsedLength = 0;
     284                 :           0 :     ios->s.nAllocatedLength = 0;
     285                 :           0 :     ios->s.nPtr = 0;
     286                 :             : 
     287                 :           0 :     return;
     288                 :             : }
     289                 :             : 
     290                 :             : 
     291                 :             : /****************************************************************************
     292                 :             :     [str] getc()
     293                 :             : ****************************************************************************/
     294                 :       68797 : int inchi_ios_str_getc(INCHI_IOSTREAM* ios)
     295                 :             : {
     296                 :             :     int c;
     297         [ +  - ]:       68797 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     298                 :             :     {
     299         [ +  - ]:       68797 :         if (ios->s.nPtr < ios->s.nUsedLength)
     300                 :             :         {
     301                 :       68797 :             return (int)ios->s.pStr[ios->s.nPtr++];
     302                 :             :         }
     303                 :           0 :         return EOF;
     304                 :             :     }
     305                 :             : 
     306         [ #  # ]:           0 :     else if (ios->type == INCHI_IOS_TYPE_FILE)
     307                 :             :     {
     308                 :           0 :         c = fgetc(ios->f);
     309         [ #  # ]:           0 :         if (ferror(ios->f))
     310                 :             :         {
     311                 :           0 :             c = EOF;
     312                 :             :         }
     313                 :           0 :         return c;
     314                 :             :     }
     315                 :             : 
     316                 :             :     /* error */
     317                 :           0 :     return EOF;
     318                 :             : }
     319                 :             : 
     320                 :             : 
     321                 :             : /****************************************************************************
     322                 :             :     [str] gets()
     323                 :             : ****************************************************************************/
     324                 :           0 : char* inchi_ios_str_gets(char* szLine, int len, INCHI_IOSTREAM* f)
     325                 :             : {
     326                 :           0 :     int  length = 0, c = 0;
     327         [ #  # ]:           0 :     if (--len < 0)
     328                 :             :     {
     329                 :           0 :         return NULL;
     330                 :             :     }
     331   [ #  #  #  # ]:           0 :     while (length < len && EOF != (c = inchi_ios_str_getc(f)))
     332                 :             :     {
     333                 :           0 :         szLine[length++] = (char)c;
     334         [ #  # ]:           0 :         if (c == '\n')
     335                 :             :         {
     336                 :           0 :             break;
     337                 :             :         }
     338                 :             :     }
     339   [ #  #  #  # ]:           0 :     if (!length && EOF == c)
     340                 :             :     {
     341                 :           0 :         return NULL;
     342                 :             :     }
     343                 :           0 :     szLine[length] = '\0';
     344                 :             : 
     345                 :           0 :     return szLine;
     346                 :             : }
     347                 :             : 
     348                 :             : /****************************************************************************
     349                 :             :     Read up to tab or LF but not more than len chars;
     350                 :             :     if empty line, read further until a non-empty line;
     351                 :             :     remove leading and trailing white spaces;
     352                 :             :     keep zero termination
     353                 :             : ****************************************************************************/
     354                 :           0 : char* inchi_ios_str_getsTab(char* szLine, int len, INCHI_IOSTREAM* f)
     355                 :             : {
     356                 :           0 :     int  length = 0, c = 0;
     357         [ #  # ]:           0 :     if (--len < 0)
     358                 :             :     {
     359                 :           0 :         return NULL;
     360                 :             :     }
     361   [ #  #  #  # ]:           0 :     while (length < len && EOF != (c = inchi_ios_str_getc(f)))
     362                 :             :     {
     363         [ #  # ]:           0 :         if (c == '\t')
     364                 :             :         {
     365                 :           0 :             c = '\n';
     366                 :             :         }
     367                 :           0 :         szLine[length++] = (char)c;
     368         [ #  # ]:           0 :         if (c == '\n')
     369                 :             :         {
     370                 :           0 :             break;
     371                 :             :         }
     372                 :             :     }
     373   [ #  #  #  # ]:           0 :     if (!length && EOF == c)
     374                 :             :     {
     375                 :           0 :         return NULL;
     376                 :             :     }
     377                 :           0 :     szLine[length] = '\0';
     378                 :             : 
     379                 :           0 :     return szLine;
     380                 :             : }
     381                 :             : 
     382                 :             : 
     383                 :             : /****************************************************************************
     384                 :             :     gets()
     385                 :             : ****************************************************************************/
     386                 :           0 : int inchi_ios_gets(char* szLine,
     387                 :             :     int len,
     388                 :             :     INCHI_IOSTREAM* f,
     389                 :             :     int* bTooLongLine)
     390                 :             : {
     391                 :             :     int  length;
     392                 :             :     char* p;
     393                 :             :     do
     394                 :             :     {
     395                 :           0 :         p = inchi_ios_str_gets(szLine, len - 1, f);
     396         [ #  # ]:           0 :         if (!p)
     397                 :             :         {
     398                 :           0 :             *bTooLongLine = 0;
     399                 :           0 :             return -1; /* end of file or cannot read */
     400                 :             :         }
     401                 :           0 :         szLine[len - 1] = '\0';
     402                 :             :         /*
     403                 :             :         *bTooLongLine = !strchr( szLine, '\n' );
     404                 :             :         */
     405                 :           0 :         p = strchr(szLine, '\n');
     406   [ #  #  #  # ]:           0 :         *bTooLongLine = (!p && ((int)strlen(szLine)) == len - 2);
     407                 :           0 :         lrtrim(szLine, &length);
     408         [ #  # ]:           0 :     } while (!length);
     409                 :             : 
     410                 :           0 :     return length;
     411                 :             : }
     412                 :             : 
     413                 :             : 
     414                 :             : /****************************************************************************
     415                 :             :     Read up to tab or LF but not more than len chars;
     416                 :             :     if empty line, read further until a non-empty line;
     417                 :             :     remove leading and trailing white spaces;
     418                 :             :     keep zero termination
     419                 :             : ****************************************************************************/
     420                 :           0 : int inchi_ios_getsTab(char* szLine,
     421                 :             :     int len,
     422                 :             :     INCHI_IOSTREAM* f,
     423                 :             :     int* bTooLongLine)
     424                 :             : {
     425                 :             :     int  length;
     426                 :             :     char* p;
     427                 :             :     do
     428                 :             :     {
     429                 :             : 
     430                 :           0 :         p = inchi_ios_str_getsTab(szLine, len - 1, f);
     431         [ #  # ]:           0 :         if (!p)
     432                 :             :         {
     433                 :           0 :             *bTooLongLine = 0;
     434                 :           0 :             return -1; /* end of file or cannot read */
     435                 :             :         }
     436                 :           0 :         szLine[len - 1] = '\0';
     437                 :             :         /*
     438                 :             :         *bTooLongLine = !strchr( szLine, '\n' );
     439                 :             :         */
     440                 :           0 :         p = strchr(szLine, '\n');
     441   [ #  #  #  # ]:           0 :         *bTooLongLine = (!p && ((int)strlen(szLine)) == len - 2);
     442                 :           0 :         lrtrim(szLine, &length);
     443                 :             : 
     444         [ #  # ]:           0 :     } while (!length);
     445                 :             : 
     446                 :           0 :     return length;
     447                 :             : }
     448                 :             : 
     449                 :             : 
     450                 :             : /****************************************************************************/
     451                 :           0 : int inchi_ios_getsTab1(char* szLine,
     452                 :             :     int len,
     453                 :             :     INCHI_IOSTREAM* f,
     454                 :             :     int* bTooLongLine)
     455                 :             : {
     456                 :             :     int  length;
     457                 :             :     char* p;
     458                 :             : 
     459                 :           0 :     p = inchi_ios_str_getsTab(szLine, len - 1, f);
     460         [ #  # ]:           0 :     if (!p)
     461                 :             :     {
     462                 :           0 :         *bTooLongLine = 0;
     463                 :           0 :         return -1; /* end of file or cannot read */
     464                 :             :     }
     465                 :           0 :     szLine[len - 1] = '\0';
     466                 :           0 :     p = strchr(szLine, '\n');
     467   [ #  #  #  # ]:           0 :     *bTooLongLine = (!p && ((int)strlen(szLine)) == len - 2);
     468                 :           0 :     lrtrim(szLine, &length);
     469                 :             : 
     470                 :           0 :     return length;
     471                 :             : }
     472                 :             : 
     473                 :             : 
     474                 :             : /****************************************************************************
     475                 :             :  General procedure for printing to INCHI_IOSTREAM
     476                 :             : ****************************************************************************/
     477                 :        1651 : int inchi_ios_print(INCHI_IOSTREAM* ios, const char* lpszFormat, ...)
     478                 :             : {
     479                 :        1651 :     int ret = 0, ret2 = 0;
     480                 :             :     va_list argList;
     481                 :             : 
     482         [ -  + ]:        1651 :     if (!ios)
     483                 :             :     {
     484                 :           0 :         return -1;
     485                 :             :     }
     486                 :             : 
     487         [ +  - ]:        1651 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     488                 :             :     {
     489                 :             :         /* output to string buffer */
     490                 :             :         int max_len;
     491                 :        1651 :         my_va_start(argList, lpszFormat);
     492                 :        1651 :         max_len = GetMaxPrintfLength(lpszFormat, argList);
     493                 :        1651 :         va_end(argList);
     494         [ +  - ]:        1651 :         if (max_len >= 0)
     495                 :             :         {
     496                 :             :             /* djb-rwth: fixing oss-fuzz issue #30152 */
     497                 :        1651 :             int  nAddLength = inchi_max(INCHI_ADD_STR_LEN, max_len);
     498                 :        1651 :             long long new_str_len = (long long)ios->s.nAllocatedLength + (long long)nAddLength;
     499         [ -  + ]:        1651 :             if (ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len)
     500                 :             :             {
     501                 :             :                 /* enlarge output string */
     502                 :           0 :                 char* new_str = (char*)inchi_calloc(new_str_len, sizeof(char)); /* djb-rwth: cast operators added */
     503         [ #  # ]:           0 :                 if (new_str)
     504                 :             :                 {
     505         [ #  # ]:           0 :                     if (ios->s.pStr)
     506                 :             :                     {
     507         [ #  # ]:           0 :                         if (ios->s.nUsedLength > 0)
     508                 :             :                         {
     509                 :           0 :                             memcpy(new_str, ios->s.pStr, sizeof(new_str[0]) * ios->s.nUsedLength);
     510                 :             :                         }
     511         [ #  # ]:           0 :                         inchi_free(ios->s.pStr);
     512                 :             :                     }
     513                 :           0 :                     ios->s.pStr = new_str;
     514                 :           0 :                     ios->s.nAllocatedLength += nAddLength;
     515                 :             :                 }
     516                 :             :                 else
     517                 :             :                 {
     518                 :           0 :                     return -1; /* failed */
     519                 :             :                 }
     520                 :             :             }
     521                 :             :             /* output */
     522                 :        1651 :             my_va_start(argList, lpszFormat);
     523                 :        1651 :             ret = vsprintf(ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList); /* djb-rwth: not using vsnprintf due to variable length argument */
     524                 :        1651 :             va_end(argList);
     525         [ +  - ]:        1651 :             if (ret >= 0)
     526                 :             :             {
     527                 :        1651 :                 ios->s.nUsedLength += ret;
     528                 :             :             }
     529                 :             : #ifdef TARGET_LIB_FOR_WINCHI
     530                 :             : #if 0
     531                 :             :             if (FWPRINT)
     532                 :             :             {
     533                 :             :                 my_va_start(argList, lpszFormat);
     534                 :             :                 FWPRINT(lpszFormat, argList);
     535                 :             :                 va_end(argList);
     536                 :             :             }
     537                 :             : #endif
     538                 :             : #endif
     539                 :        1651 :             return ret;
     540                 :             :         }
     541                 :           0 :         return -1;
     542                 :             :     }
     543                 :             : 
     544         [ #  # ]:           0 :     else if (ios->type == INCHI_IOS_TYPE_FILE)
     545                 :             :     {
     546                 :             :         /* output to file */
     547         [ #  # ]:           0 :         if (ios->f)
     548                 :             :         {
     549                 :           0 :             my_va_start(argList, lpszFormat);
     550                 :           0 :             ret = vfprintf(ios->f, lpszFormat, argList);
     551                 :           0 :             va_end(argList);
     552                 :             :         }
     553                 :             :         else
     554                 :             :         {
     555                 :           0 :             my_va_start(argList, lpszFormat);
     556                 :           0 :             ret2 = vfprintf(stdout, lpszFormat, argList);
     557                 :           0 :             va_end(argList);
     558                 :             :         }
     559                 :             : #ifdef TARGET_LIB_FOR_WINCHI
     560                 :             :         if (FWPRINT)
     561                 :             :         {
     562                 :             :             my_va_start(argList, lpszFormat);
     563                 :             :             FWPRINT(lpszFormat, argList);
     564                 :             :             va_end(argList);
     565                 :             :         }
     566                 :             : #endif
     567         [ #  # ]:           0 :         return ret ? ret : ret2;
     568                 :             :     }
     569                 :             : 
     570                 :             :     /* no output */
     571                 :           0 :     return 0;
     572                 :             : }
     573                 :             : 
     574                 :             : 
     575                 :             : /****************************************************************************/
     576                 :           0 : int push_to_winchi_text_window(INCHI_IOSTREAM* ios)
     577                 :             : /*, const char* lpszFormat, ... ) */
     578                 :             : {
     579                 :             : #ifndef TARGET_LIB_FOR_WINCHI
     580                 :           0 :     return -1;
     581                 :             : #else
     582                 :             :     if (ios->type != INCHI_IOS_TYPE_STRING)
     583                 :             :     {
     584                 :             :         return -1;
     585                 :             :     }
     586                 :             :     if (!ios || !ios->s.pStr)
     587                 :             :     {
     588                 :             :         return -1;
     589                 :             :     }
     590                 :             :     if (!FWPUSH)
     591                 :             :     {
     592                 :             :         return -1;
     593                 :             :     }
     594                 :             : 
     595                 :             :     FWPUSH(ios->s.pStr);
     596                 :             : 
     597                 :             :     return 0;
     598                 :             : #endif
     599                 :             : }
     600                 :             : 
     601                 :             : /****************************************************************************
     602                 :             :     This function's output should not be displayed in the output pane
     603                 :             : ****************************************************************************/
     604                 :         796 : int inchi_ios_print_nodisplay( INCHI_IOSTREAM * ios,
     605                 :             :                                const char* lpszFormat,
     606                 :             :                                ... )
     607                 :             : {
     608                 :             :     va_list argList;
     609                 :             : 
     610         [ -  + ]:         796 :     if (!ios)
     611                 :             :     {
     612                 :           0 :         return -1;
     613                 :             :     }
     614                 :             : 
     615         [ +  - ]:         796 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     616                 :             :     {
     617                 :             :         /* output to string buffer */
     618                 :         796 :         int ret = 0, max_len;
     619                 :         796 :         my_va_start( argList, lpszFormat );
     620                 :         796 :         max_len = GetMaxPrintfLength( lpszFormat, argList );
     621                 :         796 :         va_end( argList );
     622         [ +  - ]:         796 :         if (max_len >= 0)
     623                 :             :         {
     624                 :             :             /* djb-rwth: fixing oss-fuzz issue #30163 */
     625                 :         796 :             int  nAddLength = inchi_max(INCHI_ADD_STR_LEN, max_len);
     626                 :         796 :             long long new_str_len = (long long)ios->s.nAllocatedLength + (long long)nAddLength;
     627         [ +  + ]:         796 :             if (ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len)
     628                 :             :             {
     629                 :             :                 /* enlarge output string */
     630                 :         123 :                 char* new_str = (char*)inchi_calloc(new_str_len, sizeof(new_str[0])); /* djb-rwth: cast operators added */
     631         [ +  - ]:         123 :                 if (new_str)
     632                 :             :                 {
     633         [ -  + ]:         123 :                     if (ios->s.pStr)
     634                 :             :                     {
     635         [ #  # ]:           0 :                         if (ios->s.nUsedLength > 0)
     636                 :             :                         {
     637                 :           0 :                             memcpy( new_str, ios->s.pStr, sizeof( new_str[0] )*ios->s.nUsedLength );
     638                 :             :                         }
     639         [ #  # ]:           0 :                         inchi_free( ios->s.pStr );
     640                 :             :                     }
     641                 :         123 :                     ios->s.pStr = new_str;
     642                 :         123 :                     ios->s.nAllocatedLength += nAddLength;
     643                 :             :                 }
     644                 :             :                 else
     645                 :             :                 {
     646                 :           0 :                     return -1; /* failed */
     647                 :             :                 }
     648                 :             :             }
     649                 :             :             /* output */
     650                 :             :             /* djb-rwth: fixing oss-fuzz issue #67676 */
     651                 :         796 :             my_va_start(argList, lpszFormat);
     652                 :         796 :             size_t remaining_length = (size_t)(ios->s.nAllocatedLength - ios->s.nUsedLength);
     653                 :         796 :             ret = vsnprintf(ios->s.pStr + ios->s.nUsedLength, remaining_length, lpszFormat, argList);
     654                 :         796 :             va_end(argList);
     655                 :             : 
     656                 :             :             /* djb-rwth: if vsnprintf fails, try again with + 1 */
     657   [ +  -  -  + ]:         796 :             if (ret < 0 || (size_t)ret >= remaining_length)
     658                 :             :             {
     659                 :             :                 long long str_length_extension;
     660         [ #  # ]:           0 :                 if (ret >= 0)
     661                 :             :                 {
     662                 :           0 :                     str_length_extension = (long long)ret + 1;
     663                 :             :                 }
     664                 :             :                 else
     665                 :             :                 {
     666                 :           0 :                     str_length_extension = (long long)max_len + 1;
     667                 :             :                 }
     668                 :           0 :                 long long new_str_length = (long long)ios->s.nAllocatedLength + str_length_extension;
     669                 :           0 :                 char* new_str = (char*)inchi_calloc(new_str_length, sizeof(new_str[0]));
     670         [ #  # ]:           0 :                 if (!new_str)
     671                 :             :                 {
     672                 :           0 :                     return -1;
     673                 :             :                 }
     674         [ #  # ]:           0 :                 if (ios->s.pStr)
     675                 :             :                 {
     676         [ #  # ]:           0 :                     if (ios->s.nUsedLength > 0)
     677                 :             :                     {
     678                 :           0 :                         memcpy(new_str, ios->s.pStr, sizeof(new_str[0]) * ios->s.nUsedLength);
     679                 :             :                     }
     680         [ #  # ]:           0 :                     inchi_free(ios->s.pStr);
     681                 :             :                 }
     682                 :           0 :                 ios->s.pStr = new_str;
     683                 :           0 :                 ios->s.nAllocatedLength += (int)str_length_extension;
     684                 :             : 
     685                 :             :                 // try printing again
     686                 :           0 :                 my_va_start(argList, lpszFormat);
     687                 :           0 :                 size_t remainingLength2 = (size_t)(ios->s.nAllocatedLength - ios->s.nUsedLength);
     688                 :           0 :                 ret = vsnprintf(ios->s.pStr + ios->s.nUsedLength, remainingLength2, lpszFormat, argList);
     689                 :           0 :                 va_end(argList);
     690                 :             :             }
     691                 :             : 
     692         [ +  - ]:         796 :             if (ret >= 0)
     693                 :             :             {
     694                 :         796 :                 ios->s.nUsedLength += ret;
     695                 :             :             }
     696                 :         796 :             return ret;
     697                 :             :         }
     698                 :           0 :         return -1;
     699                 :             :     }
     700                 :             : 
     701         [ #  # ]:           0 :     else if (ios->type == INCHI_IOS_TYPE_FILE)
     702                 :             :     {
     703                 :           0 :         my_va_start( argList, lpszFormat );
     704                 :           0 :         inchi_print_nodisplay( ios->f, lpszFormat, argList );
     705                 :           0 :         va_end( argList );
     706                 :             :     }
     707                 :             : 
     708                 :             :     /* no output */
     709                 :           0 :     return 0;
     710                 :             : }
     711                 :             : 
     712                 :             : 
     713                 :             : /****************************************************************************
     714                 :             :     This function's flushes previously hidden output and resets string stream
     715                 :             :     returns n chars on success, otherwise -1
     716                 :             : ****************************************************************************/
     717                 :           0 : int inchi_ios_flush_not_displayed(INCHI_IOSTREAM* ios)
     718                 :             : {
     719                 :           0 :     char* obuf = NULL;
     720                 :             :     int ret;
     721                 :             : 
     722         [ #  # ]:           0 :     if (!ios)
     723                 :             :     {
     724                 :           0 :         return -1;
     725                 :             :     }
     726                 :             : 
     727                 :           0 :     obuf = (char*)inchi_calloc((long long)ios->s.nUsedLength + 1, sizeof(char)); /* djb-rwth: cast operator added */
     728                 :             : 
     729         [ #  # ]:           0 :     if (!obuf)
     730                 :             :     {
     731                 :           0 :         return -1;
     732                 :             :     }
     733                 :             : 
     734                 :           0 :     strcpy(obuf, ios->s.pStr);
     735                 :           0 :     ios->s.nUsedLength = 0;
     736                 :           0 :     ret = inchi_ios_print(ios, "%s", obuf);
     737         [ #  # ]:           0 :     inchi_free(obuf);
     738                 :             : 
     739                 :           0 :     return ret;
     740                 :             : }
     741                 :             : 
     742                 :             : 
     743                 :             : /****************************************************************************
     744                 :             :  Print to string buffer or to file+stderr
     745                 :             : ****************************************************************************/
     746                 :          56 : int inchi_ios_eprint(INCHI_IOSTREAM* ios, const char* lpszFormat, ...)
     747                 :             : {
     748                 :          56 :     int ret = 0, ret2 = 0;
     749                 :             :     va_list argList;
     750                 :             : 
     751         [ -  + ]:          56 :     if (!ios)
     752                 :             :     {
     753                 :           0 :         return -1;
     754                 :             :     }
     755                 :             : 
     756         [ +  - ]:          56 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     757                 :             :         /* was #if ( defined(TARGET_API_LIB) || defined(INCHI_STANDALONE_EXE) ) */
     758                 :             :     {
     759                 :             :         /* output to string buffer */
     760                 :          56 :         int max_len, nAddLength = 0;
     761                 :          56 :         char* new_str = NULL;
     762                 :             : 
     763                 :          56 :         my_va_start(argList, lpszFormat);
     764                 :          56 :         max_len = GetMaxPrintfLength(lpszFormat, argList);
     765                 :          56 :         va_end(argList);
     766                 :             : 
     767         [ +  - ]:          56 :         if (max_len >= 0)
     768                 :             :         {
     769         [ +  + ]:          56 :             if (ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len)
     770                 :             :             {
     771                 :             :                 /* enlarge output string */
     772                 :          27 :                 nAddLength = inchi_max(INCHI_ADD_STR_LEN, max_len);
     773                 :          27 :                 new_str = (char*)inchi_calloc((long long)ios->s.nAllocatedLength + (long long)nAddLength, sizeof(new_str[0])); /* djb-rwth: cast operators added */
     774         [ +  - ]:          27 :                 if (new_str)
     775                 :             :                 {
     776         [ -  + ]:          27 :                     if (ios->s.pStr)
     777                 :             :                     {
     778         [ #  # ]:           0 :                         if (ios->s.nUsedLength > 0)
     779                 :             :                         {
     780                 :           0 :                             memcpy(new_str, ios->s.pStr, sizeof(new_str[0]) * ios->s.nUsedLength);
     781                 :             :                         }
     782         [ #  # ]:           0 :                         inchi_free(ios->s.pStr);
     783                 :             :                     }
     784                 :          27 :                     ios->s.pStr = new_str;
     785                 :          27 :                     ios->s.nAllocatedLength += nAddLength;
     786                 :             :                 }
     787                 :             :                 else
     788                 :             :                 {
     789                 :           0 :                     return -1; /* failed */
     790                 :             :                 }
     791                 :             :             }
     792                 :             : 
     793                 :             :             /* output */
     794                 :          56 :             my_va_start(argList, lpszFormat);
     795                 :          56 :             ret = vsprintf(ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList);
     796                 :          56 :             va_end(argList);
     797         [ +  - ]:          56 :             if (ret >= 0)
     798                 :             :             {
     799                 :          56 :                 ios->s.nUsedLength += ret;
     800                 :             :             }
     801                 :          56 :             return ret;
     802                 :             :         }
     803                 :           0 :         return -1;
     804                 :             :     }
     805                 :             : 
     806         [ #  # ]:           0 :     else if (ios->type == INCHI_IOS_TYPE_FILE)
     807                 :             :     {
     808         [ #  # ]:           0 :         if (ios->f)
     809                 :             :         {
     810                 :             :             /* output to plain file */
     811                 :           0 :             my_va_start(argList, lpszFormat);
     812                 :           0 :             ret = inchi_vfprintf(ios->f, lpszFormat, argList);
     813                 :           0 :             va_end(argList);
     814                 :             :             /*  No output to stderr from within dll or GUI program */
     815                 :             : #if ( !defined(TARGET_API_LIB) && !defined(TARGET_LIB_FOR_WINCHI) )
     816                 :             :             if (ios->f != stderr)
     817                 :             :             {
     818                 :             :                 my_va_start(argList, lpszFormat);
     819                 :             :                 ret2 = vfprintf(stderr, lpszFormat, argList);
     820                 :             :                 va_end(argList);
     821                 :             :             }
     822                 :             : #endif
     823         [ #  # ]:           0 :             return ret ? ret : ret2;
     824                 :             :         }
     825                 :             :     }
     826                 :             : 
     827                 :             :     /* no output */
     828                 :           0 :     return 0;
     829                 :             : }
     830                 :             : 
     831                 :             : 
     832                 :             : /*    PLAIN FILE OPERATIONS */
     833                 :             : 
     834                 :             : 
     835                 :             : /****************************************************************************
     836                 :             :  Print to file, echoing to stderr
     837                 :             : ****************************************************************************/
     838                 :           0 : int inchi_fprintf(FILE* f, const char* lpszFormat, ...)
     839                 :             : {
     840                 :           0 :     int ret = 0, ret2 = 0;
     841                 :             :     va_list argList;
     842         [ #  # ]:           0 :     if (f)
     843                 :             :     {
     844                 :           0 :         my_va_start(argList, lpszFormat);
     845                 :           0 :         ret = inchi_vfprintf(f, lpszFormat, argList);
     846                 :           0 :         va_end(argList);
     847                 :             :         /*  No output to stderr from within dll or GUI program */
     848                 :             : #if ( !defined(TARGET_API_LIB) && !defined(TARGET_LIB_FOR_WINCHI) )
     849                 :             :         if (f != stderr)
     850                 :             :         {
     851                 :             :             my_va_start(argList, lpszFormat);
     852                 :             :             ret2 = vfprintf(stderr, lpszFormat, argList);
     853                 :             :             va_end(argList);
     854                 :             :         }
     855                 :             : #endif
     856         [ #  # ]:           0 :         return ret ? ret : ret2;
     857                 :             :     }
     858                 :             : 
     859                 :           0 :     return 0;
     860                 :             : }
     861                 :             : 
     862                 :             : 
     863                 :             : /****************************************************************************
     864                 :             :  Print to file
     865                 :             : ****************************************************************************/
     866                 :           0 : int inchi_vfprintf(FILE* f, const char* lpszFormat, va_list argList)
     867                 :             : {
     868                 :           0 :     int ret = 0;
     869   [ #  #  #  # ]:           0 :     if (lpszFormat && lpszFormat[0]) /* djb-rwth: condition added as lpszFormat == 0 may lead to undefined ret value */
     870                 :             :     {
     871   [ #  #  #  # ]:           0 :         if (f == stderr && '\r' == lpszFormat[strlen(lpszFormat) - 1])
     872                 :             :         {
     873                 :             : #define CONSOLE_LINE_LEN 80
     874                 :             : #ifndef COMPILE_ANSI_ONLY
     875                 :             :             char szLine[CONSOLE_LINE_LEN];
     876                 :             : 
     877                 :             :             ret = _vsnprintf(szLine, CONSOLE_LINE_LEN - 1, lpszFormat, argList);
     878                 :             : 
     879                 :             :             if (ret < 0)
     880                 :             :             {
     881                 :             :                 /*  output is longer than the console line */
     882                 :             :                 /* Fixed bug: (CONSOLE_LINE_LEN-4) --> (CONSOLE_LINE_LEN-4-1) 11-22-08 IPl */
     883                 :             :                 strcpy(szLine + CONSOLE_LINE_LEN - 5, "...\r");
     884                 :             :             }
     885                 :             : 
     886                 :             :             fputs(szLine, f);
     887                 :             : #else
     888                 :           0 :             ret = vfprintf(f, lpszFormat, argList);
     889                 :             : #endif
     890                 :             : #undef CONSOLE_LINE_LEN
     891                 :             :         }
     892                 :             :         else
     893                 :             :         {
     894                 :           0 :             ret = vfprintf(f, lpszFormat, argList);
     895                 :             :         }
     896                 :             :     }
     897                 :             : 
     898                 :           0 :     return ret;
     899                 :             : }
     900                 :             : 
     901                 :             : 
     902                 :             : /****************************************************************************
     903                 :             :     This function's output should not be displayed in the output pane
     904                 :             : ****************************************************************************/
     905                 :           0 : int inchi_print_nodisplay(FILE* f, const char* lpszFormat, ...)
     906                 :             : {
     907                 :           0 :     int ret = 0;
     908                 :             :     va_list argList;
     909                 :             :     FILE* fi;
     910                 :             : 
     911         [ #  # ]:           0 :     if (f)
     912                 :             :     {
     913                 :           0 :         fi = f;
     914                 :             :     }
     915                 :             :     else
     916                 :             :     {
     917                 :           0 :         fi = stdout;
     918                 :             :     }
     919                 :             : 
     920                 :           0 :     my_va_start(argList, lpszFormat);
     921                 :           0 :     ret = vfprintf(fi, lpszFormat, argList);
     922                 :           0 :     va_end(argList);
     923                 :           0 :     return ret;
     924                 :             : }
     925                 :             : 
     926                 :             : 
     927                 :             : #if ( FIX_READ_LONG_LINE_BUG == 1 )
     928                 :             : 
     929                 :             : 
     930                 :             : /****************************************************************************/
     931                 :           0 : int inchi_fgetsLfTab(char* szLine, int len, FILE* f)
     932                 :             : {
     933                 :             :     int  length;
     934                 :             :     char* p;
     935                 :             :     char szSkip[256];
     936                 :           0 :     int  bTooLongLine = 0;
     937                 :             :     do
     938                 :             :     {
     939                 :           0 :         p = inchi_fgetsTab(szLine, len, f);
     940         [ #  # ]:           0 :         if (!p)
     941                 :             :         {
     942                 :           0 :             return -1; /* end of file or cannot read */
     943                 :             :         }
     944   [ #  #  #  # ]:           0 :         bTooLongLine = ((int)strlen(szLine) == len - 1 && szLine[len - 2] != '\n');
     945                 :           0 :         lrtrim(szLine, &length);
     946         [ #  # ]:           0 :     } while (!length);
     947         [ #  # ]:           0 :     if (bTooLongLine)
     948                 :             :     {
     949         [ #  # ]:           0 :         while ((p = inchi_fgetsTab(szSkip, sizeof(szSkip) - 1, f))) /* djb-rwth: ignoring LLVM warning: function returning value */
     950                 :             :         {
     951         [ #  # ]:           0 :             if (strchr(szSkip, '\n'))
     952                 :           0 :                 break;
     953                 :             :         }
     954                 :             :     }
     955                 :             : 
     956                 :           0 :     return length;
     957                 :             : }
     958                 :             : 
     959                 :             : 
     960                 :             : #else
     961                 :             : 
     962                 :             : 
     963                 :             : /****************************************************************************/
     964                 :             : int inchi_fgetsLfTab(char* szLine, int len, FILE* f)
     965                 :             : {
     966                 :             :     int  length;
     967                 :             :     char* p;
     968                 :             :     char szSkip[256];
     969                 :             :     int  bTooLongLine = 0;
     970                 :             :     do
     971                 :             :     {
     972                 :             :         p = inchi_fgetsTab(szLine, len - 1, f);
     973                 :             :         if (!p)
     974                 :             :         {
     975                 :             :             return -1; /* end of file or cannot read */
     976                 :             :         }
     977                 :             :         szLine[len - 1] = '\0';
     978                 :             :         /*
     979                 :             :         bTooLongLine = !strchr( szLine, '\n' );
     980                 :             :         */
     981                 :             :         bTooLongLine = (!p && ((int)strlen(szLine)) == len - 2);
     982                 :             :         lrtrim(szLine, &length);
     983                 :             :     } while (!length);
     984                 :             :     if (bTooLongLine)
     985                 :             :     {
     986                 :             :         while (p = inchi_fgetsTab(szSkip, sizeof(szSkip) - 1, f))
     987                 :             :         {
     988                 :             :             szSkip[sizeof(szSkip) - 1] = '\0';
     989                 :             :             if (strchr(szSkip, '\n'))
     990                 :             :                 break;
     991                 :             :         }
     992                 :             :     }
     993                 :             :     return length;
     994                 :             : }
     995                 :             : #endif
     996                 :             : 
     997                 :             : 
     998                 :             : /****************************************************************************
     999                 :             :     Read up to tab or LF but not more than len chars;
    1000                 :             :     if empty line, read further until a non-empty line;
    1001                 :             :     remove leading and trailing white spaces;
    1002                 :             :     keep zero termination
    1003                 :             : ****************************************************************************/
    1004                 :           0 : char* inchi_fgetsTab(char* szLine, int len, FILE* f)
    1005                 :             : {
    1006                 :           0 :     int  length = 0, c = 0;
    1007                 :           0 :     len--;
    1008   [ #  #  #  # ]:           0 :     while (length < len && EOF != (c = fgetc(f)))
    1009                 :             :     {
    1010         [ #  # ]:           0 :         if (c == '\t')
    1011                 :             :         {
    1012                 :           0 :             c = '\n';
    1013                 :             :         }
    1014                 :           0 :         szLine[length++] = (char)c;
    1015         [ #  # ]:           0 :         if (c == '\n')
    1016                 :             :         {
    1017                 :           0 :             break;
    1018                 :             :         }
    1019                 :             :     }
    1020   [ #  #  #  # ]:           0 :     if (!length && EOF == c)
    1021                 :             :     {
    1022                 :           0 :         return NULL;
    1023                 :             :     }
    1024                 :           0 :     szLine[length] = '\0';
    1025                 :             : 
    1026                 :           0 :     return szLine;
    1027                 :             : }
    1028                 :             : 
    1029                 :             : 
    1030                 :             : /****************************************************************************
    1031                 :             :     Read up to LF but not more than line_len bytes;
    1032                 :             :     if input line is too long, quietly ignore the rest of the line
    1033                 :             : ****************************************************************************/
    1034                 :         984 : char* inchi_fgetsLf(char* line, int line_len, INCHI_IOSTREAM* inp_stream)
    1035                 :             : {
    1036                 :         984 :     char* p = NULL, * q;
    1037                 :         984 :     FILE* finp = NULL;
    1038                 :             : 
    1039         [ -  + ]:         984 :     if (inp_stream->type == INCHI_IOS_TYPE_FILE)
    1040                 :             :     {
    1041                 :             :         /* Read from file */
    1042                 :           0 :         finp = inp_stream->f;
    1043                 :           0 :         memset(line, 0, line_len); /* djb-rwth: memset_s C11/Annex K variant? */
    1044         [ #  # ]:           0 :         if (NULL != (p = fgets(line, line_len, finp)) &&
    1045         [ #  # ]:           0 :             NULL == strchr(p, '\n'))
    1046                 :             :         {
    1047                 :             :             char temp[64];
    1048                 :             :             /* bypass up to '\n' or up to end of file whichever comes first */
    1049   [ #  #  #  # ]:           0 :             while (NULL != fgets(temp, sizeof(temp), finp) && NULL == strchr(temp, '\n'))
    1050                 :             :             {
    1051                 :             :                 ;
    1052                 :             :             }
    1053                 :             :         }
    1054                 :             :     }
    1055         [ +  - ]:         984 :     else if (inp_stream->type == INCHI_IOS_TYPE_STRING)
    1056                 :             :     {
    1057                 :             :         /* Read from supplied string representing Molfile */
    1058                 :         984 :         memset(line, 0, line_len); /* djb-rwth: memset_s C11/Annex K variant? */
    1059         [ +  + ]:         984 :         if (NULL != (p = inchi_sgets(line, line_len, inp_stream)) &&
    1060         [ +  + ]:         865 :             NULL == strchr(p, '\n'))
    1061                 :             :         {
    1062                 :             :             char temp[64];
    1063                 :             :             /* bypass up to '\n' or up to end of file whichever comes first */
    1064   [ -  +  -  - ]:           2 :             while (NULL != inchi_sgets(temp, sizeof(temp), inp_stream) && NULL == strchr(temp, '\n'))
    1065                 :             :             {
    1066                 :             :                 ;
    1067                 :             :             }
    1068                 :             :         }
    1069                 :             :     }
    1070                 :             :     else
    1071                 :             :     {
    1072                 :             :         ;
    1073                 :             :     }
    1074                 :             : 
    1075         [ +  + ]:         984 :     if (p)
    1076                 :             :     {
    1077         [ -  + ]:         865 :         if ((q = strchr(line, '\r'))) /* djb-rwth: addressing LLVM warning */
    1078                 :             :         {
    1079                 :             :             /*  fix CR CR LF line terminator. */
    1080                 :           0 :             q[0] = '\n';
    1081                 :           0 :             q[1] = '\0';
    1082                 :             :         }
    1083                 :             :     }
    1084                 :             : 
    1085                 :         984 :     return p;
    1086                 :             : }
    1087                 :             : 
    1088                 :             : 
    1089                 :             : /****************************************************************************
    1090                 :             :     Estimate printf string length.
    1091                 :             : 
    1092                 :             :     The code is based on Microsoft Knowledge Base article Q127038:
    1093                 :             :     "FIX: CString::Format Gives Assertion Failed, Access Violation"
    1094                 :             :     (Related to Microsoft Visual C++, 32-bit Editions, versions 2.0, 2.1)
    1095                 :             : ****************************************************************************/
    1096                 :             : 
    1097                 :             : #define FORCE_ANSI      0x10000
    1098                 :             : #define FORCE_UNICODE   0x20000
    1099                 :             : 
    1100                 :             : /****************************************************************************
    1101                 :             :  Formatting (using wsprintf style formatting)
    1102                 :             : ****************************************************************************/
    1103                 :       75224 : int GetMaxPrintfLength(const char* lpszFormat, va_list argList)
    1104                 :             : {
    1105                 :             :     /*ASSERT(AfxIsValidString(lpszFormat, FALSE));*/
    1106                 :             :     const char* lpsz;
    1107                 :             :     int nMaxLen, nWidth, nPrecision, nModifier, nItemLen;
    1108                 :             : 
    1109                 :       75224 :     nMaxLen = 0;
    1110                 :             :     /* make a guess at the maximum length of the resulting string */
    1111         [ +  + ]:      155423 :     for (lpsz = lpszFormat; *lpsz; lpsz++)
    1112                 :             :     {
    1113                 :             :         /* moved from below for C syntax reason - 2024-09-01 DT */
    1114                 :             :         /* djb-rwth: return values needed for va_arg; djb-rwth: ignoring LLVM warnings: function returning value */
    1115                 :             :         int ivarg;
    1116                 :             :         double dvarg;
    1117                 :             :         void* ivvarg;
    1118                 :             :         int* ipvarg;
    1119                 :             : 
    1120                 :             :         /* handle '%' character, but watch out for '%%' */
    1121   [ +  +  -  + ]:       80199 :         if (*lpsz != '%' || *(++lpsz) == '%')
    1122                 :             :         {
    1123                 :        3274 :             nMaxLen += 1;
    1124                 :        3274 :             continue;
    1125                 :             :         }
    1126                 :             : 
    1127                 :       76925 :         nItemLen = 0;
    1128                 :             : 
    1129                 :             :         /*  handle '%' character with format */
    1130                 :       76925 :         nWidth = 0;
    1131         [ +  - ]:       77253 :         for (; *lpsz; lpsz++)
    1132                 :             :         {
    1133                 :             :             /* check for valid flags */
    1134         [ -  + ]:       77253 :             if (*lpsz == '#')
    1135                 :             :             {
    1136                 :           0 :                 nMaxLen += 2;   /* for '0x' */
    1137                 :             :             }
    1138         [ -  + ]:       77253 :             else if (*lpsz == '*')
    1139                 :             :             {
    1140                 :           0 :                 nWidth = va_arg(argList, int);
    1141                 :             :             }
    1142   [ +  +  +  +  :       77253 :             else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0'
                   +  - ]
    1143         [ +  - ]:       76925 :                 || *lpsz == ' ')
    1144                 :             :             {
    1145                 :             :                 ;
    1146                 :             :             }
    1147                 :             :             else /* hit non-flag character */
    1148                 :             :             {
    1149                 :       76925 :                 break;
    1150                 :             :             }
    1151                 :             :         }
    1152                 :             :         /* get width and skip it */
    1153         [ +  - ]:       76925 :         if (nWidth == 0)
    1154                 :             :         {
    1155                 :             :             /* width indicated by */
    1156                 :       76925 :             nWidth = atoi(lpsz);
    1157   [ +  -  -  + ]:       76925 :             for (; *lpsz && isdigit(*lpsz); lpsz++)
    1158                 :             :             {
    1159                 :             :                 ;
    1160                 :             :             }
    1161                 :             :         }
    1162                 :             :         /*ASSERT(nWidth >= 0);*/
    1163         [ -  + ]:       76925 :         if (nWidth < 0)
    1164                 :             :         {
    1165                 :           0 :             goto exit_error; /* instead of exception */
    1166                 :             :         }
    1167                 :             : 
    1168                 :       76925 :         nPrecision = 0;
    1169         [ -  + ]:       76925 :         if (*lpsz == '.')
    1170                 :             :         {
    1171                 :             :             /* skip past '.' separator (width.precision)*/
    1172                 :           0 :             lpsz++;
    1173                 :             : 
    1174                 :             :             /* get precision and skip it*/
    1175         [ #  # ]:           0 :             if (*lpsz == '*')
    1176                 :             :             {
    1177                 :           0 :                 nPrecision = va_arg(argList, int);
    1178                 :           0 :                 lpsz++;
    1179                 :             :             }
    1180                 :             :             else
    1181                 :             :             {
    1182                 :           0 :                 nPrecision = atoi(lpsz);
    1183   [ #  #  #  # ]:           0 :                 for (; *lpsz && isdigit(*lpsz); lpsz++)
    1184                 :             :                 {
    1185                 :             :                     ;
    1186                 :             :                 }
    1187                 :             :             }
    1188         [ #  # ]:           0 :             if (nPrecision < 0)
    1189                 :             :             {
    1190                 :           0 :                 goto exit_error; /* instead of exception */
    1191                 :             :             }
    1192                 :             :         }
    1193                 :             : 
    1194                 :             :         /* should be on type modifier or specifier */
    1195                 :       76925 :         nModifier = 0;
    1196   [ -  +  -  + ]:       76925 :         switch (*lpsz)
    1197                 :             :         {
    1198                 :             :             /* modifiers that affect size */
    1199                 :           0 :         case 'h':
    1200         [ #  # ]:           0 :             switch (lpsz[1])
    1201                 :             :             {
    1202                 :           0 :             case 'd':
    1203                 :             :             case 'i':
    1204                 :             :             case 'o':
    1205                 :             :             case 'x':
    1206                 :             :             case 'X':
    1207                 :             :             case 'u':
    1208                 :             :                 /* short unsigned, short double, etc. -- added to the original MS example */
    1209                 :             :                 /* ignore the fact that these modifiers do affect size */
    1210                 :           0 :                 lpsz++;
    1211                 :           0 :                 break;
    1212                 :           0 :             default:
    1213                 :           0 :                 nModifier = FORCE_ANSI;
    1214                 :           0 :                 lpsz++;
    1215                 :           0 :                 break;
    1216                 :             :             }
    1217                 :           0 :             break;
    1218                 :          36 :         case 'l':
    1219         [ +  - ]:          36 :             switch (lpsz[1])
    1220                 :             :             {
    1221                 :          36 :             case 'd':
    1222                 :             :             case 'i':
    1223                 :             :             case 'o':
    1224                 :             :             case 'x':
    1225                 :             :             case 'X':
    1226                 :             :             case 'u':
    1227                 :             :             case 'f': /* long float -- post ANSI C */
    1228                 :             :                 /* long unsigned, long double, etc. -- added to the original MS example */
    1229                 :             :                 /* ignore the fact that these modifiers do affect size */
    1230                 :          36 :                 lpsz++;
    1231                 :          36 :                 break;
    1232                 :           0 :             default:
    1233                 :             :                 /*
    1234                 :             :                 nModifier = FORCE_UNICODE;
    1235                 :             :                 lpsz ++;
    1236                 :             :                 break;
    1237                 :             :                 */
    1238                 :           0 :                 goto exit_error;  /* no UNICODE, please */
    1239                 :             :             }
    1240                 :          36 :             break;
    1241                 :             :             /* modifiers that do not affect size */
    1242                 :           0 :         case 'F':
    1243                 :             :         case 'N':
    1244                 :             :         case 'L':
    1245                 :           0 :             lpsz++;
    1246                 :           0 :             break;
    1247                 :             :         }
    1248                 :             : 
    1249                 :             :         /* now should be on specifier */
    1250                 :             : 
    1251   [ +  -  -  +  :       76925 :         switch (*lpsz | nModifier)
                -  -  + ]
    1252                 :             :         {
    1253                 :             :             /* single characters*/
    1254                 :       68797 :         case 'c':
    1255                 :             :         case 'C':
    1256                 :       68797 :             nItemLen = 2;
    1257                 :       68797 :             ivarg = va_arg(argList, int); /* djb-rwth: int return value; ignoring LLVM warning */
    1258                 :       68797 :             break;
    1259                 :           0 :         case 'c' | FORCE_ANSI:
    1260                 :             :         case 'C' | FORCE_ANSI:
    1261                 :           0 :             nItemLen = 2;
    1262                 :           0 :             ivarg = va_arg(argList, int); /* djb-rwth: int return value; ignoring LLVM warning */
    1263                 :           0 :             break;
    1264                 :           0 :         case 'c' | FORCE_UNICODE:
    1265                 :             :         case 'C' | FORCE_UNICODE:
    1266                 :           0 :             goto exit_error;  /* no UNICODE, please */
    1267                 :             :             /*
    1268                 :             :             nItemLen = 2;
    1269                 :             :             va_arg(argList, wchar_t);
    1270                 :             :             break;
    1271                 :             :             */
    1272                 :             : 
    1273                 :             :             /* strings*/
    1274                 :        7867 :         case 's':
    1275                 :             :         case 'S':
    1276                 :        7867 :             nItemLen = (int)strlen(va_arg(argList, char*));
    1277                 :        7867 :             nItemLen = inchi_max(1, nItemLen);
    1278                 :        7867 :             break;
    1279                 :           0 :         case 's' | FORCE_ANSI:
    1280                 :             :         case 'S' | FORCE_ANSI:
    1281                 :           0 :             nItemLen = (int)strlen(va_arg(argList, char*));
    1282                 :           0 :             nItemLen = inchi_max(1, nItemLen);
    1283                 :           0 :             break;
    1284                 :             : 
    1285                 :           0 :         case 's' | FORCE_UNICODE:
    1286                 :             :         case 'S' | FORCE_UNICODE:
    1287                 :           0 :             goto exit_error;  /* no UNICODE, please */
    1288                 :             :             /*
    1289                 :             :             nItemLen = wcslen(va_arg(argList, wchar_t*));
    1290                 :             :             nItemLen = inchi_max(1, nItemLen);
    1291                 :             :             break;
    1292                 :             :             */
    1293                 :             :         }
    1294                 :             : 
    1295                 :             :         /* adjust nItemLen for strings */
    1296         [ +  + ]:       76925 :         if (nItemLen != 0)
    1297                 :             :         {
    1298                 :       76664 :             nItemLen = inchi_max(nItemLen, nWidth);
    1299         [ -  + ]:       76664 :             if (nPrecision != 0)
    1300                 :             :             {
    1301                 :           0 :                 nItemLen = inchi_min(nItemLen, nPrecision);
    1302                 :             :             }
    1303                 :             :         }
    1304                 :             :         else
    1305                 :             :         {
    1306   [ +  +  -  -  :         261 :             switch (*lpsz)
                      - ]
    1307                 :             :             {
    1308                 :             :                 /* integers */
    1309                 :         245 :             case 'd':
    1310                 :             :             case 'i':
    1311                 :             :             case 'u':
    1312                 :             :             case 'x':
    1313                 :             :             case 'X':
    1314                 :             :             case 'o':
    1315                 :         245 :                 ivarg = va_arg(argList, int); /* djb-rwth: int return value; ignoring LLVM warning */
    1316                 :         245 :                 nItemLen = 32;
    1317                 :         245 :                 nItemLen = inchi_max(nItemLen, nWidth + nPrecision);
    1318                 :         245 :                 break;
    1319                 :             : 
    1320                 :          16 :             case 'e':
    1321                 :             :             case 'f':
    1322                 :             :             case 'g':
    1323                 :             :             case 'G':
    1324                 :          16 :                 dvarg = va_arg(argList, double); /* djb-rwth: double return value; ignoring LLVM warning */
    1325                 :          16 :                 nItemLen = 32;
    1326                 :          16 :                 nItemLen = inchi_max(nItemLen, nWidth + nPrecision);
    1327                 :          16 :                 break;
    1328                 :             : 
    1329                 :           0 :             case 'p':
    1330                 :           0 :                 ivvarg = va_arg(argList, void*); /* djb-rwth: void* return value; ignoring LLVM warning */
    1331                 :           0 :                 nItemLen = 32;
    1332                 :           0 :                 nItemLen = inchi_max(nItemLen, nWidth + nPrecision);
    1333                 :           0 :                 break;
    1334                 :             : 
    1335                 :             :                 /* no output */
    1336                 :           0 :             case 'n':
    1337                 :           0 :                 ipvarg = va_arg(argList, int*); /* djb-rwth: int* return value; ignoring LLVM warning */
    1338                 :           0 :                 break;
    1339                 :             : 
    1340                 :           0 :             default:
    1341                 :             :                 /*ASSERT(FALSE);*/  /* unknown formatting option*/
    1342                 :           0 :                 goto exit_error; /* instead of exception */
    1343                 :             :             }
    1344                 :             :         }
    1345                 :             : 
    1346                 :             :         /* adjust nMaxLen for output nItemLen */
    1347                 :       76925 :         nMaxLen += nItemLen;
    1348                 :             :     }
    1349                 :       75224 :     return nMaxLen;
    1350                 :             : 
    1351                 :           0 : exit_error:
    1352                 :           0 :     return -1; /* wrong format */
    1353                 :             : }
    1354                 :             : 
    1355                 :             : 
    1356                 :             : /****************************************************************************
    1357                 :             :     Get at most n-1 chars, plus a null, then advance input's start.
    1358                 :             :     Return emulates fgets()
    1359                 :             : ****************************************************************************/
    1360                 :         986 : char* inchi_sgets(char* s, int n, INCHI_IOSTREAM* ios)
    1361                 :             : {
    1362                 :         986 :     int c = 0;
    1363                 :             :     char* p;
    1364                 :             :     char* inp;
    1365                 :             : 
    1366                 :         986 :     inp = ios->s.pStr + ios->s.nPtr;
    1367                 :             : 
    1368         [ -  + ]:         986 :     if (n <= 0)
    1369                 :             :     {
    1370                 :           0 :         return NULL;
    1371                 :             :     }
    1372                 :             : 
    1373         [ -  + ]:         986 :     if (NULL == inp)
    1374                 :             :     {
    1375                 :             :         /* like EOF */
    1376                 :           0 :         return NULL; /* djb-rwth: addressing coverity ID #499480 -- inp can be NULL */
    1377                 :             :     }
    1378                 :             : 
    1379                 :         986 :     p = s;
    1380                 :             : 
    1381                 :             :     /*
    1382                 :             :     if ( *inp == '\0' )
    1383                 :             :         s = '\0';
    1384                 :             :     else
    1385                 :             :     */
    1386                 :             : 
    1387   [ +  -  +  + ]:       25989 :     while (--n > 0 && (c = *inp++))
    1388                 :             :     {
    1389                 :       25866 :         ios->s.nPtr++;
    1390         [ +  + ]:       25866 :         if ((*p++ = c) == '\n')
    1391                 :             :         {
    1392                 :         863 :             break;
    1393                 :             :         }
    1394                 :             :     }
    1395                 :         986 :     *p = '\0';
    1396                 :             : 
    1397                 :             :     /* printf("\n*** {%-s}",s); */
    1398                 :             : 
    1399         [ +  + ]:         123 :     return (c == '\0' && p == s)
    1400                 :             :         ? NULL /* like EOF reached */
    1401         [ +  + ]:        1109 :         : s;
    1402                 :             : }
    1403                 :             : 
    1404                 :             : 
    1405                 :             : /****************************************************************************
    1406                 :             :  Init expandable buffer of type INCHI_IOS_STRING
    1407                 :             : ****************************************************************************/
    1408                 :         167 : int inchi_strbuf_init(INCHI_IOS_STRING* buf, int start_size, int incr_size)
    1409                 :             : {
    1410                 :         167 :     char* new_str = NULL;
    1411                 :         167 :     memset(buf, 0, sizeof(*buf)); /* djb-rwth: memset_s C11/Annex K variant? */
    1412                 :             : 
    1413         [ -  + ]:         167 :     if (start_size <= 0)
    1414                 :             :     {
    1415                 :           0 :         start_size = INCHI_STRBUF_INITIAL_SIZE;
    1416                 :             :     }
    1417         [ -  + ]:         167 :     if (incr_size <= 0)
    1418                 :             :     {
    1419                 :           0 :         incr_size = INCHI_STRBUF_SIZE_INCREMENT;
    1420                 :             :     }
    1421                 :             : 
    1422                 :         167 :     new_str = (char*)inchi_calloc(start_size, sizeof(char));
    1423                 :             : 
    1424         [ -  + ]:         167 :     if (!new_str)
    1425                 :             :     {
    1426                 :           0 :         return -1;
    1427                 :             :     }
    1428                 :             : 
    1429                 :         167 :     buf->pStr = new_str;
    1430                 :         167 :     buf->nAllocatedLength = start_size;
    1431                 :         167 :     buf->nPtr = incr_size;
    1432                 :             : 
    1433                 :         167 :     return start_size;
    1434                 :             : }
    1435                 :             : 
    1436                 :             : 
    1437                 :             : /****************************************************************************
    1438                 :             :     Reset INCHI_IOS_STRING object holding an expandable buffer string
    1439                 :             :     (place '\0' at the start and do _not_ free memory).
    1440                 :             : ****************************************************************************/
    1441                 :        5467 : void inchi_strbuf_reset(INCHI_IOS_STRING* buf)
    1442                 :             : {
    1443         [ -  + ]:        5467 :     if (!buf)
    1444                 :             :     {
    1445                 :           0 :         return;
    1446                 :             :     }
    1447         [ +  + ]:        5467 :     if (buf->pStr)
    1448                 :             :     {
    1449                 :        5145 :         buf->pStr[0] = '\0';
    1450                 :             :     }
    1451                 :             : 
    1452                 :        5467 :     buf->nUsedLength = buf->nPtr = 0;
    1453                 :             : }
    1454                 :             : 
    1455                 :             : 
    1456                 :             : /****************************************************************************
    1457                 :             : Close INCHI_IOS_STRING object holding an expandable buffer string,
    1458                 :             :     free previously allocated sring memory
    1459                 :             : ****************************************************************************/
    1460                 :         339 : void inchi_strbuf_close(INCHI_IOS_STRING* buf)
    1461                 :             : {
    1462         [ -  + ]:         339 :     if (!buf)
    1463                 :             :     {
    1464                 :           0 :         return;
    1465                 :             :     }
    1466         [ +  - ]:         339 :     if (buf->pStr)
    1467                 :             :     {
    1468         [ +  - ]:         339 :         inchi_free(buf->pStr);
    1469                 :             :     }
    1470                 :             : 
    1471                 :         339 :     memset(buf, 0, sizeof(*buf)); /* djb-rwth: memset_s C11/Annex K variant? */
    1472                 :             : }
    1473                 :             : 
    1474                 :             : 
    1475                 :             : /****************************************************************************/
    1476                 :           1 : int inchi_strbuf_create_copy(INCHI_IOS_STRING* buf2, INCHI_IOS_STRING* buf)
    1477                 :             : {
    1478                 :           1 :     char* new_str = NULL;
    1479                 :             : 
    1480                 :           1 :     new_str = (char*)inchi_calloc(buf->nAllocatedLength, sizeof(char));
    1481                 :           1 :     buf2->pStr = new_str;
    1482         [ -  + ]:           1 :     if (!new_str)
    1483                 :             :     {
    1484                 :           0 :         return -1;
    1485                 :             :     }
    1486                 :           1 :     buf2->nAllocatedLength = buf->nAllocatedLength;
    1487                 :           1 :     buf2->nUsedLength = buf->nUsedLength;
    1488                 :           1 :     buf2->nPtr = buf->nPtr;
    1489                 :             : 
    1490                 :           1 :     return 0;
    1491                 :             : }
    1492                 :             : 
    1493                 :             : 
    1494                 :             : /****************************************************************************
    1495                 :             :  Check size and if necessary expand string buffer in INCHI_IOS_STRING
    1496                 :             : ****************************************************************************/
    1497                 :       73466 : int inchi_strbuf_update(INCHI_IOS_STRING* buf, int new_addition_size)
    1498                 :             : {
    1499                 :             :     int requsted_len;
    1500                 :             : 
    1501         [ -  + ]:       73466 :     if (!buf)
    1502                 :             :     {
    1503                 :           0 :         return -1;
    1504                 :             :     }
    1505                 :             : 
    1506         [ -  + ]:       73466 :     if (new_addition_size <= 0)
    1507                 :             :     {
    1508                 :           0 :         return buf->nAllocatedLength;
    1509                 :             :     }
    1510                 :             : 
    1511                 :       73466 :     requsted_len = buf->nUsedLength + new_addition_size;
    1512                 :             : 
    1513         [ +  + ]:       73466 :     if (requsted_len >= buf->nAllocatedLength)
    1514                 :             :     {
    1515                 :             :         /* Expand */
    1516                 :        4723 :         int  nAddLength = inchi_max(buf->nPtr, new_addition_size);
    1517                 :             :         /* buf->nPtr stores size increment for this buffer */
    1518                 :             :         char* new_str =
    1519                 :        4723 :             (char*)inchi_calloc((long long)buf->nAllocatedLength + (long long)nAddLength,
    1520                 :             :                 sizeof(new_str[0])); /* djb-rwth: cast operators added */
    1521         [ -  + ]:        4723 :         if (!new_str)
    1522                 :             :         {
    1523                 :           0 :             return -1; /* failed */
    1524                 :             :         }
    1525         [ +  + ]:        4723 :         if (buf->pStr)
    1526                 :             :         {
    1527         [ +  - ]:        4458 :             if (buf->nUsedLength > 0)
    1528                 :             :             {
    1529                 :        4458 :                 memcpy(new_str, buf->pStr, sizeof(new_str[0]) * buf->nUsedLength);
    1530                 :             :             }
    1531         [ +  - ]:        4458 :             inchi_free(buf->pStr);
    1532                 :             :         }
    1533                 :        4723 :         buf->pStr = new_str;
    1534                 :        4723 :         buf->nAllocatedLength += nAddLength;
    1535                 :             :     }
    1536                 :             : 
    1537                 :       73466 :     return buf->nAllocatedLength;
    1538                 :             : }
    1539                 :             : 
    1540                 :             : 
    1541                 :             : /****************************************************************************
    1542                 :             :  Add to the end of string in INCHI_IOS_STRING object,
    1543                 :             :     expanding buffer if necessary
    1544                 :             : ****************************************************************************/
    1545                 :       72721 : int inchi_strbuf_printf(INCHI_IOS_STRING* buf, const char* lpszFormat, ...)
    1546                 :             : {
    1547                 :       72721 :     int ret = 0, max_len;
    1548                 :             :     va_list argList;
    1549                 :             : 
    1550         [ -  + ]:       72721 :     if (!buf)
    1551                 :             :     {
    1552                 :           0 :         return -1;
    1553                 :             :     }
    1554                 :             : 
    1555                 :       72721 :     my_va_start(argList, lpszFormat);
    1556                 :       72721 :     max_len = GetMaxPrintfLength(lpszFormat, argList);
    1557                 :       72721 :     va_end(argList);
    1558         [ -  + ]:       72721 :     if (max_len < 0)
    1559                 :             :     {
    1560                 :           0 :         return 0;
    1561                 :             :     }
    1562                 :             : 
    1563                 :       72721 :     inchi_strbuf_update(buf, max_len);
    1564                 :             : 
    1565                 :       72721 :     my_va_start(argList, lpszFormat);
    1566                 :       72721 :     ret = vsprintf(buf->pStr + buf->nUsedLength, lpszFormat, argList);
    1567                 :       72721 :     va_end(argList);
    1568         [ +  - ]:       72721 :     if (ret >= 0)
    1569                 :             :     {
    1570                 :       72721 :         buf->nUsedLength += ret;
    1571                 :             :     }
    1572                 :             : 
    1573                 :       72721 :     return ret;
    1574                 :             : }
    1575                 :             : 
    1576                 :             : 
    1577                 :             : /****************************************************************************
    1578                 :             :     Print to string in INCHI_IOS_STRING object
    1579                 :             :     from specified position 'npos', expanding buffer if necessary.
    1580                 :             :     NB: be careful, intentionally no checks on where is 'npos'!
    1581                 :             : ****************************************************************************/
    1582                 :           0 : int inchi_strbuf_printf_from(INCHI_IOS_STRING* buf,
    1583                 :             :     int npos,
    1584                 :             :     const char* lpszFormat, ...)
    1585                 :             : {
    1586                 :           0 :     int ret = 0, max_len;
    1587                 :             :     va_list argList;
    1588                 :             : 
    1589         [ #  # ]:           0 :     if (!buf)
    1590                 :             :     {
    1591                 :           0 :         return -1;
    1592                 :             :     }
    1593                 :             : 
    1594                 :           0 :     my_va_start(argList, lpszFormat);
    1595                 :           0 :     max_len = GetMaxPrintfLength(lpszFormat, argList);
    1596                 :           0 :     va_end(argList);
    1597         [ #  # ]:           0 :     if (max_len < 0)
    1598                 :             :     {
    1599                 :           0 :         return 0;
    1600                 :             :     }
    1601                 :             : 
    1602                 :           0 :     max_len += npos;
    1603                 :             : 
    1604                 :           0 :     inchi_strbuf_update(buf, max_len);
    1605                 :             : 
    1606                 :           0 :     my_va_start(argList, lpszFormat);
    1607                 :           0 :     ret = vsprintf(buf->pStr + npos, lpszFormat, argList);
    1608                 :           0 :     va_end(argList);
    1609         [ #  # ]:           0 :     if (ret >= 0)
    1610                 :             :     {
    1611                 :           0 :         buf->nUsedLength = npos + ret;
    1612                 :             :     }
    1613                 :             : 
    1614                 :           0 :     return ret;
    1615                 :             : }
    1616                 :             : 
    1617                 :             : 
    1618                 :             : /****************************************************************************
    1619                 :             :     Reads the next line to growing str buf.
    1620                 :             :     Returns n of read chars, -1 at end of file or at error.
    1621                 :             : *****************************************************************************/
    1622                 :           0 : int inchi_strbuf_getline(INCHI_IOS_STRING* buf,
    1623                 :             :     FILE* f,
    1624                 :             :     int crlf2lf,
    1625                 :             :     int preserve_lf)
    1626                 :             : {
    1627                 :             :     int c;
    1628                 :           0 :     inchi_strbuf_reset(buf);
    1629                 :             : 
    1630                 :             :     while (1)
    1631                 :             :     {
    1632                 :           0 :         c = fgetc(f);
    1633         [ #  # ]:           0 :         if (ferror(f))
    1634                 :             :         {
    1635                 :           0 :             return -1;
    1636                 :             :         }
    1637         [ #  # ]:           0 :         if (c == EOF)
    1638                 :             :         {
    1639                 :           0 :             return -1;
    1640                 :             :         }
    1641                 :           0 :         inchi_strbuf_printf(buf, "%c", c);
    1642         [ #  # ]:           0 :         if (c == '\n')
    1643                 :             :         {
    1644                 :           0 :             break;
    1645                 :             :         }
    1646                 :             :     }
    1647                 :             : 
    1648         [ #  # ]:           0 :     if (crlf2lf)
    1649                 :             :     {
    1650         [ #  # ]:           0 :         if (buf->nUsedLength > 2)
    1651                 :             :         {
    1652         [ #  # ]:           0 :             if (buf->pStr[buf->nUsedLength - 2] == '\r')
    1653                 :             :             {
    1654                 :           0 :                 buf->pStr[buf->nUsedLength - 2] = '\n';
    1655                 :           0 :                 buf->pStr[--buf->nUsedLength] = '\0';
    1656                 :             :             }
    1657                 :             :         }
    1658                 :             :     }
    1659         [ #  # ]:           0 :     if (!preserve_lf)
    1660                 :             :     {
    1661                 :           0 :         buf->pStr[--buf->nUsedLength] = '\0';
    1662                 :             :     }
    1663                 :             : 
    1664                 :           0 :     return buf->nUsedLength;
    1665                 :             : }
    1666                 :             : 
    1667                 :             : 
    1668                 :             : 
    1669                 :             : /****************************************************************************
    1670                 :             :     Adds the next line to growing str buf (does not reset buf before adding).
    1671                 :             :     Returns n of read chars, -1 at end of file or at error.
    1672                 :             : ****************************************************************************/
    1673                 :        1830 : int inchi_strbuf_addline(INCHI_IOS_STRING* buf,
    1674                 :             :     INCHI_IOSTREAM* inp_stream,
    1675                 :             :     int crlf2lf,
    1676                 :             :     int preserve_lf)
    1677                 :             : {
    1678                 :             :     int c;
    1679                 :             : 
    1680                 :             :     while (1)
    1681                 :             :     {
    1682                 :       68797 :         c = inchi_ios_str_getc(inp_stream);
    1683         [ -  + ]:       68797 :         if (c == EOF)
    1684                 :             :         {
    1685                 :           0 :             return -1;
    1686                 :             :         }
    1687                 :       68797 :         inchi_strbuf_printf(buf, "%c", c);
    1688         [ +  + ]:       68797 :         if (c == '\n')
    1689                 :             :         {
    1690                 :        1830 :             break;
    1691                 :             :         }
    1692                 :             :     }
    1693         [ +  - ]:        1830 :     if (crlf2lf)
    1694                 :             :     {
    1695         [ +  - ]:        1830 :         if (buf->nUsedLength > 2)
    1696                 :             :         {
    1697         [ -  + ]:        1830 :             if (buf->pStr[buf->nUsedLength - 2] == '\r')
    1698                 :             :             {
    1699                 :           0 :                 buf->pStr[buf->nUsedLength - 2] = '\n';
    1700                 :           0 :                 buf->pStr[--buf->nUsedLength] = '\0';
    1701                 :             :             }
    1702                 :             :         }
    1703                 :             :     }
    1704         [ +  - ]:        1830 :     if (!preserve_lf)
    1705                 :             :     {
    1706                 :        1830 :         buf->pStr[--buf->nUsedLength] = '\0';
    1707                 :             :     }
    1708                 :             : 
    1709                 :        1830 :     return buf->nUsedLength;
    1710                 :             : }
    1711                 :             : 
    1712                 :             : 
    1713                 :             : #if ( defined(_WIN32) && defined(_DEBUG) && defined(_MSC_VER) )
    1714                 :             : #include <windows.h>
    1715                 :             : 
    1716                 :             : 
    1717                 :             : /****************************************************************************/
    1718                 :             : /* djb-rwth: placed as a global variable to avoid function buffer issues */
    1719                 :             : char it_buffer[32767];
    1720                 :             : int _inchi_trace(const char* format, ...)
    1721                 :             : {
    1722                 :             :     /*
    1723                 :             :     TCHAR buffer[32767];
    1724                 :             :     char buffer[32767];
    1725                 :             :     */
    1726                 :             :     int ret;
    1727                 :             : 
    1728                 :             :     va_list argptr;
    1729                 :             :     va_start(argptr, format);
    1730                 :             :     /*wvsprintf(buffer, format, argptr);*/
    1731                 :             :     ret = vsprintf(it_buffer, format, argptr);
    1732                 :             :     va_end(argptr);
    1733                 :             :     OutputDebugString(it_buffer);
    1734                 :             :     return 1;
    1735                 :             : }
    1736                 :             : #else
    1737                 :           0 : int _inchi_trace(const char* format, ...)
    1738                 :             : {
    1739                 :           0 :     return 1;
    1740                 :             : }
    1741                 :             : #endif
    1742                 :             : 
    1743                 :             : 
    1744                 :             : /****************************************************************************
    1745                 :             : Output structure (compound) header for current record
    1746                 :             : ****************************************************************************/
    1747                 :           0 : int Output_RecordInfo(INCHI_IOSTREAM* out_file,
    1748                 :             :     int              num_input_struct,
    1749                 :             :     int              bNoStructLabels,
    1750                 :             :     const char* szSdfLabel,
    1751                 :             :     const char* szSdfValue,
    1752                 :             :     unsigned long    lSdfId,
    1753                 :             :     char* pLF,
    1754                 :             :     char* pTAB)
    1755                 :             : {
    1756         [ #  # ]:           0 :     if (bNoStructLabels)
    1757                 :             :     {
    1758                 :           0 :         return 0;
    1759                 :             :     }
    1760                 :             : 
    1761                 :             : #ifdef TARGET_LIB_FOR_WINCHI
    1762                 :             :     /*out_file->s.nUsedLength = 0;
    1763                 :             :     inchi_ios_reset( out_file );*/
    1764                 :             : #endif
    1765   [ #  #  #  #  :           0 :     if (!(szSdfLabel && szSdfLabel[0]) && !(szSdfValue && szSdfValue[0]))
             #  #  #  # ]
    1766                 :             :     {
    1767                 :           0 :         inchi_ios_print_nodisplay(out_file, "%sStructure: %d", pLF, num_input_struct);
    1768                 :           0 :         inchi_ios_print_nodisplay(out_file, "%s", pTAB);
    1769                 :             :     }
    1770                 :             :     else
    1771                 :             :     {
    1772   [ #  #  #  #  :           0 :         inchi_ios_print_nodisplay(out_file, "%sStructure: %d.%s%s%s%s",
             #  #  #  # ]
    1773                 :             :             pLF, num_input_struct,
    1774   [ #  #  #  #  :           0 :             SDF_LBL_VAL(szSdfLabel, szSdfValue));
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1775                 :             : 
    1776         [ #  # ]:           0 :         if (lSdfId)
    1777                 :             :         {
    1778                 :           0 :             (out_file->s.nUsedLength)--;
    1779                 :           0 :             inchi_ios_print_nodisplay(out_file, ":%lu", lSdfId);
    1780                 :             :         }
    1781                 :           0 :         inchi_ios_print_nodisplay(out_file, "%s", pTAB);
    1782                 :             :     }
    1783                 :             : 
    1784                 :           0 :     return 0;
    1785                 :             : }
        

Generated by: LCOV version 2.0-1