~ubuntu-branches/debian/stretch/openbabel/stretch

« back to all changes in this revision

Viewing changes to src/formats/libinchi/ichi_io.c

  • Committer: Package Import Robot
  • Author(s): Daniel Leidert
  • Date: 2013-05-22 19:08:27 UTC
  • mfrom: (1.1.11) (7.1.9 sid)
  • Revision ID: package-import@ubuntu.com-20130522190827-72q0fnx5y2nm3bc0
Tags: 2.3.2+dfsg-1
* New upstream release.
* debian/control: Dropped DM-Upload-Allowed field.
  (Standards-Version): Bumped to 3.9.4.
* debian/copyright: Massive update.
* debian/upstream: Author name update.
* debian/get-orig-source.sh: Remove the windows-*/ directory too.
* debian/openbabel.install: Removed roundtrip manpage.
* debian/openbabel-gui.install: Fixed manpage name.
* debian/openbabel-gui.links: Removed unused file.
* debian/rules: Enable OpenMP. Disable tests on `nocheck'.
* debian/patches/gaussformat_nosym.patch: Dropped. Applied upstream.
* debian/patches/moldenformat_coordonly.patch: Ditto.
* debian/patches/obspectrophore_man.patch: Ditto.
* debian/patches/fix_ftbfs.patch: Added.
  - Fix several FTBFS issues in upstream build system.
* debian/patches/series: Adjusted.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * International Chemical Identifier (InChI)
 
3
 * Version 1
 
4
 * Software version 1.04
 
5
 * September 9, 2011
 
6
 *
 
7
 * The InChI library and programs are free software developed under the
 
8
 * auspices of the International Union of Pure and Applied Chemistry (IUPAC).
 
9
 * Originally developed at NIST. Modifications and additions by IUPAC 
 
10
 * and the InChI Trust.
 
11
 *
 
12
 * IUPAC/InChI-Trust Licence for the International Chemical Identifier (InChI) 
 
13
 * Software version 1.0.
 
14
 * Copyright (C) IUPAC and InChI Trust Limited
 
15
 * 
 
16
 * This library is free software; you can redistribute it and/or modify it under the 
 
17
 * terms of the IUPAC/InChI Trust Licence for the International Chemical Identifier 
 
18
 * (InChI) Software version 1.0; either version 1.0 of the License, or 
 
19
 * (at your option) any later version.
 
20
 * 
 
21
 * This library is distributed in the hope that it will be useful, 
 
22
 * but WITHOUT ANY WARRANTY; without even the implied warranty of 
 
23
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
 
24
 * See the IUPAC/InChI Trust Licence for the International Chemical Identifier (InChI) 
 
25
 * Software version 1.0 for more details.
 
26
 * 
 
27
 * You should have received a copy of the IUPAC/InChI Trust Licence for the 
 
28
 * International Chemical Identifier (InChI) Software version 1.0 along with 
 
29
 * this library; if not, write to:
 
30
 * 
 
31
 * The InChI Trust
 
32
 * c/o FIZ CHEMIE Berlin
 
33
 * Franklinstrasse 11
 
34
 * 10587 Berlin
 
35
 * GERMANY
 
36
 * 
 
37
 */
 
38
 
 
39
 
 
40
#include <stdio.h>
 
41
#include <string.h>
 
42
#include <stdlib.h>
 
43
#include <ctype.h>
 
44
#include <stdarg.h>
 
45
#include "mode.h"
 
46
#include "ichi_io.h"
 
47
#include "ichicomp.h"
 
48
#include "util.h"
 
49
 
 
50
#ifndef INCHI_ADD_STR_LEN
 
51
#define INCHI_ADD_STR_LEN   32768
 
52
#endif
 
53
 
 
54
 
 
55
#ifdef TARGET_LIB_FOR_WINCHI
 
56
extern void (*FWPRINT) (const char * format, va_list argptr );
 
57
#endif
 
58
 
 
59
 
 
60
/*^^^ Internal functions */
 
61
 
 
62
int inchi_ios_str_getc( INCHI_IOSTREAM *ios );
 
63
char *inchi_ios_str_gets( char *szLine, int len, INCHI_IOSTREAM *ios );
 
64
char *inchi_ios_str_getsTab( char *szLine, int len, INCHI_IOSTREAM *ios );
 
65
int GetMaxPrintfLength( const char *lpszFormat, va_list argList);
 
66
char *inchi_fgetsTab( char *szLine, int len, FILE *f ); 
 
67
int inchi_vfprintf( FILE* f, const char* lpszFormat, va_list argList ); 
 
68
 
 
69
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
70
 
 
71
 
 
72
                                    INCHI_IOSTREAM OPERATIONS 
 
73
 
 
74
 
 
75
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
76
 
 
77
 
 
78
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
79
    Init INCHI_IOSTREAM
 
80
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
81
void inchi_ios_init(INCHI_IOSTREAM* ios, int io_type, FILE *f)
 
82
{
 
83
    memset( ios, 0, sizeof(*ios) );
 
84
    switch (io_type)
 
85
    {
 
86
        case INCHI_IOSTREAM_FILE:       ios->type = INCHI_IOSTREAM_FILE; 
 
87
                                    break;
 
88
        case INCHI_IOSTREAM_STRING:
 
89
        default:                    ios->type = INCHI_IOSTREAM_STRING;
 
90
                                    break;
 
91
    }
 
92
    ios->f = f; 
 
93
    return;
 
94
}
 
95
 
 
96
 
 
97
 
 
98
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
99
    If INCHI_IOSTREAM type is INCHI_IOSTREAM_STRING,
 
100
        flush INCHI_IOSTREAM string buffer to file (if non-NULL); then free buffer.
 
101
    If INCHI_IOSTREAM type is INCHI_IOSTREAM_FILE, just flush the file.
 
102
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
103
void inchi_ios_flush(INCHI_IOSTREAM* ios)
 
104
{
 
105
    
 
106
    if (ios->type == INCHI_IOSTREAM_STRING) 
 
107
    {
 
108
        if (ios->s.pStr)
 
109
        {
 
110
            if (ios->s.nUsedLength > 0)
 
111
            {       
 
112
                if (ios->f)
 
113
                {
 
114
                    fprintf(ios->f,"%-s", ios->s.pStr); 
 
115
                    fflush(ios->f);
 
116
                }
 
117
                inchi_free(ios->s.pStr );
 
118
                ios->s.pStr = NULL; 
 
119
                ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
 
120
            }       
 
121
        }
 
122
    }
 
123
    
 
124
    else if (ios->type == INCHI_IOSTREAM_FILE)
 
125
    {
 
126
        /* output to plain file: just flush it. */
 
127
        fflush(ios->f);
 
128
    }
 
129
    
 
130
    return;
 
131
}
 
132
 
 
133
 
 
134
 
 
135
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
136
    If INCHI_IOSTREAM type is INCHI_IOSTREAM_STRING,
 
137
        flush INCHI_IOSTREAM string buffer to file (if non-NULL) and
 
138
        another file f2 supplied as parameter (typically, it will be stderr); then free buffer.
 
139
    If INCHI_IOSTREAM type is INCHI_IOSTREAM_FILE, just flush the both files.
 
140
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
141
void inchi_ios_flush2(INCHI_IOSTREAM* ios, FILE *f2)
 
142
{
 
143
 
 
144
    if (ios->type == INCHI_IOSTREAM_STRING) 
 
145
    {
 
146
        if (ios->s.pStr)
 
147
        {
 
148
            if (ios->s.nUsedLength > 0)
 
149
            {       
 
150
                if (ios->f)
 
151
                {
 
152
                    fprintf(ios->f,"%-s", ios->s.pStr); 
 
153
                    fflush(ios->f);
 
154
                }
 
155
                if (f2!=ios->f)
 
156
                    fprintf(f2,"%-s", ios->s.pStr); 
 
157
                
 
158
                inchi_free(ios->s.pStr );
 
159
                ios->s.pStr = NULL; 
 
160
                ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
 
161
            }       
 
162
        }
 
163
    }
 
164
 
 
165
    else if (ios->type == INCHI_IOSTREAM_FILE)
 
166
    {
 
167
        /* output to plain file: just flush it. */
 
168
        if ( (ios->f) && (ios->f!=stderr) && (ios->f!=stdout) )
 
169
            fflush(ios->f);
 
170
        if ( f2 && f2!=stderr && f2!=stdout)
 
171
            fflush(f2);
 
172
 
 
173
 
 
174
    }
 
175
 
 
176
    return;
 
177
}
 
178
 
 
179
 
 
180
 
 
181
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
182
    Close INCHI_IOSTREAM: free string buffer and close the file.
 
183
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
184
void inchi_ios_close(INCHI_IOSTREAM* ios)
 
185
{
 
186
    if (ios->s.pStr)
 
187
        inchi_free(ios->s.pStr);
 
188
    ios->s.pStr = NULL; 
 
189
    ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
 
190
    if ( (ios->f) && (ios->f!=stderr) && (ios->f!=stdout) && (ios->f!=stdin))
 
191
        fclose(ios->f);
 
192
    return;
 
193
}
 
194
 
 
195
 
 
196
 
 
197
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
198
    Reset INCHI_IOSTREAM: set string buffer ptr to NULL (but do _not_ free memory)and close the file.
 
199
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
200
void inchi_ios_reset(INCHI_IOSTREAM* ios)
 
201
{
 
202
    ios->s.pStr = NULL; 
 
203
    ios->s.nUsedLength = ios->s.nAllocatedLength = ios->s.nPtr = 0;
 
204
    if ( (ios->f) && (ios->f!=stderr) && (ios->f!=stdout) && (ios->f!=stdin))
 
205
        fclose(ios->f);
 
206
    return;
 
207
}
 
208
 
 
209
 
 
210
 
 
211
 
 
212
 
 
213
/*******************************************************************/
 
214
int inchi_ios_str_getc(INCHI_IOSTREAM *ios)
 
215
{
 
216
 
 
217
    if (ios->type==INCHI_IOSTREAM_STRING)
 
218
    {
 
219
        if ( ios->s.nPtr < ios->s.nUsedLength ) 
 
220
        {
 
221
            return (int)ios->s.pStr[ios->s.nPtr++];
 
222
        }
 
223
        return EOF;
 
224
    }
 
225
    
 
226
    else if (ios->type==INCHI_IOSTREAM_FILE)
 
227
    {
 
228
        return fgetc( ios->f );
 
229
    }
 
230
    
 
231
    /* error */
 
232
    return EOF;
 
233
}
 
234
 
 
235
 
 
236
 
 
237
/*******************************************************************/
 
238
char *inchi_ios_str_gets(char *szLine, int len, INCHI_IOSTREAM *f)
 
239
{
 
240
int  length=0, c=0;
 
241
    if ( -- len < 0 ) 
 
242
    {
 
243
        return NULL;
 
244
    }
 
245
    while ( length < len && EOF != (c = inchi_ios_str_getc( f )) ) 
 
246
    {
 
247
        szLine[length++] = (char)c;
 
248
        if ( c == '\n' )
 
249
            break;
 
250
    }
 
251
    if ( !length && EOF == c ) 
 
252
    {
 
253
        return NULL;
 
254
    }
 
255
    szLine[length] = '\0';
 
256
    return szLine;
 
257
}
 
258
 
 
259
 
 
260
 
 
261
/********************************************************************************/
 
262
/* read up to len or tab or LF; if empty read next until finds non-empty line   */
 
263
/* remove leading and trailing white spaces; keep zero termination              */
 
264
/********************************************************************************/
 
265
char *inchi_ios_str_getsTab( char *szLine, int len, INCHI_IOSTREAM *f )
 
266
{
 
267
int  length=0, c=0;
 
268
    if ( --len < 0 ) 
 
269
    {
 
270
        return NULL;
 
271
    }
 
272
    while ( length < len && EOF != (c = inchi_ios_str_getc(f)) ) 
 
273
    {
 
274
        if ( c == '\t' )
 
275
            c = '\n';
 
276
        szLine[length++] = (char)c;
 
277
        if ( c == '\n' )
 
278
            break;
 
279
    }
 
280
    if ( !length && EOF == c ) 
 
281
    {
 
282
        return NULL;
 
283
    }
 
284
    szLine[length] = '\0';
 
285
    return szLine;
 
286
}
 
287
 
 
288
 
 
289
/*******************************************************************/
 
290
int inchi_ios_gets( char *szLine, int len, INCHI_IOSTREAM *f, int *bTooLongLine )
 
291
{
 
292
int  length;
 
293
char *p;
 
294
    do 
 
295
    {
 
296
        p = inchi_ios_str_gets( szLine, len-1, f );
 
297
        if ( !p ) 
 
298
        {
 
299
            *bTooLongLine = 0;
 
300
            return -1; /* end of file or cannot read */
 
301
        }
 
302
        szLine[len-1] = '\0';
 
303
        /*
 
304
        *bTooLongLine = !strchr( szLine, '\n' );
 
305
        */
 
306
        p = strchr( szLine, '\n' );
 
307
        *bTooLongLine = ( !p && ((int)strlen(szLine)) == len-2 );
 
308
        LtrimRtrim( szLine, &length );
 
309
    } while ( !length );
 
310
 
 
311
    return length;
 
312
}
 
313
 
 
314
 
 
315
/*******************************************************************/
 
316
/* read up to len or tab or LF; if empty read next until finds non-empty line   */
 
317
/* remove leading and trailing white spaces; keep zero termination */
 
318
/*******************************************************************/
 
319
int inchi_ios_getsTab( char *szLine, int len, INCHI_IOSTREAM *f, int *bTooLongLine )
 
320
{
 
321
int  length;
 
322
char *p;
 
323
    do 
 
324
    {
 
325
        p = inchi_ios_str_getsTab( szLine, len-1, f );
 
326
        if ( !p ) 
 
327
        {
 
328
            *bTooLongLine = 0;
 
329
            return -1; /* end of file or cannot read */
 
330
        }
 
331
        szLine[len-1] = '\0';
 
332
        /*
 
333
        *bTooLongLine = !strchr( szLine, '\n' );
 
334
        */
 
335
        p = strchr( szLine, '\n' );
 
336
        *bTooLongLine = ( !p && ((int)strlen(szLine)) == len-2 );
 
337
        LtrimRtrim( szLine, &length );
 
338
    } while ( !length );
 
339
    return length;
 
340
}
 
341
 
 
342
/*******************************************************************/
 
343
int inchi_ios_getsTab1( char *szLine, int len, INCHI_IOSTREAM *f, int *bTooLongLine )
 
344
{
 
345
int  length;
 
346
char *p;
 
347
    /*do {*/
 
348
        p = inchi_ios_str_getsTab( szLine, len-1, f );
 
349
        if ( !p ) 
 
350
        {
 
351
            *bTooLongLine = 0;
 
352
            return -1; /* end of file or cannot read */
 
353
        }
 
354
        szLine[len-1] = '\0';
 
355
        /*
 
356
        *bTooLongLine = !strchr( szLine, '\n' );
 
357
        */
 
358
        p = strchr( szLine, '\n' );
 
359
        *bTooLongLine = ( !p && ((int)strlen(szLine)) == len-2 );
 
360
        LtrimRtrim( szLine, &length );
 
361
    /*} while ( !length );*/
 
362
    return length;
 
363
}
 
364
 
 
365
 
 
366
 
 
367
 
 
368
 
 
369
 
 
370
/*****************************************************************/
 
371
int inchi_ios_print( INCHI_IOSTREAM * ios, const char* lpszFormat, ... )
 
372
{
 
373
int ret=0, ret2=0;
 
374
va_list argList;
 
375
 
 
376
    if (!ios) 
 
377
        return -1;
 
378
    
 
379
    if (ios->type == INCHI_IOSTREAM_STRING) 
 
380
    {    
 
381
        /* output to string buffer */        
 
382
        int max_len;
 
383
        my_va_start( argList, lpszFormat );
 
384
        max_len = GetMaxPrintfLength( lpszFormat, argList);
 
385
        va_end( argList );
 
386
        if ( max_len >= 0 ) 
 
387
        {
 
388
            if ( ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len ) 
 
389
            {
 
390
                /* enlarge output string */
 
391
                int  nAddLength = inchi_max( INCHI_ADD_STR_LEN, max_len );
 
392
                char *new_str = 
 
393
                    (char *)inchi_calloc( ios->s.nAllocatedLength + nAddLength, sizeof(new_str[0]) );
 
394
                if ( new_str ) 
 
395
                {
 
396
                    if ( ios->s.pStr ) 
 
397
                    {
 
398
                        if ( ios->s.nUsedLength > 0 ) 
 
399
                            memcpy( new_str, ios->s.pStr, sizeof(new_str[0])* ios->s.nUsedLength );
 
400
                        inchi_free( ios->s.pStr );
 
401
                    }
 
402
                    ios->s.pStr              = new_str;
 
403
                    ios->s.nAllocatedLength += nAddLength;
 
404
                } 
 
405
                else return -1; /* failed */
 
406
            }
 
407
            /* output */
 
408
            my_va_start( argList, lpszFormat );
 
409
            ret = vsprintf( ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList );
 
410
            va_end(argList);
 
411
            if ( ret >= 0 ) 
 
412
                ios->s.nUsedLength += ret;
 
413
#ifdef TARGET_LIB_FOR_WINCHI
 
414
            if( FWPRINT )
 
415
            {
 
416
                my_va_start( argList, lpszFormat );
 
417
                FWPRINT( lpszFormat, argList );
 
418
                va_end( argList );
 
419
            }
 
420
#endif
 
421
            return ret;
 
422
        }
 
423
        return -1;
 
424
    }
 
425
    
 
426
    else if (ios->type == INCHI_IOSTREAM_FILE)
 
427
    {
 
428
        /* output to file */
 
429
        if (ios->f) 
 
430
        {
 
431
            my_va_start( argList, lpszFormat );
 
432
            ret = vfprintf( ios->f, lpszFormat, argList );
 
433
            va_end( argList );
 
434
        } 
 
435
        else 
 
436
        {
 
437
            my_va_start( argList, lpszFormat );
 
438
            ret2 = vfprintf( stdout, lpszFormat, argList );
 
439
            va_end( argList );
 
440
        }
 
441
#ifdef TARGET_LIB_FOR_WINCHI
 
442
        if( FWPRINT )
 
443
        {
 
444
            my_va_start( argList, lpszFormat );
 
445
            FWPRINT( lpszFormat, argList );
 
446
            va_end( argList );
 
447
        }
 
448
#endif
 
449
        return ret? ret : ret2;
 
450
    }
 
451
 
 
452
 
 
453
    /* no output */
 
454
    return 0;
 
455
}
 
456
 
 
457
 
 
458
 
 
459
 
 
460
/**********************************************************************/
 
461
/* This function's output should not be displayed in the output pane  */
 
462
/**********************************************************************/
 
463
int inchi_ios_print_nodisplay( INCHI_IOSTREAM * ios, const char* lpszFormat, ... )
 
464
{
 
465
va_list argList;
 
466
 
 
467
    if (!ios) 
 
468
        return -1;
 
469
    
 
470
    if (ios->type == INCHI_IOSTREAM_STRING) 
 
471
    {
 
472
        /* output to string buffer */
 
473
        int ret=0, max_len;
 
474
        my_va_start( argList, lpszFormat );
 
475
        max_len = GetMaxPrintfLength( lpszFormat, argList);
 
476
        va_end( argList );
 
477
        if ( max_len >= 0 ) 
 
478
        {
 
479
            if ( ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len ) 
 
480
            {
 
481
                /* enlarge output string */
 
482
                int  nAddLength = inchi_max( INCHI_ADD_STR_LEN, max_len );
 
483
                char *new_str = (char *)inchi_calloc( ios->s.nAllocatedLength + nAddLength, sizeof(new_str[0]) );
 
484
                if ( new_str ) 
 
485
                {
 
486
                    if ( ios->s.pStr ) 
 
487
                    {
 
488
                        if ( ios->s.nUsedLength > 0 ) 
 
489
                        {
 
490
                            memcpy( new_str, ios->s.pStr, sizeof(new_str[0])*ios->s.nUsedLength );
 
491
                        }
 
492
                        inchi_free( ios->s.pStr );
 
493
                    }
 
494
                    ios->s.pStr              = new_str;
 
495
                    ios->s.nAllocatedLength += nAddLength;
 
496
                } else 
 
497
                {
 
498
                    return -1; /* failed */
 
499
                }
 
500
            }
 
501
            /* output */
 
502
            my_va_start( argList, lpszFormat );
 
503
            ret = vsprintf( ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList );
 
504
            va_end(argList);
 
505
            if ( ret >= 0 ) 
 
506
            {
 
507
                ios->s.nUsedLength += ret;
 
508
            }
 
509
            return ret;
 
510
        }
 
511
        return -1;
 
512
    }
 
513
 
 
514
    else if (ios->type == INCHI_IOSTREAM_FILE)
 
515
    {
 
516
        my_va_start( argList, lpszFormat );
 
517
        inchi_print_nodisplay( ios->f, lpszFormat, argList);
 
518
        va_end(argList);        
 
519
    }
 
520
 
 
521
    /* no output */
 
522
    return 0;
 
523
}
 
524
 
 
525
 
 
526
 
 
527
 
 
528
/*****************************************************************/
 
529
/* Print to string buffer or to file+stderr */
 
530
int inchi_ios_eprint( INCHI_IOSTREAM * ios, const char* lpszFormat, ... )
 
531
{
 
532
int ret=0, ret2=0;
 
533
va_list argList;
 
534
 
 
535
    if (!ios) 
 
536
        return -1;
 
537
 
 
538
    if (ios->type == INCHI_IOSTREAM_STRING) /* was #if ( defined(TARGET_API_LIB) || defined(INCHI_STANDALONE_EXE) ) */
 
539
    {
 
540
        /* output to string buffer */
 
541
        int max_len, nAddLength = 0;
 
542
        char *new_str = NULL;
 
543
 
 
544
        my_va_start( argList, lpszFormat );
 
545
        max_len = GetMaxPrintfLength( lpszFormat, argList);
 
546
        va_end( argList );
 
547
 
 
548
        if ( max_len >= 0 ) 
 
549
        {
 
550
            if ( ios->s.nAllocatedLength - ios->s.nUsedLength <= max_len ) 
 
551
            {
 
552
                /* enlarge output string */
 
553
                nAddLength = inchi_max( INCHI_ADD_STR_LEN, max_len );
 
554
                new_str = (char *)inchi_calloc( ios->s.nAllocatedLength + nAddLength, sizeof(new_str[0]) );
 
555
                if ( new_str ) 
 
556
                {
 
557
                    if ( ios->s.pStr ) 
 
558
                    {
 
559
                        if ( ios->s.nUsedLength > 0 ) 
 
560
                        {
 
561
                            memcpy( new_str, ios->s.pStr, sizeof(new_str[0])* ios->s.nUsedLength );
 
562
                        }
 
563
                        inchi_free( ios->s.pStr );
 
564
                    }
 
565
                    ios->s.pStr              = new_str;
 
566
                    ios->s.nAllocatedLength += nAddLength;
 
567
                } 
 
568
                else 
 
569
                {
 
570
                    return -1; /* failed */
 
571
                }
 
572
            }
 
573
         
 
574
            /* output */
 
575
            my_va_start( argList, lpszFormat );
 
576
            ret = vsprintf( ios->s.pStr + ios->s.nUsedLength, lpszFormat, argList );
 
577
            va_end(argList);
 
578
            if ( ret >= 0 ) 
 
579
            {
 
580
                ios->s.nUsedLength += ret;
 
581
            }
 
582
            return ret;
 
583
        }
 
584
        return -1;
 
585
    }
 
586
 
 
587
    else if (ios->type == INCHI_IOSTREAM_FILE)
 
588
    {
 
589
        if ( ios->f) 
 
590
        {
 
591
            /* output to plain file */
 
592
            my_va_start( argList, lpszFormat );
 
593
            ret = inchi_vfprintf( ios->f, lpszFormat, argList ); 
 
594
            va_end( argList );
 
595
/*^^^  No output to stderr from within dll or GUI program */
 
596
#if ( !defined(TARGET_API_LIB) && !defined(TARGET_LIB_FOR_WINCHI) )
 
597
            if ( ios->f != stderr ) 
 
598
            { 
 
599
                my_va_start( argList, lpszFormat );
 
600
                ret2 = vfprintf( stderr, lpszFormat, argList );
 
601
                va_end( argList );
 
602
            }
 
603
#endif
 
604
            return ret? ret : ret2;
 
605
        }
 
606
    } 
 
607
 
 
608
    /* no output */
 
609
    return 0;
 
610
}
 
611
 
 
612
 
 
613
 
 
614
 
 
615
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
616
 
 
617
 
 
618
                                    PLAIN FILE OPERATIONS 
 
619
 
 
620
 
 
621
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
622
 
 
623
 
 
624
 
 
625
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
626
 
 
627
/* Print to file, echoing to stderr */
 
628
int inchi_fprintf( FILE* f, const char* lpszFormat, ... )
 
629
{
 
630
int ret=0, ret2=0;
 
631
va_list argList;
 
632
    if (f) 
 
633
    {
 
634
        my_va_start( argList, lpszFormat );
 
635
        ret = inchi_vfprintf( f, lpszFormat, argList ); 
 
636
        va_end( argList );
 
637
/*^^^  No output to stderr from within dll or GUI program */
 
638
#if ( !defined(TARGET_API_LIB) && !defined(TARGET_LIB_FOR_WINCHI) )
 
639
        if ( f != stderr ) 
 
640
        { 
 
641
            my_va_start( argList, lpszFormat );
 
642
            ret2 = vfprintf( stderr, lpszFormat, argList );
 
643
            va_end( argList );
 
644
        }
 
645
#endif
 
646
        return ret? ret : ret2;
 
647
    }
 
648
    return 0;
 
649
}
 
650
 
 
651
 
 
652
 
 
653
/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
 
654
 
 
655
/* Print to file */
 
656
int inchi_vfprintf( FILE* f, const char* lpszFormat, va_list argList )
 
657
{
 
658
int ret=0;
 
659
    if ( f == stderr && lpszFormat && lpszFormat[0] && '\r' == lpszFormat[strlen(lpszFormat)-1] ) 
 
660
    {
 
661
#define CONSOLE_LINE_LEN 80
 
662
#ifndef COMPILE_ANSI_ONLY
 
663
        char szLine[CONSOLE_LINE_LEN];
 
664
        ret = _vsnprintf( szLine, CONSOLE_LINE_LEN-1, lpszFormat, argList );
 
665
        if ( ret < 0 ) 
 
666
        {
 
667
            /*  output is longer than the console line */
 
668
            /*^^^ Fixed bug: (CONSOLE_LINE_LEN-4) --> (CONSOLE_LINE_LEN-4-1) 11-22-08 IPl */
 
669
            strcpy(szLine+CONSOLE_LINE_LEN-5, "...\r");
 
670
        }
 
671
        fputs( szLine, f );
 
672
#else
 
673
        ret = vfprintf( f, lpszFormat, argList );
 
674
#endif
 
675
#undef CONSOLE_LINE_LEN
 
676
    } 
 
677
    else 
 
678
    {
 
679
        ret = vfprintf( f, lpszFormat, argList );
 
680
    }
 
681
    return ret;
 
682
}
 
683
 
 
684
 
 
685
 
 
686
/**********************************************************************/
 
687
/* This function's output should not be displayed in the output pane  */
 
688
/**********************************************************************/
 
689
int inchi_print_nodisplay( FILE* f, const char* lpszFormat, ... )
 
690
{
 
691
int ret=0;
 
692
va_list argList;
 
693
FILE* fi;
 
694
    if (f)      
 
695
        fi = f;
 
696
    else        
 
697
        fi = stdout;
 
698
    my_va_start( argList, lpszFormat );
 
699
    ret = vfprintf( fi, lpszFormat, argList );
 
700
    return ret;
 
701
}
 
702
 
 
703
 
 
704
 
 
705
#if ( FIX_READ_LONG_LINE_BUG == 1 )
 
706
/********************************************************************/
 
707
int inchi_fgetsLfTab( char *szLine, int len, FILE *f )
 
708
{
 
709
    int  length;
 
710
    char *p;
 
711
    char szSkip[256];
 
712
    int  bTooLongLine = 0;
 
713
    do {
 
714
        p = inchi_fgetsTab( szLine, len, f );
 
715
        if ( !p ) {
 
716
            return -1; /* end of file or cannot read */
 
717
        }
 
718
        bTooLongLine = ( (int)strlen(szLine) == len-1 && szLine[len-2] != '\n' );
 
719
        LtrimRtrim( szLine, &length );
 
720
    } while ( !length );
 
721
    if ( bTooLongLine ) {
 
722
        while ( p = inchi_fgetsTab( szSkip, sizeof(szSkip)-1, f ) ) {
 
723
            if ( strchr( szSkip, '\n' ) )
 
724
                break;
 
725
        }
 
726
    }
 
727
    return length;
 
728
}
 
729
#else
 
730
/********************************************************************/
 
731
int inchi_fgetsLfTab( char *szLine, int len, FILE *f )
 
732
{
 
733
    int  length;
 
734
    char *p;
 
735
    char szSkip[256];
 
736
    int  bTooLongLine = 0;
 
737
    do {
 
738
        p = inchi_fgetsTab( szLine, len-1, f );
 
739
        if ( !p ) {
 
740
            return -1; /* end of file or cannot read */
 
741
        }
 
742
        szLine[len-1] = '\0';
 
743
        /*
 
744
        bTooLongLine = !strchr( szLine, '\n' );
 
745
        */
 
746
        bTooLongLine = ( !p && ((int)strlen(szLine)) == len-2 );
 
747
        LtrimRtrim( szLine, &length );
 
748
    } while ( !length );
 
749
    if ( bTooLongLine ) {
 
750
        while ( p = inchi_fgetsTab( szSkip, sizeof(szSkip)-1, f ) ) {
 
751
            szSkip[sizeof(szSkip)-1] = '\0';
 
752
            if ( strchr( szSkip, '\n' ) )
 
753
                break;
 
754
        }
 
755
    }
 
756
    return length;
 
757
}
 
758
#endif
 
759
 
 
760
 
 
761
/*******************************************************************/
 
762
/* read up to len or tab or LF; if empty read next until finds non-empty line   */
 
763
/* remove leading and trailing white spaces; keep zero termination */
 
764
/*******************************************************************/
 
765
char *inchi_fgetsTab( char *szLine, int len, FILE *f )
 
766
{
 
767
    int  length=0, c=0;
 
768
    len --;
 
769
    while ( length < len && EOF != (c = fgetc( f )) ) {
 
770
        if ( c == '\t' )
 
771
            c = '\n';
 
772
        szLine[length++] = (char)c;
 
773
        if ( c == '\n' )
 
774
            break;
 
775
    }
 
776
    if ( !length && EOF == c ) {
 
777
        return NULL;
 
778
    }
 
779
    szLine[length] = '\0';
 
780
    return szLine;
 
781
}
 
782
 
 
783
 
 
784
 
 
785
/******************************************************************/
 
786
/* read not more than line_len bytes from an lf-terminated line   */
 
787
/* if input line is too long quietly ignore the rest of the line  */
 
788
char* inchi_fgetsLf( char* line, int line_len, FILE* inp )
 
789
{
 
790
    char *p, *q;
 
791
    memset( line, 0, line_len );
 
792
    if ( NULL != (p = fgets( line, line_len, inp ) ) && NULL == strchr(p, '\n' ) ){
 
793
        char temp[64]; /* bypass up to '\n' or up to end of file whichever comes first*/
 
794
        while ( NULL != fgets( temp, sizeof(temp), inp ) && NULL == strchr(temp,'\n') )
 
795
            ;
 
796
    }
 
797
    if ( p && (q = strchr(line, '\r')) ) { /*  fix CR CR LF line terminator. */
 
798
        q[0] = '\n';
 
799
        q[1] = '\0';
 
800
    }    
 
801
    return p;
 
802
}
 
803
 
 
804
 
 
805
 
 
806
 
 
807
 
 
808
 
 
809
 
 
810
 
 
811
 
 
812
 
 
813
/*****************************************************************
 
814
 *
 
815
 *  Estimate printf string length
 
816
 *  
 
817
 *  The code is based on Microsoft Knowledge Base article Q127038:
 
818
 *  "FIX: CString::Format Gives Assertion Failed, Access Violation"
 
819
 *  (Related to Microsoft Visual C++, 32-bit Editions, versions 2.0, 2.1)
 
820
 *
 
821
 *****************************************************************/
 
822
 
 
823
#define FORCE_ANSI      0x10000
 
824
#define FORCE_UNICODE   0x20000
 
825
 
 
826
/* formatting (using wsprintf style formatting)*/
 
827
int GetMaxPrintfLength( const char *lpszFormat, va_list argList)
 
828
{
 
829
     /*ASSERT(AfxIsValidString(lpszFormat, FALSE));*/
 
830
     const char * lpsz;
 
831
     int nMaxLen, nWidth, nPrecision, nModifier, nItemLen;
 
832
 
 
833
     nMaxLen = 0;
 
834
     /* make a guess at the maximum length of the resulting string */
 
835
     for ( lpsz = lpszFormat; *lpsz; lpsz ++ )
 
836
     {
 
837
          /* handle '%' character, but watch out for '%%' */
 
838
          if (*lpsz != '%' || *( ++ lpsz ) == '%')
 
839
          {
 
840
               nMaxLen += 1;
 
841
               continue;
 
842
          }
 
843
 
 
844
          nItemLen = 0;
 
845
 
 
846
          /*  handle '%' character with format */
 
847
          nWidth = 0;
 
848
          for (; *lpsz; lpsz ++ )
 
849
          {
 
850
               /* check for valid flags */
 
851
               if (*lpsz == '#')
 
852
                    nMaxLen += 2;   /* for '0x' */
 
853
               else if (*lpsz == '*')
 
854
                    nWidth = va_arg(argList, int);
 
855
               else if (*lpsz == '-' || *lpsz == '+' || *lpsz == '0'
 
856
                        || *lpsz == ' ')
 
857
                           ;
 
858
               else /* hit non-flag character */
 
859
                          break;
 
860
          }
 
861
          /* get width and skip it */
 
862
          if (nWidth == 0)
 
863
          {
 
864
               /* width indicated by */
 
865
               nWidth = atoi(lpsz);
 
866
               for (; *lpsz && isdigit(*lpsz); lpsz ++ )
 
867
                     ;
 
868
          }
 
869
          /*ASSERT(nWidth >= 0);*/
 
870
          if ( nWidth < 0 )
 
871
              goto exit_error; /* instead of exception */
 
872
 
 
873
          nPrecision = 0;
 
874
          if (*lpsz == '.')
 
875
          {
 
876
               /* skip past '.' separator (width.precision)*/
 
877
               lpsz ++;
 
878
 
 
879
               /* get precision and skip it*/
 
880
               if (*lpsz == '*')
 
881
               {
 
882
                    nPrecision = va_arg(argList, int);
 
883
                    lpsz ++;
 
884
               }
 
885
               else
 
886
               {
 
887
                    nPrecision = atoi(lpsz);
 
888
                    for (; *lpsz && isdigit(*lpsz); lpsz ++)
 
889
                            ;
 
890
               }
 
891
              if ( nPrecision < 0 )
 
892
                  goto exit_error; /* instead of exception */
 
893
          }
 
894
 
 
895
          /* should be on type modifier or specifier */
 
896
          nModifier = 0;
 
897
          switch (*lpsz)
 
898
          {
 
899
          /* modifiers that affect size */
 
900
          case 'h':
 
901
               switch ( lpsz[1] ) {
 
902
               case 'd':
 
903
               case 'i':
 
904
               case 'o':
 
905
               case 'x':
 
906
               case 'X':
 
907
               case 'u':
 
908
                   /* short unsigned, short double, etc. -- added to the original MS example */
 
909
                   /* ignore the fact that these modifiers do affect size */
 
910
                   lpsz ++;
 
911
                   break;
 
912
               default:
 
913
                   nModifier = FORCE_ANSI;
 
914
                   lpsz ++;
 
915
                   break;
 
916
               }
 
917
               break;
 
918
          case 'l':
 
919
               switch ( lpsz[1] ) {
 
920
               case 'd':
 
921
               case 'i':
 
922
               case 'o':
 
923
               case 'x':
 
924
               case 'X':
 
925
               case 'u':
 
926
               case 'f': /* long float -- post ANSI C */
 
927
                   /* long unsigned, long double, etc. -- added to the original MS example */
 
928
                   /* ignore the fact that these modifiers do affect size */
 
929
                   lpsz ++;
 
930
                   break;
 
931
               default:
 
932
                   /*
 
933
                   nModifier = FORCE_UNICODE;
 
934
                   lpsz ++;
 
935
                   break;
 
936
                   */
 
937
                   goto exit_error;  /* no UNICODE, please */
 
938
               }
 
939
               break;
 
940
          /* modifiers that do not affect size */
 
941
          case 'F':
 
942
          case 'N':
 
943
          case 'L':
 
944
               lpsz ++;
 
945
               break;
 
946
          }
 
947
 
 
948
          /* now should be on specifier */
 
949
          switch (*lpsz | nModifier)
 
950
          {
 
951
          /* single characters*/
 
952
          case 'c':
 
953
          case 'C':
 
954
               nItemLen = 2;
 
955
               va_arg(argList, int);
 
956
               break;
 
957
          case 'c'|FORCE_ANSI:
 
958
          case 'C'|FORCE_ANSI:
 
959
               nItemLen = 2;
 
960
               va_arg(argList, int);
 
961
               break;
 
962
          case 'c'|FORCE_UNICODE:
 
963
          case 'C'|FORCE_UNICODE:
 
964
               goto exit_error;  /* no UNICODE, please */
 
965
               /*
 
966
               nItemLen = 2;
 
967
               va_arg(argList, wchar_t);
 
968
               break;
 
969
               */
 
970
 
 
971
          /* strings*/
 
972
          case 's':
 
973
          case 'S':
 
974
               nItemLen = strlen(va_arg(argList, char*));
 
975
               nItemLen = inchi_max(1, nItemLen);
 
976
               break;
 
977
          case 's'|FORCE_ANSI:
 
978
          case 'S'|FORCE_ANSI:
 
979
               nItemLen = strlen(va_arg(argList, char*));
 
980
               nItemLen = inchi_max(1, nItemLen);
 
981
               break;
 
982
 
 
983
          case 's'|FORCE_UNICODE:
 
984
          case 'S'|FORCE_UNICODE:
 
985
               goto exit_error;  /* no UNICODE, please */
 
986
               /*
 
987
               nItemLen = wcslen(va_arg(argList, wchar_t*));
 
988
               nItemLen = inchi_max(1, nItemLen);
 
989
               break;
 
990
               */
 
991
 
 
992
          }
 
993
 
 
994
          /* adjust nItemLen for strings */
 
995
          if (nItemLen != 0)
 
996
          {
 
997
               nItemLen = inchi_max(nItemLen, nWidth);
 
998
               if (nPrecision != 0)
 
999
                    nItemLen = inchi_min(nItemLen, nPrecision);
 
1000
          }
 
1001
          else
 
1002
          {
 
1003
               switch (*lpsz)
 
1004
               {
 
1005
               /* integers */
 
1006
               case 'd':
 
1007
               case 'i':
 
1008
               case 'u':
 
1009
               case 'x':
 
1010
               case 'X':
 
1011
               case 'o':
 
1012
                    va_arg(argList, int);
 
1013
                    nItemLen = 32;
 
1014
                    nItemLen = inchi_max(nItemLen, nWidth+nPrecision);
 
1015
                    break;
 
1016
 
 
1017
               case 'e':
 
1018
               case 'f':
 
1019
               case 'g':
 
1020
               case 'G':
 
1021
                    va_arg(argList, double);
 
1022
                    nItemLen = 32;
 
1023
                    nItemLen = inchi_max(nItemLen, nWidth+nPrecision);
 
1024
                    break;
 
1025
 
 
1026
               case 'p':
 
1027
                    va_arg(argList, void*);
 
1028
                    nItemLen = 32;
 
1029
                    nItemLen = inchi_max(nItemLen, nWidth+nPrecision);
 
1030
                    break;
 
1031
 
 
1032
               /* no output */
 
1033
               case 'n':
 
1034
                    va_arg(argList, int*);
 
1035
                    break;
 
1036
 
 
1037
               default:
 
1038
                   /*ASSERT(FALSE);*/  /* unknown formatting option*/
 
1039
                   goto exit_error; /* instead of exception */
 
1040
               }
 
1041
          }
 
1042
 
 
1043
          /* adjust nMaxLen for output nItemLen */
 
1044
          nMaxLen += nItemLen;
 
1045
     }
 
1046
     return nMaxLen;
 
1047
 
 
1048
exit_error:
 
1049
     return -1; /* wrong format */
 
1050
 
1051