LCOV - code coverage report
Current view: top level - src - ichi_io.c (source / functions) Coverage Total Hit
Test: InChI Unit Test Coverage Lines: 36.5 % 595 217
Test Date: 2026-05-04 07:05:02 Functions: 40.5 % 37 15
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: 23.6 % 454 107

             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                 :         445 : void inchi_ios_init(INCHI_IOSTREAM* ios, int io_type, FILE* f)
      86                 :             : {
      87                 :         445 :     memset(ios, 0, sizeof(*ios)); /* djb-rwth: memset_s C11/Annex K variant? */
      88         [ -  + ]:         445 :     switch (io_type)
      89                 :             :     {
      90                 :           0 :     case INCHI_IOS_TYPE_FILE:
      91                 :           0 :         ios->type = INCHI_IOS_TYPE_FILE;
      92                 :           0 :         break;
      93                 :         445 :     case INCHI_IOS_TYPE_STRING:
      94                 :             :     default:
      95                 :         445 :         ios->type = INCHI_IOS_TYPE_STRING;
      96                 :         445 :         break;
      97                 :             :     }
      98                 :         445 :     ios->f = f;
      99                 :         445 :     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                 :         193 : void inchi_ios_close(INCHI_IOSTREAM* ios)
     230                 :             : {
     231         [ -  + ]:         193 :     if (NULL == ios)
     232                 :             :     {
     233                 :           0 :         return;
     234                 :             :     }
     235         [ +  + ]:         193 :     if (ios->s.pStr)
     236                 :             :     {
     237         [ +  - ]:          85 :         inchi_free(ios->s.pStr);
     238                 :             :     }
     239                 :         193 :     ios->s.pStr = NULL;
     240                 :         193 :     ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
     241                 :             : 
     242   [ -  +  -  -  :         193 :     if (NULL != ios->f && stdout != ios->f && stderr != ios->f && stdin != ios->f)
             -  -  -  - ]
     243                 :             :     {
     244                 :           0 :         fclose(ios->f);
     245                 :             :     }
     246                 :             : 
     247                 :         193 :     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                 :           0 : void inchi_ios_reset(INCHI_IOSTREAM* ios)
     256                 :             : {
     257                 :           0 :     ios->s.pStr = NULL;
     258                 :           0 :     ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
     259   [ #  #  #  #  :           0 :     if (NULL != ios->f && stdout != ios->f && stderr != ios->f && stdin != ios->f)
             #  #  #  # ]
     260                 :             :     {
     261                 :           0 :         fclose(ios->f);
     262                 :             :     }
     263                 :             : 
     264                 :           0 :     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                 :       64247 : int inchi_ios_str_getc(INCHI_IOSTREAM* ios)
     295                 :             : {
     296                 :             :     int c;
     297         [ +  - ]:       64247 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     298                 :             :     {
     299         [ +  - ]:       64247 :         if (ios->s.nPtr < ios->s.nUsedLength)
     300                 :             :         {
     301                 :       64247 :             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                 :         797 : int inchi_ios_print(INCHI_IOSTREAM* ios, const char* lpszFormat, ...)
     478                 :             : {
     479                 :         797 :     int ret = 0, ret2 = 0;
     480                 :             :     va_list argList;
     481                 :             : 
     482         [ -  + ]:         797 :     if (!ios)
     483                 :             :     {
     484                 :           0 :         return -1;
     485                 :             :     }
     486                 :             : 
     487         [ +  - ]:         797 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     488                 :             :     {
     489                 :             :         /* output to string buffer */
     490                 :             :         int max_len;
     491                 :         797 :         my_va_start(argList, lpszFormat);
     492                 :         797 :         max_len = GetMaxPrintfLength(lpszFormat, argList);
     493                 :         797 :         va_end(argList);
     494         [ +  - ]:         797 :         if (max_len >= 0)
     495                 :             :         {
     496                 :             :             /* djb-rwth: fixing oss-fuzz issue #30152 */
     497                 :         797 :             int  nAddLength = inchi_max(INCHI_ADD_STR_LEN, max_len);
     498                 :         797 :             long long new_str_len = (long long)ios->s.nAllocatedLength + (long long)nAddLength;
     499         [ -  + ]:         797 :             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                 :         797 :             my_va_start(argList, lpszFormat);
     523                 :         797 :             ret = vsprintf(ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList); /* djb-rwth: not using vsnprintf due to variable length argument */
     524                 :         797 :             va_end(argList);
     525         [ +  - ]:         797 :             if (ret >= 0)
     526                 :             :             {
     527                 :         797 :                 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                 :         797 :             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                 :         450 : int inchi_ios_print_nodisplay( INCHI_IOSTREAM * ios,
     605                 :             :                                const char* lpszFormat,
     606                 :             :                                ... )
     607                 :             : {
     608                 :             :     va_list argList;
     609                 :             : 
     610         [ -  + ]:         450 :     if (!ios)
     611                 :             :     {
     612                 :           0 :         return -1;
     613                 :             :     }
     614                 :             : 
     615         [ +  - ]:         450 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     616                 :             :     {
     617                 :             :         /* output to string buffer */
     618                 :         450 :         int ret = 0, max_len;
     619                 :         450 :         my_va_start( argList, lpszFormat );
     620                 :         450 :         max_len = GetMaxPrintfLength( lpszFormat, argList );
     621                 :         450 :         va_end( argList );
     622         [ +  - ]:         450 :         if (max_len >= 0)
     623                 :             :         {
     624                 :             :             /* djb-rwth: fixing oss-fuzz issue #30163 */
     625                 :         450 :             int  nAddLength = inchi_max(INCHI_ADD_STR_LEN, max_len);
     626                 :         450 :             long long new_str_len = (long long)ios->s.nAllocatedLength + (long long)nAddLength;
     627         [ +  + ]:         450 :             if (ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len)
     628                 :             :             {
     629                 :             :                 /* enlarge output string */
     630                 :          54 :                 char* new_str = (char*)inchi_calloc(new_str_len, sizeof(new_str[0])); /* djb-rwth: cast operators added */
     631         [ +  - ]:          54 :                 if (new_str)
     632                 :             :                 {
     633         [ -  + ]:          54 :                     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                 :          54 :                     ios->s.pStr = new_str;
     642                 :          54 :                     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                 :         450 :             my_va_start(argList, lpszFormat);
     652                 :         450 :             ret = vsprintf(ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList); /* djb-rwth: not using vsnprintf due to variable length argument; fixing GHI #71 */
     653                 :         450 :             va_end(argList);
     654         [ +  - ]:         450 :             if (ret >= 0)
     655                 :             :             {
     656                 :         450 :                 ios->s.nUsedLength += ret;
     657                 :             :             }
     658                 :         450 :             return ret;
     659                 :             :         }
     660                 :           0 :         return -1;
     661                 :             :     }
     662                 :             : 
     663         [ #  # ]:           0 :     else if (ios->type == INCHI_IOS_TYPE_FILE)
     664                 :             :     {
     665                 :           0 :         my_va_start( argList, lpszFormat );
     666                 :           0 :         inchi_print_nodisplay( ios->f, lpszFormat, argList );
     667                 :           0 :         va_end( argList );
     668                 :             :     }
     669                 :             : 
     670                 :             :     /* no output */
     671                 :           0 :     return 0;
     672                 :             : }
     673                 :             : 
     674                 :             : 
     675                 :             : /****************************************************************************
     676                 :             :     This function's flushes previously hidden output and resets string stream
     677                 :             :     returns n chars on success, otherwise -1
     678                 :             : ****************************************************************************/
     679                 :           0 : int inchi_ios_flush_not_displayed(INCHI_IOSTREAM* ios)
     680                 :             : {
     681                 :           0 :     char* obuf = NULL;
     682                 :             :     int ret;
     683                 :             : 
     684         [ #  # ]:           0 :     if (!ios)
     685                 :             :     {
     686                 :           0 :         return -1;
     687                 :             :     }
     688                 :             : 
     689                 :           0 :     obuf = (char*)inchi_calloc((long long)ios->s.nUsedLength + 1, sizeof(char)); /* djb-rwth: cast operator added */
     690                 :             : 
     691         [ #  # ]:           0 :     if (!obuf)
     692                 :             :     {
     693                 :           0 :         return -1;
     694                 :             :     }
     695                 :             : 
     696                 :           0 :     strcpy(obuf, ios->s.pStr);
     697                 :           0 :     ios->s.nUsedLength = 0;
     698                 :           0 :     ret = inchi_ios_print(ios, "%s", obuf);
     699         [ #  # ]:           0 :     inchi_free(obuf);
     700                 :             : 
     701                 :           0 :     return ret;
     702                 :             : }
     703                 :             : 
     704                 :             : 
     705                 :             : /****************************************************************************
     706                 :             :  Print to string buffer or to file+stderr
     707                 :             : ****************************************************************************/
     708                 :           9 : int inchi_ios_eprint(INCHI_IOSTREAM* ios, const char* lpszFormat, ...)
     709                 :             : {
     710                 :           9 :     int ret = 0, ret2 = 0;
     711                 :             :     va_list argList;
     712                 :             : 
     713         [ -  + ]:           9 :     if (!ios)
     714                 :             :     {
     715                 :           0 :         return -1;
     716                 :             :     }
     717                 :             : 
     718         [ +  - ]:           9 :     if (ios->type == INCHI_IOS_TYPE_STRING)
     719                 :             :         /* was #if ( defined(TARGET_API_LIB) || defined(INCHI_STANDALONE_EXE) ) */
     720                 :             :     {
     721                 :             :         /* output to string buffer */
     722                 :           9 :         int max_len, nAddLength = 0;
     723                 :           9 :         char* new_str = NULL;
     724                 :             : 
     725                 :           9 :         my_va_start(argList, lpszFormat);
     726                 :           9 :         max_len = GetMaxPrintfLength(lpszFormat, argList);
     727                 :           9 :         va_end(argList);
     728                 :             : 
     729         [ +  - ]:           9 :         if (max_len >= 0)
     730                 :             :         {
     731         [ +  + ]:           9 :             if (ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len)
     732                 :             :             {
     733                 :             :                 /* enlarge output string */
     734                 :           7 :                 nAddLength = inchi_max(INCHI_ADD_STR_LEN, max_len);
     735                 :           7 :                 new_str = (char*)inchi_calloc((long long)ios->s.nAllocatedLength + (long long)nAddLength, sizeof(new_str[0])); /* djb-rwth: cast operators added */
     736         [ +  - ]:           7 :                 if (new_str)
     737                 :             :                 {
     738         [ -  + ]:           7 :                     if (ios->s.pStr)
     739                 :             :                     {
     740         [ #  # ]:           0 :                         if (ios->s.nUsedLength > 0)
     741                 :             :                         {
     742                 :           0 :                             memcpy(new_str, ios->s.pStr, sizeof(new_str[0]) * ios->s.nUsedLength);
     743                 :             :                         }
     744         [ #  # ]:           0 :                         inchi_free(ios->s.pStr);
     745                 :             :                     }
     746                 :           7 :                     ios->s.pStr = new_str;
     747                 :           7 :                     ios->s.nAllocatedLength += nAddLength;
     748                 :             :                 }
     749                 :             :                 else
     750                 :             :                 {
     751                 :           0 :                     return -1; /* failed */
     752                 :             :                 }
     753                 :             :             }
     754                 :             : 
     755                 :             :             /* output */
     756                 :           9 :             my_va_start(argList, lpszFormat);
     757                 :           9 :             ret = vsprintf(ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList);
     758                 :           9 :             va_end(argList);
     759         [ +  - ]:           9 :             if (ret >= 0)
     760                 :             :             {
     761                 :           9 :                 ios->s.nUsedLength += ret;
     762                 :             :             }
     763                 :           9 :             return ret;
     764                 :             :         }
     765                 :           0 :         return -1;
     766                 :             :     }
     767                 :             : 
     768         [ #  # ]:           0 :     else if (ios->type == INCHI_IOS_TYPE_FILE)
     769                 :             :     {
     770         [ #  # ]:           0 :         if (ios->f)
     771                 :             :         {
     772                 :             :             /* output to plain file */
     773                 :           0 :             my_va_start(argList, lpszFormat);
     774                 :           0 :             ret = inchi_vfprintf(ios->f, lpszFormat, argList);
     775                 :           0 :             va_end(argList);
     776                 :             :             /*  No output to stderr from within dll or GUI program */
     777                 :             : #if ( !defined(TARGET_API_LIB) && !defined(TARGET_LIB_FOR_WINCHI) )
     778                 :             :             if (ios->f != stderr)
     779                 :             :             {
     780                 :             :                 my_va_start(argList, lpszFormat);
     781                 :             :                 ret2 = vfprintf(stderr, lpszFormat, argList);
     782                 :             :                 va_end(argList);
     783                 :             :             }
     784                 :             : #endif
     785         [ #  # ]:           0 :             return ret ? ret : ret2;
     786                 :             :         }
     787                 :             :     }
     788                 :             : 
     789                 :             :     /* no output */
     790                 :           0 :     return 0;
     791                 :             : }
     792                 :             : 
     793                 :             : 
     794                 :             : /*    PLAIN FILE OPERATIONS */
     795                 :             : 
     796                 :             : 
     797                 :             : /****************************************************************************
     798                 :             :  Print to file, echoing to stderr
     799                 :             : ****************************************************************************/
     800                 :           0 : int inchi_fprintf(FILE* f, const char* lpszFormat, ...)
     801                 :             : {
     802                 :           0 :     int ret = 0, ret2 = 0;
     803                 :             :     va_list argList;
     804         [ #  # ]:           0 :     if (f)
     805                 :             :     {
     806                 :           0 :         my_va_start(argList, lpszFormat);
     807                 :           0 :         ret = inchi_vfprintf(f, lpszFormat, argList);
     808                 :           0 :         va_end(argList);
     809                 :             :         /*  No output to stderr from within dll or GUI program */
     810                 :             : #if ( !defined(TARGET_API_LIB) && !defined(TARGET_LIB_FOR_WINCHI) )
     811                 :             :         if (f != stderr)
     812                 :             :         {
     813                 :             :             my_va_start(argList, lpszFormat);
     814                 :             :             ret2 = vfprintf(stderr, lpszFormat, argList);
     815                 :             :             va_end(argList);
     816                 :             :         }
     817                 :             : #endif
     818         [ #  # ]:           0 :         return ret ? ret : ret2;
     819                 :             :     }
     820                 :             : 
     821                 :           0 :     return 0;
     822                 :             : }
     823                 :             : 
     824                 :             : 
     825                 :             : /****************************************************************************
     826                 :             :  Print to file
     827                 :             : ****************************************************************************/
     828                 :           0 : int inchi_vfprintf(FILE* f, const char* lpszFormat, va_list argList)
     829                 :             : {
     830                 :           0 :     int ret = 0;
     831   [ #  #  #  # ]:           0 :     if (lpszFormat && lpszFormat[0]) /* djb-rwth: condition added as lpszFormat == 0 may lead to undefined ret value */
     832                 :             :     {
     833   [ #  #  #  # ]:           0 :         if (f == stderr && '\r' == lpszFormat[strlen(lpszFormat) - 1])
     834                 :             :         {
     835                 :             : #define CONSOLE_LINE_LEN 80
     836                 :             : #ifndef COMPILE_ANSI_ONLY
     837                 :             :             char szLine[CONSOLE_LINE_LEN];
     838                 :             : 
     839                 :             :             ret = _vsnprintf(szLine, CONSOLE_LINE_LEN - 1, lpszFormat, argList);
     840                 :             : 
     841                 :             :             if (ret < 0)
     842                 :             :             {
     843                 :             :                 /*  output is longer than the console line */
     844                 :             :                 /* Fixed bug: (CONSOLE_LINE_LEN-4) --> (CONSOLE_LINE_LEN-4-1) 11-22-08 IPl */
     845                 :             :                 strcpy(szLine + CONSOLE_LINE_LEN - 5, "...\r");
     846                 :             :             }
     847                 :             : 
     848                 :             :             fputs(szLine, f);
     849                 :             : #else
     850                 :           0 :             ret = vfprintf(f, lpszFormat, argList);
     851                 :             : #endif
     852                 :             : #undef CONSOLE_LINE_LEN
     853                 :             :         }
     854                 :             :         else
     855                 :             :         {
     856                 :           0 :             ret = vfprintf(f, lpszFormat, argList);
     857                 :             :         }
     858                 :             :     }
     859                 :             : 
     860                 :           0 :     return ret;
     861                 :             : }
     862                 :             : 
     863                 :             : 
     864                 :             : /****************************************************************************
     865                 :             :     This function's output should not be displayed in the output pane
     866                 :             : ****************************************************************************/
     867                 :           0 : int inchi_print_nodisplay(FILE* f, const char* lpszFormat, ...)
     868                 :             : {
     869                 :           0 :     int ret = 0;
     870                 :             :     va_list argList;
     871                 :             :     FILE* fi;
     872                 :             : 
     873         [ #  # ]:           0 :     if (f)
     874                 :             :     {
     875                 :           0 :         fi = f;
     876                 :             :     }
     877                 :             :     else
     878                 :             :     {
     879                 :           0 :         fi = stdout;
     880                 :             :     }
     881                 :             : 
     882                 :           0 :     my_va_start(argList, lpszFormat);
     883                 :           0 :     ret = vfprintf(fi, lpszFormat, argList);
     884                 :           0 :     va_end(argList);
     885                 :           0 :     return ret;
     886                 :             : }
     887                 :             : 
     888                 :             : 
     889                 :             : #if ( FIX_READ_LONG_LINE_BUG == 1 )
     890                 :             : 
     891                 :             : 
     892                 :             : /****************************************************************************/
     893                 :           0 : int inchi_fgetsLfTab(char* szLine, int len, FILE* f)
     894                 :             : {
     895                 :             :     int  length;
     896                 :             :     char* p;
     897                 :             :     char szSkip[256];
     898                 :           0 :     int  bTooLongLine = 0;
     899                 :             :     do
     900                 :             :     {
     901                 :           0 :         p = inchi_fgetsTab(szLine, len, f);
     902         [ #  # ]:           0 :         if (!p)
     903                 :             :         {
     904                 :           0 :             return -1; /* end of file or cannot read */
     905                 :             :         }
     906   [ #  #  #  # ]:           0 :         bTooLongLine = ((int)strlen(szLine) == len - 1 && szLine[len - 2] != '\n');
     907                 :           0 :         lrtrim(szLine, &length);
     908         [ #  # ]:           0 :     } while (!length);
     909         [ #  # ]:           0 :     if (bTooLongLine)
     910                 :             :     {
     911         [ #  # ]:           0 :         while ((p = inchi_fgetsTab(szSkip, sizeof(szSkip) - 1, f))) /* djb-rwth: ignoring LLVM warning: function returning value */
     912                 :             :         {
     913         [ #  # ]:           0 :             if (strchr(szSkip, '\n'))
     914                 :           0 :                 break;
     915                 :             :         }
     916                 :             :     }
     917                 :             : 
     918                 :           0 :     return length;
     919                 :             : }
     920                 :             : 
     921                 :             : 
     922                 :             : #else
     923                 :             : 
     924                 :             : 
     925                 :             : /****************************************************************************/
     926                 :             : int inchi_fgetsLfTab(char* szLine, int len, FILE* f)
     927                 :             : {
     928                 :             :     int  length;
     929                 :             :     char* p;
     930                 :             :     char szSkip[256];
     931                 :             :     int  bTooLongLine = 0;
     932                 :             :     do
     933                 :             :     {
     934                 :             :         p = inchi_fgetsTab(szLine, len - 1, f);
     935                 :             :         if (!p)
     936                 :             :         {
     937                 :             :             return -1; /* end of file or cannot read */
     938                 :             :         }
     939                 :             :         szLine[len - 1] = '\0';
     940                 :             :         /*
     941                 :             :         bTooLongLine = !strchr( szLine, '\n' );
     942                 :             :         */
     943                 :             :         bTooLongLine = (!p && ((int)strlen(szLine)) == len - 2);
     944                 :             :         lrtrim(szLine, &length);
     945                 :             :     } while (!length);
     946                 :             :     if (bTooLongLine)
     947                 :             :     {
     948                 :             :         while (p = inchi_fgetsTab(szSkip, sizeof(szSkip) - 1, f))
     949                 :             :         {
     950                 :             :             szSkip[sizeof(szSkip) - 1] = '\0';
     951                 :             :             if (strchr(szSkip, '\n'))
     952                 :             :                 break;
     953                 :             :         }
     954                 :             :     }
     955                 :             :     return length;
     956                 :             : }
     957                 :             : #endif
     958                 :             : 
     959                 :             : 
     960                 :             : /****************************************************************************
     961                 :             :     Read up to tab or LF but not more than len chars;
     962                 :             :     if empty line, read further until a non-empty line;
     963                 :             :     remove leading and trailing white spaces;
     964                 :             :     keep zero termination
     965                 :             : ****************************************************************************/
     966                 :           0 : char* inchi_fgetsTab(char* szLine, int len, FILE* f)
     967                 :             : {
     968                 :           0 :     int  length = 0, c = 0;
     969                 :           0 :     len--;
     970   [ #  #  #  # ]:           0 :     while (length < len && EOF != (c = fgetc(f)))
     971                 :             :     {
     972         [ #  # ]:           0 :         if (c == '\t')
     973                 :             :         {
     974                 :           0 :             c = '\n';
     975                 :             :         }
     976                 :           0 :         szLine[length++] = (char)c;
     977         [ #  # ]:           0 :         if (c == '\n')
     978                 :             :         {
     979                 :           0 :             break;
     980                 :             :         }
     981                 :             :     }
     982   [ #  #  #  # ]:           0 :     if (!length && EOF == c)
     983                 :             :     {
     984                 :           0 :         return NULL;
     985                 :             :     }
     986                 :           0 :     szLine[length] = '\0';
     987                 :             : 
     988                 :           0 :     return szLine;
     989                 :             : }
     990                 :             : 
     991                 :             : 
     992                 :             : /****************************************************************************
     993                 :             :     Read up to LF but not more than line_len bytes;
     994                 :             :     if input line is too long, quietly ignore the rest of the line
     995                 :             : ****************************************************************************/
     996                 :         388 : char* inchi_fgetsLf(char* line, int line_len, INCHI_IOSTREAM* inp_stream)
     997                 :             : {
     998                 :         388 :     char* p = NULL, * q;
     999                 :         388 :     FILE* finp = NULL;
    1000                 :             : 
    1001         [ -  + ]:         388 :     if (inp_stream->type == INCHI_IOS_TYPE_FILE)
    1002                 :             :     {
    1003                 :             :         /* Read from file */
    1004                 :           0 :         finp = inp_stream->f;
    1005                 :           0 :         memset(line, 0, line_len); /* djb-rwth: memset_s C11/Annex K variant? */
    1006         [ #  # ]:           0 :         if (NULL != (p = fgets(line, line_len, finp)) &&
    1007         [ #  # ]:           0 :             NULL == strchr(p, '\n'))
    1008                 :             :         {
    1009                 :             :             char temp[64];
    1010                 :             :             /* bypass up to '\n' or up to end of file whichever comes first */
    1011   [ #  #  #  # ]:           0 :             while (NULL != fgets(temp, sizeof(temp), finp) && NULL == strchr(temp, '\n'))
    1012                 :             :             {
    1013                 :             :                 ;
    1014                 :             :             }
    1015                 :             :         }
    1016                 :             :     }
    1017         [ +  - ]:         388 :     else if (inp_stream->type == INCHI_IOS_TYPE_STRING)
    1018                 :             :     {
    1019                 :             :         /* Read from supplied string representing Molfile */
    1020                 :         388 :         memset(line, 0, line_len); /* djb-rwth: memset_s C11/Annex K variant? */
    1021         [ +  + ]:         388 :         if (NULL != (p = inchi_sgets(line, line_len, inp_stream)) &&
    1022         [ +  + ]:         334 :             NULL == strchr(p, '\n'))
    1023                 :             :         {
    1024                 :             :             char temp[64];
    1025                 :             :             /* bypass up to '\n' or up to end of file whichever comes first */
    1026   [ -  +  -  - ]:           1 :             while (NULL != inchi_sgets(temp, sizeof(temp), inp_stream) && NULL == strchr(temp, '\n'))
    1027                 :             :             {
    1028                 :             :                 ;
    1029                 :             :             }
    1030                 :             :         }
    1031                 :             :     }
    1032                 :             :     else
    1033                 :             :     {
    1034                 :             :         ;
    1035                 :             :     }
    1036                 :             : 
    1037         [ +  + ]:         388 :     if (p)
    1038                 :             :     {
    1039         [ -  + ]:         334 :         if ((q = strchr(line, '\r'))) /* djb-rwth: addressing LLVM warning */
    1040                 :             :         {
    1041                 :             :             /*  fix CR CR LF line terminator. */
    1042                 :           0 :             q[0] = '\n';
    1043                 :           0 :             q[1] = '\0';
    1044                 :             :         }
    1045                 :             :     }
    1046                 :             : 
    1047                 :         388 :     return p;
    1048                 :             : }
    1049                 :             : 
    1050                 :             : 
    1051                 :             : /****************************************************************************
    1052                 :             :     Estimate printf string length.
    1053                 :             : 
    1054                 :             :     The code is based on Microsoft Knowledge Base article Q127038:
    1055                 :             :     "FIX: CString::Format Gives Assertion Failed, Access Violation"
    1056                 :             :     (Related to Microsoft Visual C++, 32-bit Editions, versions 2.0, 2.1)
    1057                 :             : ****************************************************************************/
    1058                 :             : 
    1059                 :             : #define FORCE_ANSI      0x10000
    1060                 :             : #define FORCE_UNICODE   0x20000
    1061                 :             : 
    1062                 :             : /****************************************************************************
    1063                 :             :  Formatting (using wsprintf style formatting)
    1064                 :             : ****************************************************************************/
    1065                 :       68268 : int GetMaxPrintfLength(const char* lpszFormat, va_list argList)
    1066                 :             : {
    1067                 :             :     /*ASSERT(AfxIsValidString(lpszFormat, FALSE));*/
    1068                 :             :     const char* lpsz;
    1069                 :             :     int nMaxLen, nWidth, nPrecision, nModifier, nItemLen;
    1070                 :             : 
    1071                 :       68268 :     nMaxLen = 0;
    1072                 :             :     /* make a guess at the maximum length of the resulting string */
    1073         [ +  + ]:      138550 :     for (lpsz = lpszFormat; *lpsz; lpsz++)
    1074                 :             :     {
    1075                 :             :         /* moved from below for C syntax reason - 2024-09-01 DT */
    1076                 :             :         /* djb-rwth: return values needed for va_arg; djb-rwth: ignoring LLVM warnings: function returning value */
    1077                 :             :         int ivarg;
    1078                 :             :         double dvarg;
    1079                 :             :         void* ivvarg;
    1080                 :             :         int* ipvarg;
    1081                 :             : 
    1082                 :             :         /* handle '%' character, but watch out for '%%' */
    1083   [ +  +  -  + ]:       70282 :         if (*lpsz != '%' || *(++lpsz) == '%')
    1084                 :             :         {
    1085                 :        1351 :             nMaxLen += 1;
    1086                 :        1351 :             continue;
    1087                 :             :         }
    1088                 :             : 
    1089                 :       68931 :         nItemLen = 0;
    1090                 :             : 
    1091                 :             :         /*  handle '%' character with format */
    1092                 :       68931 :         nWidth = 0;
    1093         [ +  - ]:       69148 :         for (; *lpsz; lpsz++)
    1094                 :             :         {
    1095                 :             :             /* check for valid flags */
    1096         [ -  + ]:       69148 :             if (*lpsz == '#')
    1097                 :             :             {
    1098                 :           0 :                 nMaxLen += 2;   /* for '0x' */
    1099                 :             :             }
    1100         [ -  + ]:       69148 :             else if (*lpsz == '*')
    1101                 :             :             {
    1102                 :           0 :                 nWidth = va_arg(argList, int);
    1103                 :             :             }
    1104   [ +  +  +  +  :       69148 :             else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0'
                   +  - ]
    1105         [ +  - ]:       68931 :                 || *lpsz == ' ')
    1106                 :             :             {
    1107                 :             :                 ;
    1108                 :             :             }
    1109                 :             :             else /* hit non-flag character */
    1110                 :             :             {
    1111                 :       68931 :                 break;
    1112                 :             :             }
    1113                 :             :         }
    1114                 :             :         /* get width and skip it */
    1115         [ +  - ]:       68931 :         if (nWidth == 0)
    1116                 :             :         {
    1117                 :             :             /* width indicated by */
    1118                 :       68931 :             nWidth = atoi(lpsz);
    1119   [ +  -  -  + ]:       68931 :             for (; *lpsz && isdigit(*lpsz); lpsz++)
    1120                 :             :             {
    1121                 :             :                 ;
    1122                 :             :             }
    1123                 :             :         }
    1124                 :             :         /*ASSERT(nWidth >= 0);*/
    1125         [ -  + ]:       68931 :         if (nWidth < 0)
    1126                 :             :         {
    1127                 :           0 :             goto exit_error; /* instead of exception */
    1128                 :             :         }
    1129                 :             : 
    1130                 :       68931 :         nPrecision = 0;
    1131         [ -  + ]:       68931 :         if (*lpsz == '.')
    1132                 :             :         {
    1133                 :             :             /* skip past '.' separator (width.precision)*/
    1134                 :           0 :             lpsz++;
    1135                 :             : 
    1136                 :             :             /* get precision and skip it*/
    1137         [ #  # ]:           0 :             if (*lpsz == '*')
    1138                 :             :             {
    1139                 :           0 :                 nPrecision = va_arg(argList, int);
    1140                 :           0 :                 lpsz++;
    1141                 :             :             }
    1142                 :             :             else
    1143                 :             :             {
    1144                 :           0 :                 nPrecision = atoi(lpsz);
    1145   [ #  #  #  # ]:           0 :                 for (; *lpsz && isdigit(*lpsz); lpsz++)
    1146                 :             :                 {
    1147                 :             :                     ;
    1148                 :             :                 }
    1149                 :             :             }
    1150         [ #  # ]:           0 :             if (nPrecision < 0)
    1151                 :             :             {
    1152                 :           0 :                 goto exit_error; /* instead of exception */
    1153                 :             :             }
    1154                 :             :         }
    1155                 :             : 
    1156                 :             :         /* should be on type modifier or specifier */
    1157                 :       68931 :         nModifier = 0;
    1158   [ -  +  -  + ]:       68931 :         switch (*lpsz)
    1159                 :             :         {
    1160                 :             :             /* modifiers that affect size */
    1161                 :           0 :         case 'h':
    1162         [ #  # ]:           0 :             switch (lpsz[1])
    1163                 :             :             {
    1164                 :           0 :             case 'd':
    1165                 :             :             case 'i':
    1166                 :             :             case 'o':
    1167                 :             :             case 'x':
    1168                 :             :             case 'X':
    1169                 :             :             case 'u':
    1170                 :             :                 /* short unsigned, short double, etc. -- added to the original MS example */
    1171                 :             :                 /* ignore the fact that these modifiers do affect size */
    1172                 :           0 :                 lpsz++;
    1173                 :           0 :                 break;
    1174                 :           0 :             default:
    1175                 :           0 :                 nModifier = FORCE_ANSI;
    1176                 :           0 :                 lpsz++;
    1177                 :           0 :                 break;
    1178                 :             :             }
    1179                 :           0 :             break;
    1180                 :           9 :         case 'l':
    1181         [ +  - ]:           9 :             switch (lpsz[1])
    1182                 :             :             {
    1183                 :           9 :             case 'd':
    1184                 :             :             case 'i':
    1185                 :             :             case 'o':
    1186                 :             :             case 'x':
    1187                 :             :             case 'X':
    1188                 :             :             case 'u':
    1189                 :             :             case 'f': /* long float -- post ANSI C */
    1190                 :             :                 /* long unsigned, long double, etc. -- added to the original MS example */
    1191                 :             :                 /* ignore the fact that these modifiers do affect size */
    1192                 :           9 :                 lpsz++;
    1193                 :           9 :                 break;
    1194                 :           0 :             default:
    1195                 :             :                 /*
    1196                 :             :                 nModifier = FORCE_UNICODE;
    1197                 :             :                 lpsz ++;
    1198                 :             :                 break;
    1199                 :             :                 */
    1200                 :           0 :                 goto exit_error;  /* no UNICODE, please */
    1201                 :             :             }
    1202                 :           9 :             break;
    1203                 :             :             /* modifiers that do not affect size */
    1204                 :           0 :         case 'F':
    1205                 :             :         case 'N':
    1206                 :             :         case 'L':
    1207                 :           0 :             lpsz++;
    1208                 :           0 :             break;
    1209                 :             :         }
    1210                 :             : 
    1211                 :             :         /* now should be on specifier */
    1212                 :             : 
    1213   [ +  -  -  +  :       68931 :         switch (*lpsz | nModifier)
                -  -  + ]
    1214                 :             :         {
    1215                 :             :             /* single characters*/
    1216                 :       64247 :         case 'c':
    1217                 :             :         case 'C':
    1218                 :       64247 :             nItemLen = 2;
    1219                 :       64247 :             ivarg = va_arg(argList, int); /* djb-rwth: int return value; ignoring LLVM warning */
    1220                 :       64247 :             break;
    1221                 :           0 :         case 'c' | FORCE_ANSI:
    1222                 :             :         case 'C' | FORCE_ANSI:
    1223                 :           0 :             nItemLen = 2;
    1224                 :           0 :             ivarg = va_arg(argList, int); /* djb-rwth: int return value; ignoring LLVM warning */
    1225                 :           0 :             break;
    1226                 :           0 :         case 'c' | FORCE_UNICODE:
    1227                 :             :         case 'C' | FORCE_UNICODE:
    1228                 :           0 :             goto exit_error;  /* no UNICODE, please */
    1229                 :             :             /*
    1230                 :             :             nItemLen = 2;
    1231                 :             :             va_arg(argList, wchar_t);
    1232                 :             :             break;
    1233                 :             :             */
    1234                 :             : 
    1235                 :             :             /* strings*/
    1236                 :        4612 :         case 's':
    1237                 :             :         case 'S':
    1238                 :        4612 :             nItemLen = (int)strlen(va_arg(argList, char*));
    1239                 :        4612 :             nItemLen = inchi_max(1, nItemLen);
    1240                 :        4612 :             break;
    1241                 :           0 :         case 's' | FORCE_ANSI:
    1242                 :             :         case 'S' | FORCE_ANSI:
    1243                 :           0 :             nItemLen = (int)strlen(va_arg(argList, char*));
    1244                 :           0 :             nItemLen = inchi_max(1, nItemLen);
    1245                 :           0 :             break;
    1246                 :             : 
    1247                 :           0 :         case 's' | FORCE_UNICODE:
    1248                 :             :         case 'S' | FORCE_UNICODE:
    1249                 :           0 :             goto exit_error;  /* no UNICODE, please */
    1250                 :             :             /*
    1251                 :             :             nItemLen = wcslen(va_arg(argList, wchar_t*));
    1252                 :             :             nItemLen = inchi_max(1, nItemLen);
    1253                 :             :             break;
    1254                 :             :             */
    1255                 :             :         }
    1256                 :             : 
    1257                 :             :         /* adjust nItemLen for strings */
    1258         [ +  + ]:       68931 :         if (nItemLen != 0)
    1259                 :             :         {
    1260                 :       68859 :             nItemLen = inchi_max(nItemLen, nWidth);
    1261         [ -  + ]:       68859 :             if (nPrecision != 0)
    1262                 :             :             {
    1263                 :           0 :                 nItemLen = inchi_min(nItemLen, nPrecision);
    1264                 :             :             }
    1265                 :             :         }
    1266                 :             :         else
    1267                 :             :         {
    1268   [ +  -  -  -  :          72 :             switch (*lpsz)
                      - ]
    1269                 :             :             {
    1270                 :             :                 /* integers */
    1271                 :          72 :             case 'd':
    1272                 :             :             case 'i':
    1273                 :             :             case 'u':
    1274                 :             :             case 'x':
    1275                 :             :             case 'X':
    1276                 :             :             case 'o':
    1277                 :          72 :                 ivarg = va_arg(argList, int); /* djb-rwth: int return value; ignoring LLVM warning */
    1278                 :          72 :                 nItemLen = 32;
    1279                 :          72 :                 nItemLen = inchi_max(nItemLen, nWidth + nPrecision);
    1280                 :          72 :                 break;
    1281                 :             : 
    1282                 :           0 :             case 'e':
    1283                 :             :             case 'f':
    1284                 :             :             case 'g':
    1285                 :             :             case 'G':
    1286                 :           0 :                 dvarg = va_arg(argList, double); /* djb-rwth: double return value; ignoring LLVM warning */
    1287                 :           0 :                 nItemLen = 32;
    1288                 :           0 :                 nItemLen = inchi_max(nItemLen, nWidth + nPrecision);
    1289                 :           0 :                 break;
    1290                 :             : 
    1291                 :           0 :             case 'p':
    1292                 :           0 :                 ivvarg = va_arg(argList, void*); /* djb-rwth: void* return value; ignoring LLVM warning */
    1293                 :           0 :                 nItemLen = 32;
    1294                 :           0 :                 nItemLen = inchi_max(nItemLen, nWidth + nPrecision);
    1295                 :           0 :                 break;
    1296                 :             : 
    1297                 :             :                 /* no output */
    1298                 :           0 :             case 'n':
    1299                 :           0 :                 ipvarg = va_arg(argList, int*); /* djb-rwth: int* return value; ignoring LLVM warning */
    1300                 :           0 :                 break;
    1301                 :             : 
    1302                 :           0 :             default:
    1303                 :             :                 /*ASSERT(FALSE);*/  /* unknown formatting option*/
    1304                 :           0 :                 goto exit_error; /* instead of exception */
    1305                 :             :             }
    1306                 :             :         }
    1307                 :             : 
    1308                 :             :         /* adjust nMaxLen for output nItemLen */
    1309                 :       68931 :         nMaxLen += nItemLen;
    1310                 :             :     }
    1311                 :       68268 :     return nMaxLen;
    1312                 :             : 
    1313                 :           0 : exit_error:
    1314                 :           0 :     return -1; /* wrong format */
    1315                 :             : }
    1316                 :             : 
    1317                 :             : 
    1318                 :             : /****************************************************************************
    1319                 :             :     Get at most n-1 chars, plus a null, then advance input's start.
    1320                 :             :     Return emulates fgets()
    1321                 :             : ****************************************************************************/
    1322                 :         389 : char* inchi_sgets(char* s, int n, INCHI_IOSTREAM* ios)
    1323                 :             : {
    1324                 :         389 :     int c = 0;
    1325                 :             :     char* p;
    1326                 :             :     char* inp;
    1327                 :             : 
    1328                 :         389 :     inp = ios->s.pStr + ios->s.nPtr;
    1329                 :             : 
    1330         [ -  + ]:         389 :     if (n <= 0)
    1331                 :             :     {
    1332                 :           0 :         return NULL;
    1333                 :             :     }
    1334                 :             : 
    1335         [ -  + ]:         389 :     if (NULL == inp)
    1336                 :             :     {
    1337                 :             :         /* like EOF */
    1338                 :           0 :         return NULL; /* djb-rwth: addressing coverity ID #499480 -- inp can be NULL */
    1339                 :             :     }
    1340                 :             : 
    1341                 :         389 :     p = s;
    1342                 :             : 
    1343                 :             :     /*
    1344                 :             :     if ( *inp == '\0' )
    1345                 :             :         s = '\0';
    1346                 :             :     else
    1347                 :             :     */
    1348                 :             : 
    1349   [ +  -  +  + ]:       11784 :     while (--n > 0 && (c = *inp++))
    1350                 :             :     {
    1351                 :       11728 :         ios->s.nPtr++;
    1352         [ +  + ]:       11728 :         if ((*p++ = c) == '\n')
    1353                 :             :         {
    1354                 :         333 :             break;
    1355                 :             :         }
    1356                 :             :     }
    1357                 :         389 :     *p = '\0';
    1358                 :             : 
    1359                 :             :     /* printf("\n*** {%-s}",s); */
    1360                 :             : 
    1361         [ +  + ]:          56 :     return (c == '\0' && p == s)
    1362                 :             :         ? NULL /* like EOF reached */
    1363         [ +  + ]:         445 :         : s;
    1364                 :             : }
    1365                 :             : 
    1366                 :             : 
    1367                 :             : /****************************************************************************
    1368                 :             :  Init expandable buffer of type INCHI_IOS_STRING
    1369                 :             : ****************************************************************************/
    1370                 :         100 : int inchi_strbuf_init(INCHI_IOS_STRING* buf, int start_size, int incr_size)
    1371                 :             : {
    1372                 :         100 :     char* new_str = NULL;
    1373                 :         100 :     memset(buf, 0, sizeof(*buf)); /* djb-rwth: memset_s C11/Annex K variant? */
    1374                 :             : 
    1375         [ -  + ]:         100 :     if (start_size <= 0)
    1376                 :             :     {
    1377                 :           0 :         start_size = INCHI_STRBUF_INITIAL_SIZE;
    1378                 :             :     }
    1379         [ -  + ]:         100 :     if (incr_size <= 0)
    1380                 :             :     {
    1381                 :           0 :         incr_size = INCHI_STRBUF_SIZE_INCREMENT;
    1382                 :             :     }
    1383                 :             : 
    1384                 :         100 :     new_str = (char*)inchi_calloc(start_size, sizeof(char));
    1385                 :             : 
    1386         [ -  + ]:         100 :     if (!new_str)
    1387                 :             :     {
    1388                 :           0 :         return -1;
    1389                 :             :     }
    1390                 :             : 
    1391                 :         100 :     buf->pStr = new_str;
    1392                 :         100 :     buf->nAllocatedLength = start_size;
    1393                 :         100 :     buf->nPtr = incr_size;
    1394                 :             : 
    1395                 :         100 :     return start_size;
    1396                 :             : }
    1397                 :             : 
    1398                 :             : 
    1399                 :             : /****************************************************************************
    1400                 :             :     Reset INCHI_IOS_STRING object holding an expandable buffer string
    1401                 :             :     (place '\0' at the start and do _not_ free memory).
    1402                 :             : ****************************************************************************/
    1403                 :        4131 : void inchi_strbuf_reset(INCHI_IOS_STRING* buf)
    1404                 :             : {
    1405         [ -  + ]:        4131 :     if (!buf)
    1406                 :             :     {
    1407                 :           0 :         return;
    1408                 :             :     }
    1409         [ +  + ]:        4131 :     if (buf->pStr)
    1410                 :             :     {
    1411                 :        3854 :         buf->pStr[0] = '\0';
    1412                 :             :     }
    1413                 :             : 
    1414                 :        4131 :     buf->nUsedLength = buf->nPtr = 0;
    1415                 :             : }
    1416                 :             : 
    1417                 :             : 
    1418                 :             : /****************************************************************************
    1419                 :             : Close INCHI_IOS_STRING object holding an expandable buffer string,
    1420                 :             :     free previously allocated sring memory
    1421                 :             : ****************************************************************************/
    1422                 :         244 : void inchi_strbuf_close(INCHI_IOS_STRING* buf)
    1423                 :             : {
    1424         [ -  + ]:         244 :     if (!buf)
    1425                 :             :     {
    1426                 :           0 :         return;
    1427                 :             :     }
    1428         [ +  - ]:         244 :     if (buf->pStr)
    1429                 :             :     {
    1430         [ +  - ]:         244 :         inchi_free(buf->pStr);
    1431                 :             :     }
    1432                 :             : 
    1433                 :         244 :     memset(buf, 0, sizeof(*buf)); /* djb-rwth: memset_s C11/Annex K variant? */
    1434                 :             : }
    1435                 :             : 
    1436                 :             : 
    1437                 :             : /****************************************************************************/
    1438                 :           0 : int inchi_strbuf_create_copy(INCHI_IOS_STRING* buf2, INCHI_IOS_STRING* buf)
    1439                 :             : {
    1440                 :           0 :     char* new_str = NULL;
    1441                 :             : 
    1442                 :           0 :     new_str = (char*)inchi_calloc(buf->nAllocatedLength, sizeof(char));
    1443                 :           0 :     buf2->pStr = new_str;
    1444         [ #  # ]:           0 :     if (!new_str)
    1445                 :             :     {
    1446                 :           0 :         return -1;
    1447                 :             :     }
    1448                 :           0 :     buf2->nAllocatedLength = buf->nAllocatedLength;
    1449                 :           0 :     buf2->nUsedLength = buf->nUsedLength;
    1450                 :           0 :     buf2->nPtr = buf->nPtr;
    1451                 :             : 
    1452                 :           0 :     return 0;
    1453                 :             : }
    1454                 :             : 
    1455                 :             : 
    1456                 :             : /****************************************************************************
    1457                 :             :  Check size and if necessary expand string buffer in INCHI_IOS_STRING
    1458                 :             : ****************************************************************************/
    1459                 :       67464 : int inchi_strbuf_update(INCHI_IOS_STRING* buf, int new_addition_size)
    1460                 :             : {
    1461                 :             :     int requsted_len;
    1462                 :             : 
    1463         [ -  + ]:       67464 :     if (!buf)
    1464                 :             :     {
    1465                 :           0 :         return -1;
    1466                 :             :     }
    1467                 :             : 
    1468         [ -  + ]:       67464 :     if (new_addition_size <= 0)
    1469                 :             :     {
    1470                 :           0 :         return buf->nAllocatedLength;
    1471                 :             :     }
    1472                 :             : 
    1473                 :       67464 :     requsted_len = buf->nUsedLength + new_addition_size;
    1474                 :             : 
    1475         [ +  + ]:       67464 :     if (requsted_len >= buf->nAllocatedLength)
    1476                 :             :     {
    1477                 :             :         /* Expand */
    1478                 :        4237 :         int  nAddLength = inchi_max(buf->nPtr, new_addition_size);
    1479                 :             :         /* buf->nPtr stores size increment for this buffer */
    1480                 :             :         char* new_str =
    1481                 :        4237 :             (char*)inchi_calloc((long long)buf->nAllocatedLength + (long long)nAddLength,
    1482                 :             :                 sizeof(new_str[0])); /* djb-rwth: cast operators added */
    1483         [ -  + ]:        4237 :         if (!new_str)
    1484                 :             :         {
    1485                 :           0 :             return -1; /* failed */
    1486                 :             :         }
    1487         [ +  + ]:        4237 :         if (buf->pStr)
    1488                 :             :         {
    1489         [ +  - ]:        4008 :             if (buf->nUsedLength > 0)
    1490                 :             :             {
    1491                 :        4008 :                 memcpy(new_str, buf->pStr, sizeof(new_str[0]) * buf->nUsedLength);
    1492                 :             :             }
    1493         [ +  - ]:        4008 :             inchi_free(buf->pStr);
    1494                 :             :         }
    1495                 :        4237 :         buf->pStr = new_str;
    1496                 :        4237 :         buf->nAllocatedLength += nAddLength;
    1497                 :             :     }
    1498                 :             : 
    1499                 :       67464 :     return buf->nAllocatedLength;
    1500                 :             : }
    1501                 :             : 
    1502                 :             : 
    1503                 :             : /****************************************************************************
    1504                 :             :  Add to the end of string in INCHI_IOS_STRING object,
    1505                 :             :     expanding buffer if necessary
    1506                 :             : ****************************************************************************/
    1507                 :       67012 : int inchi_strbuf_printf(INCHI_IOS_STRING* buf, const char* lpszFormat, ...)
    1508                 :             : {
    1509                 :       67012 :     int ret = 0, max_len;
    1510                 :             :     va_list argList;
    1511                 :             : 
    1512         [ -  + ]:       67012 :     if (!buf)
    1513                 :             :     {
    1514                 :           0 :         return -1;
    1515                 :             :     }
    1516                 :             : 
    1517                 :       67012 :     my_va_start(argList, lpszFormat);
    1518                 :       67012 :     max_len = GetMaxPrintfLength(lpszFormat, argList);
    1519                 :       67012 :     va_end(argList);
    1520         [ -  + ]:       67012 :     if (max_len < 0)
    1521                 :             :     {
    1522                 :           0 :         return 0;
    1523                 :             :     }
    1524                 :             : 
    1525                 :       67012 :     inchi_strbuf_update(buf, max_len);
    1526                 :             : 
    1527                 :       67012 :     my_va_start(argList, lpszFormat);
    1528                 :       67012 :     ret = vsprintf(buf->pStr + buf->nUsedLength, lpszFormat, argList);
    1529                 :       67012 :     va_end(argList);
    1530         [ +  - ]:       67012 :     if (ret >= 0)
    1531                 :             :     {
    1532                 :       67012 :         buf->nUsedLength += ret;
    1533                 :             :     }
    1534                 :             : 
    1535                 :       67012 :     return ret;
    1536                 :             : }
    1537                 :             : 
    1538                 :             : 
    1539                 :             : /****************************************************************************
    1540                 :             :     Print to string in INCHI_IOS_STRING object
    1541                 :             :     from specified position 'npos', expanding buffer if necessary.
    1542                 :             :     NB: be careful, intentionally no checks on where is 'npos'!
    1543                 :             : ****************************************************************************/
    1544                 :           0 : int inchi_strbuf_printf_from(INCHI_IOS_STRING* buf,
    1545                 :             :     int npos,
    1546                 :             :     const char* lpszFormat, ...)
    1547                 :             : {
    1548                 :           0 :     int ret = 0, max_len;
    1549                 :             :     va_list argList;
    1550                 :             : 
    1551         [ #  # ]:           0 :     if (!buf)
    1552                 :             :     {
    1553                 :           0 :         return -1;
    1554                 :             :     }
    1555                 :             : 
    1556                 :           0 :     my_va_start(argList, lpszFormat);
    1557                 :           0 :     max_len = GetMaxPrintfLength(lpszFormat, argList);
    1558                 :           0 :     va_end(argList);
    1559         [ #  # ]:           0 :     if (max_len < 0)
    1560                 :             :     {
    1561                 :           0 :         return 0;
    1562                 :             :     }
    1563                 :             : 
    1564                 :           0 :     max_len += npos;
    1565                 :             : 
    1566                 :           0 :     inchi_strbuf_update(buf, max_len);
    1567                 :             : 
    1568                 :           0 :     my_va_start(argList, lpszFormat);
    1569                 :           0 :     ret = vsprintf(buf->pStr + npos, lpszFormat, argList);
    1570                 :           0 :     va_end(argList);
    1571         [ #  # ]:           0 :     if (ret >= 0)
    1572                 :             :     {
    1573                 :           0 :         buf->nUsedLength = npos + ret;
    1574                 :             :     }
    1575                 :             : 
    1576                 :           0 :     return ret;
    1577                 :             : }
    1578                 :             : 
    1579                 :             : 
    1580                 :             : /****************************************************************************
    1581                 :             :     Reads the next line to growing str buf.
    1582                 :             :     Returns n of read chars, -1 at end of file or at error.
    1583                 :             : *****************************************************************************/
    1584                 :           0 : int inchi_strbuf_getline(INCHI_IOS_STRING* buf,
    1585                 :             :     FILE* f,
    1586                 :             :     int crlf2lf,
    1587                 :             :     int preserve_lf)
    1588                 :             : {
    1589                 :             :     int c;
    1590                 :           0 :     inchi_strbuf_reset(buf);
    1591                 :             : 
    1592                 :             :     while (1)
    1593                 :             :     {
    1594                 :           0 :         c = fgetc(f);
    1595         [ #  # ]:           0 :         if (ferror(f))
    1596                 :             :         {
    1597                 :           0 :             return -1;
    1598                 :             :         }
    1599         [ #  # ]:           0 :         if (c == EOF)
    1600                 :             :         {
    1601                 :           0 :             return -1;
    1602                 :             :         }
    1603                 :           0 :         inchi_strbuf_printf(buf, "%c", c);
    1604         [ #  # ]:           0 :         if (c == '\n')
    1605                 :             :         {
    1606                 :           0 :             break;
    1607                 :             :         }
    1608                 :             :     }
    1609                 :             : 
    1610         [ #  # ]:           0 :     if (crlf2lf)
    1611                 :             :     {
    1612         [ #  # ]:           0 :         if (buf->nUsedLength > 2)
    1613                 :             :         {
    1614         [ #  # ]:           0 :             if (buf->pStr[buf->nUsedLength - 2] == '\r')
    1615                 :             :             {
    1616                 :           0 :                 buf->pStr[buf->nUsedLength - 2] = '\n';
    1617                 :           0 :                 buf->pStr[--buf->nUsedLength] = '\0';
    1618                 :             :             }
    1619                 :             :         }
    1620                 :             :     }
    1621         [ #  # ]:           0 :     if (!preserve_lf)
    1622                 :             :     {
    1623                 :           0 :         buf->pStr[--buf->nUsedLength] = '\0';
    1624                 :             :     }
    1625                 :             : 
    1626                 :           0 :     return buf->nUsedLength;
    1627                 :             : }
    1628                 :             : 
    1629                 :             : 
    1630                 :             : 
    1631                 :             : /****************************************************************************
    1632                 :             :     Adds the next line to growing str buf (does not reset buf before adding).
    1633                 :             :     Returns n of read chars, -1 at end of file or at error.
    1634                 :             : ****************************************************************************/
    1635                 :        1640 : int inchi_strbuf_addline(INCHI_IOS_STRING* buf,
    1636                 :             :     INCHI_IOSTREAM* inp_stream,
    1637                 :             :     int crlf2lf,
    1638                 :             :     int preserve_lf)
    1639                 :             : {
    1640                 :             :     int c;
    1641                 :             : 
    1642                 :             :     while (1)
    1643                 :             :     {
    1644                 :       64247 :         c = inchi_ios_str_getc(inp_stream);
    1645         [ -  + ]:       64247 :         if (c == EOF)
    1646                 :             :         {
    1647                 :           0 :             return -1;
    1648                 :             :         }
    1649                 :       64247 :         inchi_strbuf_printf(buf, "%c", c);
    1650         [ +  + ]:       64247 :         if (c == '\n')
    1651                 :             :         {
    1652                 :        1640 :             break;
    1653                 :             :         }
    1654                 :             :     }
    1655         [ +  - ]:        1640 :     if (crlf2lf)
    1656                 :             :     {
    1657         [ +  - ]:        1640 :         if (buf->nUsedLength > 2)
    1658                 :             :         {
    1659         [ -  + ]:        1640 :             if (buf->pStr[buf->nUsedLength - 2] == '\r')
    1660                 :             :             {
    1661                 :           0 :                 buf->pStr[buf->nUsedLength - 2] = '\n';
    1662                 :           0 :                 buf->pStr[--buf->nUsedLength] = '\0';
    1663                 :             :             }
    1664                 :             :         }
    1665                 :             :     }
    1666         [ +  - ]:        1640 :     if (!preserve_lf)
    1667                 :             :     {
    1668                 :        1640 :         buf->pStr[--buf->nUsedLength] = '\0';
    1669                 :             :     }
    1670                 :             : 
    1671                 :        1640 :     return buf->nUsedLength;
    1672                 :             : }
    1673                 :             : 
    1674                 :             : 
    1675                 :             : #if ( defined(_WIN32) && defined(_DEBUG) && defined(_MSC_VER) )
    1676                 :             : #include <windows.h>
    1677                 :             : 
    1678                 :             : 
    1679                 :             : /****************************************************************************/
    1680                 :             : /* djb-rwth: placed as a global variable to avoid function buffer issues */
    1681                 :             : char it_buffer[32767];
    1682                 :             : int _inchi_trace(const char* format, ...)
    1683                 :             : {
    1684                 :             :     /*
    1685                 :             :     TCHAR buffer[32767];
    1686                 :             :     char buffer[32767];
    1687                 :             :     */
    1688                 :             :     int ret;
    1689                 :             : 
    1690                 :             :     va_list argptr;
    1691                 :             :     va_start(argptr, format);
    1692                 :             :     /*wvsprintf(buffer, format, argptr);*/
    1693                 :             :     ret = vsprintf(it_buffer, format, argptr);
    1694                 :             :     va_end(argptr);
    1695                 :             :     OutputDebugString(it_buffer);
    1696                 :             :     return 1;
    1697                 :             : }
    1698                 :             : #else
    1699                 :           0 : int _inchi_trace(char* format, ...)
    1700                 :             : {
    1701                 :           0 :     return 1;
    1702                 :             : }
    1703                 :             : #endif
    1704                 :             : 
    1705                 :             : 
    1706                 :             : /****************************************************************************
    1707                 :             : Output structure (compound) header for current record
    1708                 :             : ****************************************************************************/
    1709                 :           0 : int Output_RecordInfo(INCHI_IOSTREAM* out_file,
    1710                 :             :     int              num_input_struct,
    1711                 :             :     int              bNoStructLabels,
    1712                 :             :     const char* szSdfLabel,
    1713                 :             :     const char* szSdfValue,
    1714                 :             :     unsigned long    lSdfId,
    1715                 :             :     char* pLF,
    1716                 :             :     char* pTAB)
    1717                 :             : {
    1718         [ #  # ]:           0 :     if (bNoStructLabels)
    1719                 :             :     {
    1720                 :           0 :         return 0;
    1721                 :             :     }
    1722                 :             : 
    1723                 :             : #ifdef TARGET_LIB_FOR_WINCHI
    1724                 :             :     /*out_file->s.nUsedLength = 0;
    1725                 :             :     inchi_ios_reset( out_file );*/
    1726                 :             : #endif
    1727   [ #  #  #  #  :           0 :     if (!(szSdfLabel && szSdfLabel[0]) && !(szSdfValue && szSdfValue[0]))
             #  #  #  # ]
    1728                 :             :     {
    1729                 :           0 :         inchi_ios_print_nodisplay(out_file, "%sStructure: %d", pLF, num_input_struct);
    1730                 :           0 :         inchi_ios_print_nodisplay(out_file, "%s", pTAB);
    1731                 :             :     }
    1732                 :             :     else
    1733                 :             :     {
    1734   [ #  #  #  #  :           0 :         inchi_ios_print_nodisplay(out_file, "%sStructure: %d.%s%s%s%s",
             #  #  #  # ]
    1735                 :             :             pLF, num_input_struct,
    1736   [ #  #  #  #  :           0 :             SDF_LBL_VAL(szSdfLabel, szSdfValue));
          #  #  #  #  #  
          #  #  #  #  #  
                   #  # ]
    1737                 :             : 
    1738         [ #  # ]:           0 :         if (lSdfId)
    1739                 :             :         {
    1740                 :           0 :             (out_file->s.nUsedLength)--;
    1741                 :           0 :             inchi_ios_print_nodisplay(out_file, ":%lu", lSdfId);
    1742                 :             :         }
    1743                 :           0 :         inchi_ios_print_nodisplay(out_file, "%s", pTAB);
    1744                 :             :     }
    1745                 :             : 
    1746                 :           0 :     return 0;
    1747                 :             : }
        

Generated by: LCOV version 2.0-1