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

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

Generated by: LCOV version 2.0-1