Coverage Report

Created: 2024-02-25 06:07

/src/inchi/INCHI-1-SRC/INCHI_API/libinchi/src/inchi_dll.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * International Chemical Identifier (InChI)
3
 * Version 1
4
 * Software version 1.07
5
 * 20/11/2023
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.
10
 * Modifications and additions by IUPAC and the InChI Trust.
11
 * Some portions of code were developed/changed by external contributors
12
 * (either contractor or volunteer) which are listed in the file
13
 * 'External-contributors' included in this distribution.
14
 *
15
 * IUPAC/InChI-Trust Licence No.1.0 for the
16
 * International Chemical Identifier (InChI)
17
 * Copyright (C) IUPAC and InChI Trust
18
 *
19
 * This library is free software; you can redistribute it and/or modify it
20
 * under the terms of the IUPAC/InChI Trust InChI Licence No.1.0,
21
 * or any later version.
22
 *
23
 * Please note that this library is distributed WITHOUT ANY WARRANTIES
24
 * whatsoever, whether expressed or implied.
25
 * See the IUPAC/InChI-Trust InChI Licence No.1.0 for more details.
26
 *
27
 * You should have received a copy of the IUPAC/InChI Trust InChI
28
 * Licence No. 1.0 with this library; if not, please e-mail:
29
 *
30
 * info@inchi-trust.org
31
 *
32
 */
33
34
35
#include <stdio.h>
36
#include <stdlib.h>
37
#include <string.h>
38
#include <ctype.h>
39
#include <stdarg.h>
40
#include <errno.h>
41
#include <limits.h>
42
#include <float.h>
43
#include <math.h>
44
45
#include "../../../INCHI_BASE/src/mode.h"
46
47
#include "../../../INCHI_BASE/src/incomdef.h"
48
#include "../../../INCHI_BASE/src/ichidrp.h"
49
#include "../../../INCHI_BASE/src/inpdef.h"
50
#include "../../../INCHI_BASE/src/ichi.h"
51
#include "../../../INCHI_BASE/src/strutil.h"
52
#include "../../../INCHI_BASE/src/util.h"
53
#include "../../../INCHI_BASE/src/ichierr.h"
54
#include "../../../INCHI_BASE/src/ichimain.h"
55
#include "../../../INCHI_BASE/src/extr_ct.h"
56
#include "../../../INCHI_BASE/src/ichi_io.h"
57
#include "../../../INCHI_BASE/src/ichicomp.h"
58
#include "../../../INCHI_BASE/src/inchi_api.h"
59
#include "../../../INCHI_BASE/src/readinch.h"
60
61
#include "../../../INCHI_BASE/src/ichitaut.h"
62
#include "../../../INCHI_BASE/src/ichicant.h"
63
#include "../../../INCHI_BASE/src/ichitime.h"
64
#include "../../../INCHI_BASE/src/bcf_s.h"
65
66
#include "inchi_dll.h"
67
68
/*************************************************************************
69
 *
70
 *   Local prototypes
71
 *
72
 *************************************************************************/
73
74
int SetAtomProperties( inp_ATOM *at,
75
                       MOL_COORD *szCoord,
76
                       inchi_Atom *ati,
77
                       int a1,
78
                       int *nDim,
79
                       char *pStrErr,
80
                       int *err );
81
void SetNumImplicitH( inp_ATOM* at, int num_atoms );
82
int SetBondProperties( inp_ATOM *at,
83
                       inchi_Atom *ati,
84
                       int a1,
85
                       int j,
86
                       int nNumAtoms,
87
                       int *nNumBonds,
88
                       char *pStrErr,
89
                       int *err );
90
int SetAtomAndBondProperties( inp_ATOM *at,
91
                              inchi_Atom *ati,
92
                              int a1,
93
                              int bDoNotAddH,
94
                              char *pStrErr,
95
                              int *err );
96
int InpAtom0DToInchiAtom( inp_ATOM *at,
97
                          int num_inp_atoms,
98
                          AT_NUM *num_atoms,
99
                          inchi_Atom **atom,
100
                          AT_NUM *num_stereo0D,
101
                          inchi_Stereo0D **stereo0D );
102
int ExtractOneStructure( STRUCT_DATA *sd,
103
                         INPUT_PARMS *ip,
104
                         char *szTitle,
105
                         inchi_InputEx *inp,
106
                         INCHI_IOSTREAM *log_file,
107
                         INCHI_IOSTREAM *out_file,
108
                         INCHI_IOSTREAM *prb_file,
109
                         ORIG_ATOM_DATA *orig_inp_data,
110
                         long *num_inp );
111
112
static int GetINCHI1( inchi_InputEx *inp, inchi_Output *out, int enforce_std_format );
113
114
int SetExtOrigAtDataByInChIExtInput( OAD_Polymer **ppPolymer,
115
                                     OAD_V3000 **ppV3000,
116
                                     inchi_Input_Polymer *polymer,
117
                                     inchi_Input_V3000 *v3000,
118
                                     int nat );
119
int SetInChIExtInputByExtOrigAtData( OAD_Polymer *pPolymer,
120
                                     OAD_V3000 *pV3000,
121
                                     inchi_Input_Polymer **ipolymer,
122
                                     inchi_Input_V3000 **iv3000,
123
                                     int nat );
124
125
/****************************************************************************/
126
127
int bInterrupted = 0;
128
129
130
131
/****************************************************************************
132
 *
133
 * INCHI API
134
 *
135
 ****************************************************************************/
136
137
138
139
/****************************************************************************
140
141
    FreeINCHI
142
143
****************************************************************************/
144
EXPIMP_TEMPLATE INCHI_API
145
void INCHI_DECL FreeINCHI( inchi_Output *out )
146
2.20k
{
147
2.20k
    if (!out)
148
0
    {
149
0
        return;
150
0
    }
151
152
2.20k
    if (out->szInChI)
153
1.51k
    {
154
1.51k
        inchi_free( out->szInChI );
155
1.51k
    }
156
2.20k
    if (out->szLog)
157
2.12k
    {
158
2.12k
        inchi_free( out->szLog );
159
2.12k
    }
160
2.20k
    if (out->szMessage)
161
2.12k
    {
162
2.12k
        inchi_free( out->szMessage );
163
2.12k
    }
164
165
2.20k
    memset( out, 0, sizeof( *out ) ); /* djb-rwth: memset_s C11/Annex K variant? */
166
2.20k
}
167
168
169
/****************************************************************************
170
171
    FreeStdINCHI
172
173
****************************************************************************/
174
EXPIMP_TEMPLATE INCHI_API
175
void INCHI_DECL FreeStdINCHI( inchi_Output *out )
176
0
{
177
0
    FreeINCHI( out );
178
0
}
179
180
181
182
/****************************************************************************
183
184
    FreeStructFromStdINCHI
185
****************************************************************************/
186
EXPIMP_TEMPLATE INCHI_API
187
void INCHI_DECL FreeStructFromStdINCHI( inchi_OutputStruct *out )
188
0
{
189
0
    FreeStructFromINCHI( out );
190
0
}
191
192
193
194
/****************************************************************************
195
196
    FreeStructFromINCHI
197
198
****************************************************************************/
199
EXPIMP_TEMPLATE INCHI_API
200
void INCHI_DECL FreeStructFromINCHI( inchi_OutputStruct *out )
201
2.20k
{
202
2.20k
    if (!out)
203
0
    {
204
0
        return;
205
0
    }
206
207
2.20k
    if (out->atom)
208
353
    {
209
353
        inchi_free( out->atom );
210
353
    }
211
2.20k
    if (out->stereo0D)
212
34
    {
213
34
        inchi_free( out->stereo0D );
214
34
    }
215
2.20k
    if (out->szLog)
216
2.12k
    {
217
2.12k
        inchi_free( out->szLog );
218
2.12k
    }
219
2.20k
    if (out->szMessage)
220
2.12k
    {
221
2.12k
        inchi_free( out->szMessage );
222
2.12k
    }
223
224
2.20k
    memset( out, 0, sizeof( *out ) ); /* djb-rwth: memset_s C11/Annex K variant? */
225
2.20k
}
226
227
228
/****************************************************************************
229
230
    GetStdINCHI
231
232
****************************************************************************/
233
EXPIMP_TEMPLATE INCHI_API
234
int INCHI_DECL GetStdINCHI( inchi_Input *inp, inchi_Output *out )
235
0
{
236
0
    inchi_InputEx extended_input;
237
238
    /* No '*' or 'Zz' elements are allowed in the input . */
239
0
    if (input_erroneously_contains_pseudoatoms(inp, out))
240
0
    {
241
0
        return _IS_ERROR;
242
0
    }
243
244
0
    extended_input.atom = inp->atom;
245
0
    extended_input.num_atoms = inp->num_atoms;
246
0
    extended_input.num_stereo0D = inp->num_stereo0D;
247
0
    extended_input.stereo0D = inp->stereo0D;
248
0
    extended_input.szOptions = inp->szOptions;
249
0
    extended_input.polymer = NULL;
250
0
    extended_input.v3000 = NULL;
251
252
0
    return GetINCHI1( &extended_input, out, 1 );
253
0
}
254
255
256
/****************************************************************************
257
258
    GetINCHI
259
260
****************************************************************************/
261
EXPIMP_TEMPLATE INCHI_API
262
int INCHI_DECL GetINCHI( inchi_Input *inp, inchi_Output *out )
263
0
{
264
0
    inchi_InputEx extended_input;
265
266
    /* For back compatibility: no '*' or 'Zz' elements are allowed in the input to GetINCHI() ! */
267
0
    if ( input_erroneously_contains_pseudoatoms( inp, out) )
268
0
    {
269
0
        return _IS_ERROR;
270
0
    }
271
272
0
    extended_input.atom = inp->atom;
273
0
    extended_input.num_atoms = inp->num_atoms;
274
0
    extended_input.stereo0D = inp->stereo0D;
275
0
    extended_input.num_stereo0D = inp->num_stereo0D;
276
0
    extended_input.szOptions = inp->szOptions;
277
0
    extended_input.polymer = NULL;
278
0
    extended_input.v3000 = NULL;
279
280
0
    return GetINCHI1( &extended_input, out, 0 );
281
0
}
282
283
284
/****************************************************************************/
285
int input_erroneously_contains_pseudoatoms( inchi_Input *inp,
286
                                            inchi_Output *out)
287
0
{
288
0
    char *str_noz = "Unsupported in this mode element \'*\'";
289
0
    int i;
290
    /* Supposed that no '*' or 'Zz' elements are allowed in the input. */
291
0
    for (i = 0; i < inp->num_atoms; i++)
292
0
    {
293
0
        if (!strcmp(inp->atom->elname, "Zz") || !strcmp(inp->atom->elname, "*"))
294
0
        {
295
0
            if (out)
296
0
            {
297
0
                memset(out, 0, sizeof(*out)); /* djb-rwth: memset_s C11/Annex K variant? */
298
0
                if ((out->szMessage = (char *)inchi_malloc(strlen(str_noz) + 1))) /* djb-rwth: addressing LLVM warning */
299
0
                {
300
0
                    strcpy(out->szMessage, str_noz);
301
0
                }
302
0
            }
303
0
            return 1;
304
0
        }
305
0
    }
306
307
0
    return 0;
308
0
}
309
310
311
/****************************************************************************
312
313
    GetINCHIEx
314
315
****************************************************************************/
316
EXPIMP_TEMPLATE INCHI_API
317
int INCHI_DECL GetINCHIEx( inchi_InputEx *inp, inchi_Output *out )
318
0
{
319
0
    int i;
320
321
    /* Check for star atoms and replace them by Zz atoms */
322
0
    for (i = 0; i < inp->num_atoms; i++)
323
0
    {
324
0
        if (!strcmp( inp->atom[i].elname, "*" ))
325
0
        {
326
0
            strcpy( inp->atom[i].elname, "Zz" );
327
0
        }
328
0
    }
329
330
0
    return GetINCHI1( inp, out, 0 );
331
0
}
332
333
334
/****************************************************************************
335
    GetINCHI1 (major worker)
336
****************************************************************************/
337
static int GetINCHI1( inchi_InputEx *extended_input,
338
                      inchi_Output *out,
339
                      int enforce_std_format )
340
0
{
341
0
    STRUCT_DATA struct_data;
342
0
    STRUCT_DATA *sd = &struct_data;
343
0
    char szTitle[MAX_SDF_HEADER + MAX_SDF_VALUE + 256];
344
345
0
    int i;
346
0
    long num_inp, num_err; /* djb-rwth: ignoring LLVM warning: variable used */
347
0
    char      szSdfDataValue[MAX_SDF_VALUE + 1];
348
0
    PINChI2     *pINChI[INCHI_NUM];
349
0
    PINChI_Aux2 *pINChI_Aux[INCHI_NUM];
350
351
0
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
352
0
    unsigned long  ulTotalProcessingTime = 0; /* djb-rwth: ignoring LLVM warning: variable used */
353
354
0
    INPUT_PARMS inp_parms;
355
0
    INPUT_PARMS *ip = &inp_parms;
356
357
0
    ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */
358
0
    ORIG_ATOM_DATA *orig_inp_data = &OrigAtData;
359
0
    ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */
360
0
    ORIG_ATOM_DATA *prep_inp_data = PrepAtData;
361
0
    int             bReleaseVersion = bRELEASE_VERSION;
362
0
    int   nRet = 0, nRet1;
363
364
0
    CANON_GLOBALS CG;
365
0
    INCHI_CLOCK ic;
366
367
0
    STRUCT_FPTRS *pStructPtrs = NULL;
368
369
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
370
    int  num_repeat = REPEAT_ALL;
371
#endif
372
373
0
    const char *argv[INCHI_MAX_NUM_ARG + 1];
374
0
    int   argc;
375
0
    char *szOptions = NULL;
376
377
0
    INCHI_IOSTREAM inchi_file[3], *out_file = inchi_file, *log_file = inchi_file + 1;
378
0
    INCHI_IOSTREAM prb_file0, *prb_file = &prb_file0;
379
0
    INCHI_IOS_STRING temp_string_container;
380
0
    INCHI_IOS_STRING *strbuf = &temp_string_container;
381
382
0
    inchi_Input prev_versions_input;
383
0
    inchi_Input *pvinp = &prev_versions_input;
384
385
0
    pvinp->atom = extended_input->atom;
386
0
    pvinp->num_atoms = extended_input->num_atoms;
387
0
    pvinp->num_stereo0D = extended_input->num_stereo0D;
388
0
    pvinp->stereo0D = extended_input->stereo0D;
389
0
    pvinp->szOptions = extended_input->szOptions;
390
391
#if( TRACE_MEMORY_LEAKS == 1 )
392
    _CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF );
393
/* for execution outside the VC++ debugger uncomment one of the following two */
394
#ifdef MY_REPORT_FILE
395
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
396
    _CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
397
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
398
    _CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
399
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
400
    _CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
401
#else
402
    _CrtSetReportMode( _CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG );
403
#endif
404
405
#if ( !defined(__STDC__) || __STDC__ != 1 )
406
    /* turn on floating point exceptions */
407
    {
408
        /* Get the default control word. */
409
        int cw = _controlfp( 0, 0 );
410
411
        /* Set the exception masks OFF, turn exceptions on. */
412
        /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
413
        cw &= ~( EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL );
414
415
        /* Set the control word. */
416
        _controlfp( cw, MCW_EM );
417
    }
418
#endif
419
#endif
420
421
0
    szTitle[0] = '\0';
422
423
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
424
    repeat:
425
          inchi_ios_close( out_file );
426
          inchi_ios_close( log_file );
427
          inchi_ios_close( prb_file );
428
          pStr = NULL;
429
#endif
430
431
    /* Initialize internal for this function output streams as string buffers */
432
0
    inchi_ios_init( out_file, INCHI_IOS_TYPE_STRING, NULL );
433
0
    inchi_ios_init( log_file, INCHI_IOS_TYPE_STRING, NULL );
434
0
    inchi_ios_init( prb_file, INCHI_IOS_TYPE_STRING, NULL );
435
436
0
    num_inp = 0;
437
0
    num_err = 0;
438
0
    sd->bUserQuit = 0;
439
440
    /* clear original input structure */
441
0
    memset( pINChI, 0, sizeof( pINChI ) ); /* djb-rwth: memset_s C11/Annex K variant? */
442
0
    memset( pINChI_Aux, 0, sizeof( pINChI_Aux ) ); /* djb-rwth: memset_s C11/Annex K variant? */
443
0
    memset( sd, 0, sizeof( *sd ) ); /* djb-rwth: memset_s C11/Annex K variant? */
444
0
    memset( ip, 0, sizeof( *ip ) ); /* djb-rwth: memset_s C11/Annex K variant? */
445
0
    memset( orig_inp_data, 0, sizeof( *orig_inp_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
446
0
    memset( prep_inp_data, 0, 2 * sizeof( *prep_inp_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
447
0
    memset( szSdfDataValue, 0, sizeof( szSdfDataValue ) ); /* djb-rwth: memset_s C11/Annex K variant? */
448
449
0
    memset( &CG, 0, sizeof( CG ) ); /* djb-rwth: memset_s C11/Annex K variant? */
450
0
    memset( &ic, 0, sizeof( ic ) ); /* djb-rwth: memset_s C11/Annex K variant? */
451
452
0
    if (!out)
453
0
    {
454
0
        nRet = _IS_ERROR;
455
0
        goto exit_function;
456
0
    }
457
0
    memset( out, 0, sizeof( *out ) ); /* djb-rwth: memset_s C11/Annex K variant? */
458
459
    /* options */
460
0
    if (pvinp && pvinp->szOptions)
461
0
    {
462
0
        szOptions = (char*) inchi_malloc( strlen( pvinp->szOptions ) + 1 );
463
0
        if (szOptions)
464
0
        {
465
0
            strcpy( szOptions, pvinp->szOptions );
466
0
            argc = parse_options_string( szOptions, argv, INCHI_MAX_NUM_ARG );
467
0
        }
468
0
        else
469
0
        {
470
0
            nRet = _IS_FATAL;
471
0
            goto translate_RetVal; /* emergency exit */
472
0
        }
473
0
    }
474
0
    else
475
0
    {
476
0
        argc = 1;
477
0
        argv[0] = "";
478
0
        argv[1] = NULL;
479
0
    }
480
481
0
    if ((argc == 1
482
0
#ifdef TARGET_API_LIB
483
0
              && ( !pvinp || pvinp->num_atoms <= 0 || !pvinp->atom ))
484
0
#endif
485
0
              || (argc == 2 && ( argv[1][0] == INCHI_OPTION_PREFX ) &&
486
0
                    ( !strcmp( argv[1] + 1, "?" ) || !inchi_stricmp( argv[1] + 1, "help" )) )) /* djb-rwth: addressing LLVM warnings */
487
0
    {
488
0
        HelpCommandLineParms( log_file );
489
0
        out->szLog = log_file->s.pStr;
490
0
        memset( log_file, 0, sizeof( *log_file ) ); /* djb-rwth: memset_s C11/Annex K variant? */
491
0
        nRet = _IS_EOF;
492
0
        goto translate_RetVal;
493
0
    }
494
495
0
    nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue, &ulDisplTime, bReleaseVersion, log_file );
496
0
    if (szOptions)
497
0
    {
498
0
        inchi_free( szOptions );
499
0
        szOptions = NULL;
500
0
    }
501
    /* INChI DLL specific */
502
0
    ip->bNoStructLabels = 1;
503
504
0
    if (0 > nRet1)
505
0
    {
506
0
        nRet = _IS_FATAL;
507
0
        goto exit_function;
508
0
    }
509
0
    if (ip->bNoStructLabels)
510
0
    {
511
0
        ip->pSdfLabel = NULL;
512
0
        ip->pSdfValue = NULL;
513
0
    }
514
0
    else
515
0
    {
516
0
        if (ip->nInputType == INPUT_INCHI_XML || ip->nInputType == INPUT_INCHI_PLAIN || ip->nInputType == INPUT_CMLFILE)
517
0
        {
518
            /* the input may contain both the header and the label of the structure */
519
0
            if (!ip->pSdfLabel)
520
0
                ip->pSdfLabel = ip->szSdfDataHeader;
521
0
            if (!ip->pSdfValue)
522
0
                ip->pSdfValue = szSdfDataValue;
523
0
        }
524
0
    }
525
526
    /* Ensure standardness */
527
0
    if (enforce_std_format)
528
0
    {
529
0
        if (ip->bINChIOutputOptions & INCHI_OUT_SAVEOPT)
530
0
        {
531
0
            ip->bINChIOutputOptions &= ~INCHI_OUT_SAVEOPT;
532
0
        }
533
0
        if (0 != ( ip->bTautFlags & TG_FLAG_RECONNECT_COORD ))
534
0
        {
535
0
            ip->bTautFlags &= ~TG_FLAG_RECONNECT_COORD;
536
0
        }
537
0
        if (0 != ( ip->nMode & REQ_MODE_BASIC ))
538
0
        {
539
0
            ip->nMode &= ~REQ_MODE_BASIC;
540
0
        }
541
0
        if (0 != ( ip->nMode & REQ_MODE_RELATIVE_STEREO ))
542
0
        {
543
0
            ip->nMode &= ~( REQ_MODE_RACEMIC_STEREO | REQ_MODE_RELATIVE_STEREO | REQ_MODE_CHIR_FLG_STEREO );
544
0
        }
545
0
        if (0 != ( ip->nMode & REQ_MODE_RACEMIC_STEREO ))
546
0
        {
547
0
            ip->nMode &= ~( REQ_MODE_RACEMIC_STEREO | REQ_MODE_RELATIVE_STEREO | REQ_MODE_CHIR_FLG_STEREO );
548
0
        }
549
0
        if (0 != ( ip->nMode & REQ_MODE_CHIR_FLG_STEREO ))
550
0
        {
551
0
            ip->nMode &= ~( REQ_MODE_RACEMIC_STEREO | REQ_MODE_RELATIVE_STEREO | REQ_MODE_CHIR_FLG_STEREO );
552
0
        }
553
0
        if (0 != ( ip->nMode & REQ_MODE_DIFF_UU_STEREO ))
554
0
        {
555
0
            ip->nMode &= ~REQ_MODE_DIFF_UU_STEREO;
556
0
        }
557
0
        if (0 == ( ip->nMode & ( REQ_MODE_SB_IGN_ALL_UU | REQ_MODE_SC_IGN_ALL_UU ) ))
558
0
        {
559
0
            ip->nMode |= REQ_MODE_SB_IGN_ALL_UU;
560
0
            ip->nMode |= REQ_MODE_SC_IGN_ALL_UU;
561
0
        }
562
0
        if (0 != ( ip->bTautFlags & TG_FLAG_KETO_ENOL_TAUT ))
563
0
        {
564
0
            ip->bTautFlags &= ~TG_FLAG_KETO_ENOL_TAUT;
565
0
        }
566
0
        if (0 != ( ip->bTautFlags & TG_FLAG_1_5_TAUT ))
567
0
        {
568
0
            ip->bTautFlags &= ~TG_FLAG_1_5_TAUT;
569
0
        }
570
        /* And anyway... */
571
0
        ip->bINChIOutputOptions |= INCHI_OUT_STDINCHI;
572
0
        ip->bINChIOutputOptions &= ~INCHI_OUT_SAVEOPT;
573
0
    }
574
    /* */
575
576
0
    PrintInputParms( log_file, ip );
577
578
0
    if (0 >= inchi_strbuf_init( strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT ))
579
0
    {
580
0
        inchi_ios_eprint( log_file, "Cannot allocate internal string buffer. Terminating\n" );
581
0
        nRet = _IS_FATAL;
582
0
        goto exit_function;
583
0
    }
584
585
    /***************************************************
586
    Main cycle -- read input structures and create their INChI's */ /* djb-rwth: addressing LLVM warning */
587
0
    ulTotalProcessingTime = 0;
588
589
0
    if (pStructPtrs)
590
0
    {
591
0
        memset( pStructPtrs, 0, sizeof( pStructPtrs[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
592
0
    }
593
594
    /* === possible improvement: convert inp to orig_inp_data ==== */
595
0
    if (!sd->bUserQuit && !bInterrupted)
596
0
    {
597
0
        if (ip->last_struct_number && num_inp >= ip->last_struct_number)
598
0
        {
599
0
            nRet = _IS_EOF; /*  simulate end of file */
600
0
            goto exit_function;
601
0
        }
602
603
0
        nRet = ExtractOneStructure( sd,ip, szTitle, extended_input,
604
0
                                    log_file, out_file, prb_file,
605
0
                                    orig_inp_data, &num_inp );
606
607
0
        if (pStructPtrs)
608
0
        {
609
0
            pStructPtrs->cur_fptr++;
610
0
        }
611
612
#ifndef TARGET_API_LIB
613
        if (sd->bUserQuit)
614
        {
615
            break;
616
        }
617
#endif
618
0
        switch (nRet)
619
0
        {
620
0
            case _IS_FATAL:
621
0
                num_err++;
622
0
                goto exit_function;
623
0
            case _IS_EOF:
624
0
                goto exit_function;
625
0
            case _IS_ERROR:
626
0
                num_err++;
627
0
                goto exit_function;
628
#ifndef TARGET_API_LIB
629
            case _IS_SKIP:
630
                continue;
631
#endif
632
0
        }
633
634
        /* Create INChI for each connected component of the structure and */
635
        /* optionally display them ; output INChI for the whole structure */
636
637
0
        nRet1 = ProcessOneStructureEx( &ic, &CG, sd, ip, szTitle,
638
0
                                        pINChI, pINChI_Aux,
639
0
                                        NULL, /* inp_file is not necessary as all input is already saved in 'ip' */
640
0
                                        log_file, out_file, prb_file,
641
0
                                        orig_inp_data, prep_inp_data,
642
0
                                        num_inp, strbuf, 0 /* save_opt_bits */ );
643
644
        /*  Free INChI memory */
645
0
        FreeAllINChIArrays( pINChI, pINChI_Aux, sd->num_components );
646
647
        /* Free structure data */
648
0
        FreeOrigAtData( orig_inp_data );
649
0
        FreeOrigAtData( prep_inp_data );
650
0
        FreeOrigAtData( prep_inp_data + 1 );
651
652
0
        ulTotalProcessingTime += sd->ulStructTime;
653
0
        nRet = inchi_max( nRet, nRet1 );
654
0
        switch (nRet)
655
0
        {
656
0
            case _IS_FATAL:
657
                /* num_err ++; */
658
0
                goto exit_function;
659
0
            case _IS_ERROR:
660
0
                ; /* num_err ++; */
661
#ifndef TARGET_API_LIB
662
                continue;
663
#endif
664
0
        }
665
0
    }
666
667
0
exit_function:
668
    /* Avoid memory leaks in case of fatal error */
669
0
    if (pStructPtrs && pStructPtrs->fptr)
670
0
    {
671
0
        inchi_free( pStructPtrs->fptr );
672
0
    }
673
    /* Free INChI memory */
674
0
    FreeAllINChIArrays( pINChI, pINChI_Aux, sd->num_components );
675
    /*    Free structure data */
676
0
    FreeOrigAtData( orig_inp_data );
677
0
    FreeOrigAtData( prep_inp_data );
678
0
    FreeOrigAtData( prep_inp_data + 1 );
679
680
0
    inchi_strbuf_close( strbuf );
681
682
0
    for (i = 0; i < MAX_NUM_PATHS; i++)
683
0
    {
684
0
        if (ip->path[i])
685
0
        {
686
0
            inchi_free( (char*) ip->path[i] ); /*  cast deliberately discards 'const' qualifier */
687
0
            ip->path[i] = NULL;
688
0
        }
689
0
    }
690
691
0
    SetBitFree( &CG );
692
693
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
694
    if (num_repeat-- > 0)
695
    {
696
        goto repeat;
697
    }
698
#endif
699
700
    /* output */
701
0
    produce_generation_output( out, sd, ip, log_file, out_file );
702
703
0
translate_RetVal:
704
705
    /* Close inernal I/O streams */
706
0
    inchi_ios_close( log_file );
707
0
    inchi_ios_close( out_file );
708
0
    inchi_ios_close( prb_file );
709
710
0
    switch (nRet)
711
0
    {
712
0
        case _IS_SKIP: nRet = inchi_Ret_SKIP; break; /* not used in INChI dll */
713
0
        case _IS_EOF: nRet = inchi_Ret_EOF; break; /* no structural data has been provided */
714
0
        case _IS_OKAY: nRet = inchi_Ret_OKAY; break; /* Success; break; no errors or warnings */
715
0
        case _IS_WARNING: nRet = inchi_Ret_WARNING; break; /* Success; break; warning(s) issued */
716
0
        case _IS_ERROR: nRet = inchi_Ret_ERROR; break; /* Error: no INChI has been created */
717
0
        case _IS_FATAL: nRet = inchi_Ret_FATAL; break; /* Severe error: no INChI has been created (typically; break; memory allocation failed) */
718
0
        case _IS_UNKNOWN:
719
0
        default: nRet = inchi_Ret_UNKNOWN; break; /* Unlnown program error */
720
0
    }
721
722
0
    return nRet;
723
0
}
724
725
726
/****************************************************************************/
727
void produce_generation_output( inchi_Output *out,
728
                                STRUCT_DATA *sd,
729
                                INPUT_PARMS *ip,
730
                                INCHI_IOSTREAM *log_file,
731
                                INCHI_IOSTREAM *out_file )
732
733
0
{
734
0
    if (sd->pStrErrStruct[0])
735
0
    {
736
0
        if (out && ( out->szMessage = (char *) inchi_malloc( strlen( sd->pStrErrStruct ) + 1 ) ))
737
0
        {
738
0
            strcpy(out->szMessage, sd->pStrErrStruct);
739
0
        }
740
0
    }
741
742
    /* Make separate strings with InChI and AuxInfo */
743
0
    if (out_file->s.pStr && out_file->s.nUsedLength > 0 && out)
744
0
    {
745
0
        char *p;
746
0
        out->szInChI = out_file->s.pStr;
747
0
        out->szAuxInfo = NULL;
748
0
        if (!( INCHI_OUT_SDFILE_ONLY & ip->bINChIOutputOptions )) /* do not remove last LF from SDF output - 2008-12-23 DT */
749
0
        {
750
0
            for (p = strchr( out->szInChI, '\n' ); p; p = strchr( p + 1, '\n' ))
751
0
            {
752
0
                if (!memcmp( p, "\nAuxInfo", 8 ))
753
0
                {
754
0
                    *p = '\0';            /* remove LF after INChI */
755
0
                    out->szAuxInfo = p + 1; /* save pointer to AuxInfo */
756
0
                }
757
0
                else if (out->szAuxInfo || !p[1])
758
0
                {
759
                    /* remove LF after aux info or from the last char */
760
0
                    *p = '\0';
761
0
                    break;
762
0
                }
763
0
            }
764
0
        }
765
0
        out_file->s.pStr = NULL;
766
0
    }
767
768
0
    copy_corrected_log_tail( out, log_file );
769
0
}
770
771
772
/****************************************************************************/
773
void copy_corrected_log_tail( inchi_Output *out, INCHI_IOSTREAM *log_file )
774
0
{
775
0
    if (log_file->s.pStr && log_file->s.nUsedLength > 0)
776
0
    {
777
0
        while (log_file->s.nUsedLength &&
778
0
                '\n' == log_file->s.pStr[log_file->s.nUsedLength - 1])
779
0
        {
780
0
            log_file->s.pStr[--log_file->s.nUsedLength] = '\0';
781
                                            /* remove last LF */
782
0
        }
783
0
        if (out)
784
0
        {
785
0
            char *p;
786
0
            out->szLog = log_file->s.pStr;
787
0
            log_file->s.pStr = NULL;
788
0
            for (p = strchr( out->szLog, ' ' ); p; p = strchr( p + 1, ' ' ))
789
0
            {
790
0
                if (!memcmp( p, " structure #", 12 ))
791
0
                {
792
0
                    *p = '\0';
793
0
                }
794
0
            }
795
0
        }
796
0
    }
797
0
}
798
799
800
/****************************************************************************
801
802
    CheckINCHI
803
804
    Check if the string represents valid InChI/standard InChI.
805
    Input:
806
            szINCHI     source InChI
807
            strict      if 0, just quickly check for proper layout
808
                        (prefix, version, etc.)
809
                        The result may not be strict.
810
                        If not 0, try to perform InChI2InChI conversion and
811
                        returns success if a resulting InChI string exactly
812
                        match source.
813
                        The result may be 'false alarm' due to imperfect algorithm of
814
                        conversion.
815
    Returns:
816
            success/errors codes
817
818
****************************************************************************/
819
EXPIMP_TEMPLATE INCHI_API
820
int INCHI_DECL CheckINCHI( const char *szINCHI, const int strict )
821
4.40k
{
822
4.40k
    int ret = INCHI_VALID_NON_STANDARD;
823
4.40k
    int ret_i2i;
824
4.40k
    inchi_InputINCHI    inchi_inp;
825
4.40k
    inchi_Output        inchi_out;
826
4.40k
    size_t slen, pos_slash1 = 0;
827
4.40k
    char *str = NULL;
828
4.40k
    size_t i;
829
4.40k
    size_t slen0;
830
4.40k
    char pp;
831
832
    /* .. non-empty */
833
4.40k
    if (szINCHI == NULL)
834
0
    {
835
0
        return INCHI_INVALID_PREFIX;
836
0
    }
837
838
4.40k
    slen = strlen( szINCHI );
839
840
841
    /* .. has valid prefix */
842
4.40k
    if (slen < LEN_INCHI_STRING_PREFIX + 3)
843
8
    {
844
8
        return INCHI_INVALID_PREFIX;
845
8
    }
846
4.39k
    if (memcmp( szINCHI, INCHI_STRING_PREFIX, LEN_INCHI_STRING_PREFIX ))
847
10
    {
848
10
        return INCHI_INVALID_PREFIX;
849
10
    }
850
851
    /* .. has InChI version 1 */
852
    /* if (!isdigit(szINCHI[LEN_INCHI_STRING_PREFIX]) )  */
853
4.38k
    if (szINCHI[LEN_INCHI_STRING_PREFIX] != '1')
854
0
    {
855
0
        return INCHI_INVALID_VERSION;
856
0
    }
857
858
    /* .. optionally has a 'standard' flag character */
859
4.38k
    pos_slash1 = LEN_INCHI_STRING_PREFIX + 1;
860
4.38k
    if (szINCHI[pos_slash1] == 'S')
861
0
    {
862
        /* Standard InChI ==> standard InChIKey */
863
0
        ret = INCHI_VALID_STANDARD;
864
0
        pos_slash1++;
865
0
    }
866
4.38k
    else if (szINCHI[pos_slash1] == 'B')
867
6
    {
868
        /* Beta version InChI ==> non-standard */
869
6
        ret = INCHI_VALID_BETA;
870
6
        pos_slash1++;
871
6
    }
872
873
    /* .. has trailing slash in the right place */
874
4.38k
    if (szINCHI[pos_slash1] != '/')
875
2
    {
876
2
        return INCHI_INVALID_LAYOUT;
877
2
    }
878
879
    /* .. the rest of source string contains valid literals */
880
881
882
    /* adjust line len so we not check trailing whitespaces */
883
4.38k
    i = slen - 1;
884
4.38k
    while (isspace(UCINT szINCHI[i--])) slen--;
885
886
    /* Treat possible SaveOpt letters  */
887
4.38k
    slen0 = slen;
888
4.38k
    if (( szINCHI[slen - 3] == '\\' ) &&
889
4.38k
        ( szINCHI[slen - 2] >= 'A' ) && ( szINCHI[slen - 2] <= 'Z' ) &&
890
4.38k
        ( szINCHI[slen - 1] >= 'A' ) && ( szINCHI[slen - 1] <= 'Z' )
891
4.38k
        )
892
8
    {
893
8
        slen0 = slen - 3;
894
8
    }
895
896
4.38k
    int prev_is_slash = 1;
897
3.42M
    for (i = pos_slash1 + 1; i < slen0; i++)
898
3.42M
    {
899
3.42M
        pp = szINCHI[i];
900
3.42M
#if ( FIX_GAF_2020_GENERIC==1 )
901
3.42M
        if (prev_is_slash)
902
50.0k
        {
903
            /* After slash: */
904
50.0k
            if (pp == '0')
905
0
            {
906
                /* '0' is never allowed */
907
0
                return INCHI_INVALID_LAYOUT;
908
0
            }
909
50.0k
            if (i > pos_slash1 + 1)
910
45.6k
            {
911
                /* Not in main formula layer... */ 
912
45.6k
                if (!islower(pp))
913
24
                {
914
                    /* only lowercase letters are allowed */
915
24
                    return INCHI_INVALID_LAYOUT;
916
24
                }
917
45.6k
            }
918
50.0k
        }
919
3.42M
        prev_is_slash = (pp != '/') ? 0 : 1;
920
3.42M
#endif
921
3.42M
        if (pp >= 'A' && pp <= 'Z')   continue;
922
3.15M
        if (pp >= 'a' && pp <= 'z')   continue;
923
2.27M
        if (pp >= '0' && pp <= '9')  continue;
924
913k
        switch (pp)
925
913k
        {
926
326k
            case '(': case ')':
927
331k
            case '*': case '+':
928
850k
            case ',': case '-':
929
904k
            case '.': case '/':
930
904k
#if ( FIX_GAF_2020_GENERIC==1 )
931
913k
            case ';': case '?':     continue;
932
#else
933
            case ';': case '=':
934
            case '?': case '@':     continue;
935
#endif
936
110
            default:            return INCHI_INVALID_LAYOUT;
937
913k
        }
938
913k
    }
939
940
4.25k
    if (strict)
941
0
    {
942
0
        char opts[] = "?FixedH ?RecMet ?SUU ?SLUUD";
943
0
        extract_inchi_substring( &str, szINCHI, slen );
944
0
        if (NULL == str)
945
0
        {
946
0
            ret = INCHI_FAIL_I2I;
947
0
            goto fin;
948
0
        }
949
950
0
        inchi_inp.szInChI = str;
951
0
        opts[0] = opts[8] = opts[16] = opts[21] = INCHI_OPTION_PREFX;
952
0
        inchi_inp.szOptions = opts;
953
954
0
        ret_i2i = GetINCHIfromINCHI( &inchi_inp, &inchi_out );
955
956
0
        if (( ( ret_i2i != inchi_Ret_OKAY ) && ( ret_i2i != inchi_Ret_WARNING ) ) || !inchi_out.szInChI)
957
0
        {
958
0
            ret = INCHI_FAIL_I2I;
959
0
        }
960
0
        else
961
0
        {
962
0
            if (strcmp( inchi_inp.szInChI, inchi_out.szInChI ))
963
0
            {
964
0
                ret = INCHI_FAIL_I2I;
965
0
            }
966
0
        }
967
0
    }
968
969
4.25k
fin:if (strict)
970
0
{
971
0
    if (NULL != str)
972
0
        inchi_free( str );
973
0
}
974
975
4.25k
    return ret;
976
4.25k
}
977
978
979
/****************************************************************************/
980
void SetNumImplicitH( inp_ATOM* at, int num_atoms )
981
0
{
982
0
    int bNonMetal;
983
0
    int a1/*, n1*/;
984
985
    /* special valences */
986
0
    for (bNonMetal = 0; bNonMetal < 2; bNonMetal++)
987
0
    {
988
0
        for (a1 = 0; a1 < num_atoms; a1++)
989
0
        {
990
0
            int bHasMetalNeighbor /*, j*/;
991
0
            if (bNonMetal != is_el_a_metal( at[a1].el_number ))
992
0
            {
993
0
                continue; /* first process all metals, after that all non-metals */
994
0
            }
995
996
0
            bHasMetalNeighbor = 0;
997
            /***********************************************************************
998
             *  Set number of hydrogen atoms
999
             */
1000
0
            at[a1].num_H = get_num_H( at[a1].elname,
1001
0
                                      at[a1].num_H,
1002
0
                                      at[a1].num_iso_H,
1003
0
                                      at[a1].charge,
1004
0
                                      at[a1].radical,
1005
0
                                      at[a1].chem_bonds_valence,
1006
0
                                      0, /* instead of valence entered by the user: it does not exist here*/
1007
0
                                      ( at[a1].at_type & 1 )  /* bAliased */,
1008
0
                                      !( at[a1].at_type & 2 ) /* bDoNotAddH */,
1009
0
                                      bHasMetalNeighbor );
1010
0
            at[a1].at_type = 0;
1011
0
        }
1012
0
    }
1013
0
}
1014
1015
1016
/****************************************************************************/
1017
1018
1019
#define REPEAT_ALL  0
1020
1021
1022
/****************************************************************************/
1023
int parse_options_string( char *cmd, const char *argv[], int maxargs )
1024
4.40k
{
1025
4.40k
    char    *p;
1026
4.40k
    char    *pArgCurChar;
1027
4.40k
    int      bInsideQuotes;
1028
4.40k
    int      bCopyCharToArg;
1029
4.40k
    int      nNumBackSlashes;
1030
4.40k
    int      i;
1031
1032
4.40k
    i = 0;
1033
4.40k
    argv[i++] = ""; /* zeroth argument is not used */
1034
4.40k
    p = cmd;
1035
4.40k
    bInsideQuotes = 0;
1036
1037
    /* arguments, one by one */
1038
8.81k
    while (i < maxargs - 1)
1039
8.81k
    {
1040
        /* bypass spaces */
1041
13.2k
        while (*p == ' ' || *p == '\t')
1042
4.40k
        {
1043
4.40k
            p++;
1044
4.40k
        }
1045
8.81k
        if (!*p)
1046
4.40k
        {
1047
4.40k
            break;
1048
4.40k
        }
1049
1050
        /* scan an argument */
1051
4.40k
        argv[i++] = pArgCurChar = p;     /* store preliminary ptr to arg */
1052
1053
59.4k
        while (1)
1054
59.4k
        {
1055
59.4k
            bCopyCharToArg = 1;
1056
59.4k
            nNumBackSlashes = 0;
1057
59.4k
            while (*p == '\\')
1058
0
            {
1059
0
                ++p;
1060
0
                ++nNumBackSlashes;
1061
0
            }
1062
1063
            /* each pair of backslashes => one backslash; one more backslash => literal quote */
1064
59.4k
            if (*p == '\"')
1065
0
            {
1066
                /* one " found */
1067
0
                if (nNumBackSlashes % 2 == 0)
1068
0
                {
1069
0
                    if (bInsideQuotes)
1070
0
                    {
1071
0
                        if (*( p + 1 ) == '\"')
1072
0
                        {
1073
0
                            p++;
1074
0
                        }
1075
0
                        else
1076
0
                        {
1077
0
                            bCopyCharToArg = 0;
1078
0
                        }
1079
0
                    }
1080
0
                    else
1081
0
                    {
1082
0
                        bCopyCharToArg = 0;
1083
0
                    }
1084
0
                    bInsideQuotes = !bInsideQuotes;
1085
0
                }
1086
0
                nNumBackSlashes /= 2;          /* divide nNumBackSlashes by two */
1087
0
            }
1088
59.4k
            while (nNumBackSlashes--)
1089
0
            {
1090
0
                *pArgCurChar++ = '\\';
1091
0
            }
1092
59.4k
            if (!*p)
1093
4.40k
            {
1094
4.40k
                break;
1095
4.40k
            }
1096
55.0k
            if (!bInsideQuotes && ( *p == ' ' || *p == '\t' ))
1097
0
            {
1098
0
                p++;
1099
                /* move to the next char because this char may become
1100
                 * zero due to  *pArgCurChar++ = '\0'; line below */
1101
0
                break;
1102
0
            }
1103
55.0k
            if (bCopyCharToArg)
1104
55.0k
            {
1105
55.0k
                *pArgCurChar++ = *p;
1106
55.0k
            }
1107
55.0k
            ++p;
1108
55.0k
        }
1109
4.40k
        *pArgCurChar++ = '\0';  /* argument zero termination */
1110
4.40k
    }
1111
1112
    /* The last argument is NULL */
1113
4.40k
    argv[i] = NULL;
1114
1115
4.40k
    return i;
1116
4.40k
}
1117
1118
1119
/****************************************************************************/
1120
1121
0
#define MIN_BOND_LENGTH   (1.0e-6)
1122
1123
1124
/****************************************************************************/
1125
int SetAtomProperties( inp_ATOM *at,
1126
                       MOL_COORD *szCoord,
1127
                       inchi_Atom *ati,
1128
                       int a1,
1129
                       int *nDim,
1130
                       char *pStrErr,
1131
                       int *err )
1132
0
{
1133
0
    S_CHAR      cRadical;
1134
1135
    /* element, check later */
1136
0
    strcpy( at[a1].elname, ati[a1].elname );
1137
1138
    /* charge */
1139
0
    at[a1].charge = ati[a1].charge;
1140
1141
    /* radical */
1142
0
    switch (ati[a1].radical)
1143
0
    {
1144
0
        case   INCHI_RADICAL_NONE:
1145
0
            cRadical = 0;
1146
0
            break;
1147
0
        case   INCHI_RADICAL_SINGLET:
1148
0
#if( SINGLET_IS_TRIPLET == 1) /* 'singlet' means two electrons make a lone pair instead of 2 bonds*/
1149
                              /* its effect on valence is same as the effect of a triplet */
1150
0
            cRadical = RADICAL_TRIPLET;
1151
#else
1152
            cRadical = RADICAL_SINGLET;
1153
#endif
1154
0
            break;
1155
0
        case   INCHI_RADICAL_DOUBLET:
1156
0
            cRadical = RADICAL_DOUBLET;
1157
0
            break;
1158
0
        case   INCHI_RADICAL_TRIPLET:
1159
0
            cRadical = RADICAL_TRIPLET;
1160
0
            break;
1161
0
        default:
1162
0
        {
1163
0
            char szRadicalType[16];
1164
0
            int nRad = ati[a1].radical;
1165
0
            while (nRad > RADICAL_TRIPLET)
1166
0
            {
1167
0
                nRad -= 2;
1168
0
            }
1169
0
            sprintf( szRadicalType, "%d->%d", ati[a1].radical, nRad );
1170
0
            TREAT_ERR( *err, 0, "Radical center type replaced:" );
1171
0
            TREAT_ERR( *err, 0, szRadicalType );
1172
0
            cRadical = nRad;
1173
0
            if (nRad < 0)
1174
0
            {
1175
0
                *err |= 8; /*  Unrecognized Radical replaced with non-radical */
1176
0
            }
1177
0
        }
1178
0
        break;
1179
0
    }
1180
0
    at[a1].radical = cRadical;
1181
1182
    /* coordinates */
1183
0
    at[a1].x = ati[a1].x;
1184
0
    at[a1].y = ati[a1].y;
1185
0
    at[a1].z = ati[a1].z;
1186
1187
0
    if (szCoord)
1188
0
    {
1189
        /* store text coordinates */
1190
0
        char str[32];
1191
0
        MOL_COORD * coord_p = szCoord + a1;
1192
0
        WriteCoord( str, ati[a1].x );
1193
0
        memcpy( *coord_p, str, 10 );
1194
0
        WriteCoord( str, ati[a1].y );
1195
0
        memcpy( *coord_p + 10, str, 10 );
1196
0
        WriteCoord( str, ati[a1].z );
1197
0
        memcpy( *coord_p + 20, str, 10 );
1198
0
    }
1199
1200
0
    if (MIN_BOND_LENGTH < fabs( ati[a1].x ) || MIN_BOND_LENGTH < fabs( ati[a1].y ) || MIN_BOND_LENGTH < fabs( ati[a1].z ))
1201
0
    {
1202
0
        if (MIN_BOND_LENGTH < fabs( ati[a1].z ))
1203
0
        {
1204
0
            *nDim |= 3;
1205
0
        }
1206
0
        else
1207
0
        {
1208
0
            *nDim |= 2;
1209
0
        }
1210
0
    }
1211
1212
    /* orig. at. number */
1213
0
    at[a1].orig_at_number = a1 + 1;
1214
0
    return 0;
1215
1216
0
#undef MIN_BOND_LENGTH
1217
0
}
1218
1219
1220
/****************************************************************************/
1221
int SetBondProperties( inp_ATOM *at,
1222
                       inchi_Atom *ati,
1223
                       int a1,
1224
                       int j,
1225
                       int nNumAtoms,
1226
                       int *nNumBonds,
1227
                       char *pStrErr,
1228
                       int *err )
1229
0
{
1230
0
    int a2;
1231
0
    S_CHAR     cBondType, cStereoType1, cStereoType2;
1232
0
    AT_NUMB   *p1, *p2;
1233
0
    int        n1, n2;
1234
1235
    /* bond type */
1236
0
    switch (ati[a1].bond_type[j])
1237
0
    {
1238
0
        case INCHI_BOND_TYPE_SINGLE:
1239
0
            cBondType = BOND_TYPE_SINGLE;
1240
0
            break;
1241
0
        case INCHI_BOND_TYPE_DOUBLE:
1242
0
            cBondType = BOND_TYPE_DOUBLE;
1243
0
            break;
1244
0
        case INCHI_BOND_TYPE_TRIPLE:
1245
0
            cBondType = BOND_TYPE_TRIPLE;
1246
0
            break;
1247
0
        case INCHI_BOND_TYPE_ALTERN:
1248
0
            cBondType = BOND_TYPE_ALTERN;
1249
0
            break;
1250
0
        default:
1251
0
        {
1252
0
            char szBondType[16];
1253
0
            sprintf( szBondType, "%d", ati[a1].bond_type[j] );
1254
0
            TREAT_ERR( *err, 0, "Unrecognized bond type:" );
1255
0
            TREAT_ERR( *err, 0, szBondType );
1256
0
            *err |= 8; /*  Unrecognized Bond type replaced with single bond */
1257
0
            cBondType = BOND_TYPE_SINGLE;
1258
0
        }
1259
0
        break;
1260
0
    }
1261
1262
    /* 2D stereo */
1263
1264
0
    switch (ati[a1].bond_stereo[j])
1265
0
    {
1266
    /* stereocenter-related; positive: the sharp end points to this atom  */
1267
0
        case   INCHI_BOND_STEREO_NONE:
1268
0
            cStereoType1 = 0;
1269
0
            cStereoType2 = 0;
1270
0
            break;
1271
0
        case   INCHI_BOND_STEREO_SINGLE_1UP:
1272
0
            cStereoType1 = STEREO_SNGL_UP;
1273
0
            cStereoType2 = -STEREO_SNGL_UP;
1274
0
            break;
1275
0
        case   INCHI_BOND_STEREO_SINGLE_1EITHER:
1276
0
            cStereoType1 = STEREO_SNGL_EITHER;
1277
0
            cStereoType2 = -STEREO_SNGL_EITHER;
1278
0
            break;
1279
0
        case   INCHI_BOND_STEREO_SINGLE_1DOWN:
1280
0
            cStereoType1 = STEREO_SNGL_DOWN;
1281
0
            cStereoType2 = -STEREO_SNGL_DOWN;
1282
0
            break;
1283
        /* stereocenter-related; negative: the sharp end points to the opposite atom  */
1284
0
        case   INCHI_BOND_STEREO_SINGLE_2UP:
1285
0
            cStereoType1 = -STEREO_SNGL_UP;
1286
0
            cStereoType2 = STEREO_SNGL_UP;
1287
0
            break;
1288
0
        case   INCHI_BOND_STEREO_SINGLE_2EITHER:
1289
0
            cStereoType1 = -STEREO_SNGL_EITHER;
1290
0
            cStereoType2 = STEREO_SNGL_EITHER;
1291
0
            break;
1292
0
        case   INCHI_BOND_STEREO_SINGLE_2DOWN:
1293
0
            cStereoType1 = -STEREO_SNGL_DOWN;
1294
0
            cStereoType2 = STEREO_SNGL_DOWN;
1295
0
            break;
1296
        /* stereobond-related */
1297
0
        case   INCHI_BOND_STEREO_DOUBLE_EITHER:
1298
0
        case  -INCHI_BOND_STEREO_DOUBLE_EITHER:
1299
0
            cStereoType1 = STEREO_DBLE_EITHER;
1300
0
            cStereoType2 = STEREO_DBLE_EITHER;
1301
0
            break;
1302
0
        default:
1303
0
        {
1304
0
            char szBondType[16];
1305
0
            sprintf( szBondType, "%d", ati[a1].bond_stereo[j] );
1306
0
            TREAT_ERR( *err, 0, "Unrecognized bond stereo:" );
1307
0
            TREAT_ERR( *err, 0, szBondType );
1308
0
            *err |= 8; /*  Unrecognized Bond stereo replaced with non-stereo bond */
1309
0
            cStereoType1 = 0;
1310
0
            cStereoType2 = 0;
1311
0
        }
1312
0
        break;
1313
0
    }
1314
1315
    /* neighbor */
1316
0
    if (ati[a1].neighbor[j] < 0 || ati[a1].neighbor[j] >= nNumAtoms)
1317
0
    {
1318
0
        *err |= 1; /*  bond for impossible atom number(s); ignored */
1319
0
        TREAT_ERR( *err, 0, "Bond to nonexistent atom" );
1320
0
        goto err_exit;
1321
0
    }
1322
1323
0
    a2 = (AT_NUMB) ati[a1].neighbor[j];
1324
0
    if (a2 == a1)
1325
0
    {
1326
0
        *err |= 1; /*  bond for impossible atom number(s); ignored */
1327
0
        TREAT_ERR( *err, 0, "Atom has a bond to itself" );
1328
0
        goto err_exit;
1329
0
    }
1330
1331
    /* consistency check; locate the bond in the opposite atom */
1332
0
    p1 = is_in_the_list( at[a1].neighbor, (AT_NUMB) a2, at[a1].valence );
1333
0
    p2 = is_in_the_list( at[a2].neighbor, (AT_NUMB) a1, at[a2].valence );
1334
1335
0
    if (p1 && p2)
1336
0
    {
1337
0
        n1 = (int) ( p1 - at[a1].neighbor );
1338
0
        n2 = (int) ( p2 - at[a2].neighbor );
1339
0
        if ((n1 + 1 < at[a1].valence &&
1340
0
             is_in_the_list( at[a1].neighbor + n1 + 1, (AT_NUMB) a2, at[a1].valence - n1 - 1 ))
1341
0
             ||
1342
0
             (n2 + 1 < at[a2].valence &&
1343
0
             is_in_the_list( at[a2].neighbor + n2 + 1, (AT_NUMB) a1, at[a2].valence - n2 - 1 ))) /* djb-rwth: addressing LLVM warnings */
1344
0
        {
1345
0
            TREAT_ERR( *err, 0, "Multiple bonds between two atoms" );
1346
0
            *err |= 2; /*  multiple bonds between atoms */
1347
0
        }
1348
0
        else if (n1 < at[a1].valence && n2 < at[a2].valence &&
1349
0
             cBondType == at[a2].bond_type[n2] &&
1350
0
             cBondType == at[a1].bond_type[n1] &&
1351
0
             cStereoType1 == at[a1].bond_stereo[n1] &&
1352
0
             cStereoType2 == at[a2].bond_stereo[n2])
1353
0
        {
1354
            /*TREAT_ERR (*err, 0, "Duplicated bond(s) between two atoms");*/
1355
0
        }
1356
0
        else
1357
0
        {
1358
0
            TREAT_ERR( *err, 0, "Multiple bonds between two atoms" );
1359
0
            *err |= 2; /*  multiple bonds between atoms */
1360
0
        }
1361
0
    }
1362
0
    else if (( p1 || p2 ) &&
1363
0
        ( p1 || at[a1].valence < MAXVAL ) &&
1364
0
        ( p2 || at[a2].valence < MAXVAL ))
1365
0
    {
1366
0
        n1 = p1 ? (int) ( p1 - at[a1].neighbor ) : at[a1].valence++;
1367
0
        n2 = p2 ? (int) ( p2 - at[a2].neighbor ) : at[a2].valence++;
1368
        /* the bond is present in one atom only: possibly program error */
1369
0
        if ((p1 && ( cBondType != at[a1].bond_type[n1] || at[a1].bond_stereo[n1] != cStereoType1 )) ||
1370
0
             (p2 && ( cBondType != at[a2].bond_type[n2] || at[a2].bond_stereo[n2] != cStereoType2 ))) /* djb-rwth: addressing LLVM warnings */
1371
0
        {
1372
0
            TREAT_ERR( *err, 0, "Multiple bonds between two atoms" );
1373
0
            *err |= 2; /*  multiple bonds between atoms */
1374
0
        }
1375
0
        else
1376
0
        {
1377
0
            TREAT_ERR( *err, 0, "Duplicated bond(s) between two atoms" );
1378
            /* warning */
1379
0
        }
1380
0
    }
1381
0
    else if (!p1 && !p2 && at[a1].valence < MAXVAL && at[a2].valence < MAXVAL)
1382
0
    {
1383
0
        n1 = at[a1].valence++;
1384
0
        n2 = at[a2].valence++;
1385
0
        ( *nNumBonds )++;
1386
0
    }
1387
0
    else
1388
0
    {
1389
0
        char szMsg[64];
1390
0
        *err |= 4; /*  too large number of bonds. Some bonds ignored. */
1391
0
        sprintf(szMsg, "Atom '%s' has more than %d bonds",
1392
0
            at[a1].valence >= MAXVAL ? at[a1].elname : at[a2].elname, MAXVAL);
1393
0
        TREAT_ERR( *err, 0, szMsg );
1394
0
        goto err_exit;
1395
0
    }
1396
1397
    /* store the connection */
1398
1399
    /* bond type */ /* djb-rwth: buffer overruns avoided implicitly */ /* djb-rwth: ui_rr? */
1400
0
    at[a1].bond_type[n1] =
1401
0
        at[a2].bond_type[n2] = cBondType;
1402
        /* connection */
1403
0
    at[a1].neighbor[n1] = (AT_NUMB) a2;
1404
0
    at[a2].neighbor[n2] = (AT_NUMB) a1;
1405
    /* stereo */
1406
0
    at[a1].bond_stereo[n1] = cStereoType1; /*  >0: the wedge (pointed) end is at this atom */
1407
0
    at[a2].bond_stereo[n2] = cStereoType2; /*  <0: the wedge (pointed) end is at the opposite atom */
1408
1409
0
    return 0;
1410
1411
0
err_exit:
1412
1413
0
    return 1;
1414
0
}
1415
1416
1417
/****************************************************************************/
1418
int SetAtomAndBondProperties( inp_ATOM *at,
1419
                              inchi_Atom *ati,
1420
                              int a1,
1421
                              int bDoNotAddH,
1422
                              char *pStrErr,
1423
                              int *err )
1424
0
{
1425
0
    int valence, chem_valence, num_alt_bonds, j, n1;
1426
0
    int nRadical, nCharge;
1427
0
    static int el_number_H = 0;
1428
1429
0
    if (!el_number_H)
1430
0
    {
1431
0
        el_number_H = get_periodic_table_number( "H" );
1432
0
    }
1433
1434
0
    nRadical = nCharge = 0;
1435
0
    valence = at[a1].valence;
1436
0
    chem_valence = num_alt_bonds = 0;
1437
0
    for (j = 0; j < valence; j++)
1438
0
    {
1439
0
        if (at[a1].bond_type[j] <= BOND_TYPE_TRIPLE)
1440
0
        {
1441
0
            chem_valence += at[a1].bond_type[j];
1442
0
        }
1443
0
        else
1444
0
        {
1445
0
            num_alt_bonds++;
1446
0
        }
1447
0
    }
1448
0
    switch (num_alt_bonds)
1449
0
    {
1450
0
        case 0:
1451
0
            break;
1452
0
        case 2:
1453
0
            chem_valence += 3; /* -C= */
1454
0
            break;
1455
0
        case 3:
1456
0
            chem_valence += 4;  /* >C= */
1457
0
            break;
1458
0
        default:
1459
0
        {
1460
0
            char szMsg[64];
1461
0
            *err |= 8; /*  wrong number of alt. bonds */
1462
0
            sprintf(szMsg, "Atom '%s' has %d alternating bonds",
1463
0
                at[a1].elname, num_alt_bonds);
1464
0
            TREAT_ERR( *err, 0, szMsg );
1465
0
        }
1466
0
        break;
1467
0
    }
1468
0
    at[a1].chem_bonds_valence = chem_valence;
1469
1470
    /* aliased hydrogen atoms */
1471
0
    if (ERR_ELEM == ( n1 = get_periodic_table_number( at[a1].elname ) ))
1472
0
    {
1473
        /*  Case when elname contains more than 1 element: extract number of H if possible */
1474
0
        if (extract_charges_and_radicals( at[a1].elname, &nRadical, &nCharge ))
1475
0
        {
1476
0
            if ((nRadical && at[a1].radical && nRadical != at[a1].radical) ||
1477
0
                 (nCharge && at[a1].charge && nCharge != at[a1].charge)) /* djb-rwth: addressing LLVM warnings */
1478
0
            {
1479
0
                TREAT_ERR( *err, 0, "Ignored charge/radical redefinition:" );
1480
0
                TREAT_ERR( *err, 0, ati[a1].elname );
1481
0
            }
1482
0
            else
1483
0
            {
1484
0
                if (nRadical)
1485
0
                {
1486
0
                    at[a1].radical = nRadical;
1487
0
                }
1488
0
                if (nCharge)
1489
0
                {
1490
0
                    at[a1].charge = nCharge;
1491
0
                }
1492
0
            }
1493
0
        }
1494
1495
0
        at[a1].num_H = extract_H_atoms( at[a1].elname, at[a1].num_iso_H );
1496
0
        if (!at[a1].elname[0] && NUMH( at, a1 ))
1497
0
        {
1498
            /* alias contains only H. Added 2004-07-21, fixed 2004-07-22
1499
             * move the heaviest isotope to the "central atom"
1500
             * Note: this must be consistent with H-H treatment in remove_terminal_HDT()
1501
             */
1502
0
            strcpy( at[a1].elname, "H" );
1503
0
            if (NUM_ISO_H( at, a1 ))
1504
0
            {
1505
0
                for (j = NUM_H_ISOTOPES - 1; 0 <= j; j--)
1506
0
                {
1507
0
                    if (at[a1].num_iso_H[j])
1508
0
                    {
1509
0
                        at[a1].num_iso_H[j] --;
1510
0
                        at[a1].iso_atw_diff = 1 + j;
1511
0
                        break;
1512
0
                    }
1513
0
                }
1514
0
            }
1515
0
            else
1516
0
            {
1517
0
                at[a1].num_H--;
1518
0
            }
1519
0
        }
1520
1521
0
        if (ERR_ELEM == ( n1 = get_periodic_table_number( at[a1].elname ) ))
1522
0
        {
1523
0
            n1 = 0;
1524
0
        }
1525
0
        if (n1)
1526
0
        {
1527
0
            at[a1].at_type |= 1; /* "Aliased" atom: data in the element name */
1528
0
            TREAT_ERR( *err, 0, "Parsed compound atom(s):" );
1529
0
            TREAT_ERR( *err, 0, ati[a1].elname );
1530
0
        }
1531
0
    }
1532
1533
0
    at[a1].el_number = (U_CHAR) n1;
1534
0
    if (!n1)
1535
0
    {
1536
0
        *err |= 64; /*  Unrecognized aromatic bond(s) replaced with single */
1537
0
        TREAT_ERR( *err, 0, "Unknown element(s):" );
1538
0
        TREAT_ERR( *err, 0, at[a1].elname );
1539
0
    }
1540
0
    else
1541
0
    {
1542
        /* replace explicit D or T with isotopic H (added 2003-06-02) */
1543
0
        if (el_number_H == n1 && !at[a1].iso_atw_diff)
1544
0
        {
1545
0
            switch (at[a1].elname[0])
1546
0
            {
1547
0
                case 'D':
1548
0
                    at[a1].iso_atw_diff = 2;
1549
0
                    mystrncpy( at[a1].elname, "H", sizeof( at->elname ) );
1550
0
                    break;
1551
0
                case 'T':
1552
0
                    at[a1].iso_atw_diff = 3;
1553
0
                    mystrncpy( at[a1].elname, "H", sizeof( at->elname ) );
1554
0
                    break;
1555
0
                case 'H':
1556
0
                    if (1 <= ati[a1].isotopic_mass)
1557
0
                    {
1558
0
                        AT_NUM iso_atw_diff;
1559
0
                        if (ISOTOPIC_SHIFT_FLAG - ISOTOPIC_SHIFT_MAX <= ati[a1].isotopic_mass &&
1560
0
                             ISOTOPIC_SHIFT_FLAG + ISOTOPIC_SHIFT_MAX >= ati[a1].isotopic_mass)
1561
0
                        {
1562
                            /* ati[a1].isotopic_mass is isotopic iso_atw_diff + ISOTOPIC_SHIFT_FLAG */
1563
0
                            iso_atw_diff = ati[a1].isotopic_mass - ISOTOPIC_SHIFT_FLAG;
1564
0
                        }
1565
0
                        else
1566
0
                        {
1567
                            /* ati[a1].isotopic_mass is isotopic mass */
1568
0
                            int iso_atw = get_atomic_mass_from_elnum( (int) at[a1].el_number );
1569
0
                            iso_atw_diff = ati[a1].isotopic_mass - iso_atw;
1570
0
                        }
1571
0
                        if (iso_atw_diff >= 0)
1572
0
                            iso_atw_diff++;
1573
                        /* reproduce Bug04: allowed non-terminal H heavier than T */
1574
0
                        if (1 <= iso_atw_diff &&
1575
0
                            ( at[a1].valence != 1 || iso_atw_diff <= NUM_H_ISOTOPES ))
1576
0
                        {
1577
0
                            at[a1].iso_atw_diff = (S_CHAR) iso_atw_diff;
1578
0
                        }
1579
0
                    }
1580
0
            }
1581
0
        }
1582
0
        else
1583
0
        {/* isotopic shift */
1584
0
            if (ati[a1].isotopic_mass)
1585
0
            {
1586
0
                AT_NUM iso_atw_diff;
1587
0
                if (ISOTOPIC_SHIFT_FLAG - ISOTOPIC_SHIFT_MAX <= ati[a1].isotopic_mass &&
1588
0
                     ISOTOPIC_SHIFT_FLAG + ISOTOPIC_SHIFT_MAX >= ati[a1].isotopic_mass)
1589
0
                {
1590
                    /* ati[a1].isotopic_mass is isotopic iso_atw_diff + ISOTOPIC_SHIFT_FLAG */
1591
0
                    iso_atw_diff = ati[a1].isotopic_mass - ISOTOPIC_SHIFT_FLAG;
1592
0
                }
1593
0
                else
1594
0
                {
1595
                    /* ati[a1].isotopic_mass is isotopic mass */
1596
0
                    iso_atw_diff = get_atomic_mass_from_elnum( (int) at[a1].el_number );
1597
0
                    iso_atw_diff = ati[a1].isotopic_mass - iso_atw_diff;
1598
0
                }
1599
0
                if (iso_atw_diff >= 0)
1600
0
                    iso_atw_diff++;
1601
0
                at[a1].iso_atw_diff = (S_CHAR) iso_atw_diff;
1602
0
            }
1603
0
        }
1604
0
    }
1605
1606
    /* add implicit hydrogen atoms flag */
1607
0
    if (ati[a1].num_iso_H[0] == -1)
1608
0
    {
1609
0
        if (!bDoNotAddH)
1610
0
        {
1611
0
            at[a1].at_type |= 2; /* user requested to add H */
1612
0
        }
1613
0
    }
1614
0
    else
1615
0
    {
1616
0
        at[a1].num_H = ati[a1].num_iso_H[0];
1617
0
    }
1618
1619
0
    for (j = 0; j < NUM_H_ISOTOPES; j++)
1620
0
    {
1621
0
        at[a1].num_iso_H[j] = ati[a1].num_iso_H[j + 1];
1622
0
    }
1623
1624
0
    if (num_alt_bonds)
1625
0
    {
1626
        /* atom has aromatic bonds AND the chemical valence is not known */
1627
0
        int num_H = NUMH( at, a1 );
1628
0
        int chem_valence_alt = at[a1].chem_bonds_valence + num_H;
1629
0
        int bUnusualValenceArom =
1630
0
            detect_unusual_el_valence( (int) at[a1].el_number, at[a1].charge,
1631
0
                                        at[a1].radical, chem_valence_alt,
1632
0
                                        num_H, at[a1].valence );
1633
0
        int bUnusualValenceNoArom =
1634
0
            detect_unusual_el_valence( (int) at[a1].el_number, at[a1].charge,
1635
0
                                        at[a1].radical, chem_valence_alt - 1,
1636
0
                                        num_H, at[a1].valence );
1637
0
        if (bUnusualValenceArom && !bUnusualValenceNoArom && 0 == nBondsValToMetal( at, a1 ))
1638
0
        {
1639
            /* typically NH in 5-member aromatic ring */
1640
0
            at[a1].chem_bonds_valence--;
1641
0
        }
1642
0
    }
1643
1644
0
    return 0;
1645
0
}
1646
1647
1648
/****************************************************************************/
1649
int InpAtom0DToInchiAtom( inp_ATOM *at,
1650
                          int num_inp_atoms,
1651
                          AT_NUM *num_atoms,
1652
                          inchi_Atom **atom,
1653
                          AT_NUM *num_stereo0D,
1654
                          inchi_Stereo0D **stereo0D )
1655
353
{
1656
353
    int num_stereo_centers, num_stereo_bonds, num_inp_stereo0D, i, m, m1, m2, n, ret = 0;
1657
1658
    /* count stereobonds, allenes. cumulenes. and stereoatoms */
1659
353
    num_stereo_centers = num_stereo_bonds = ret = 0;
1660
1661
353
    *atom = NULL;
1662
353
    *num_atoms = 0;
1663
353
    *stereo0D = NULL;
1664
353
    *num_stereo0D = 0;
1665
1666
38.9k
    for (i = 0; i < num_inp_atoms; i++)
1667
38.6k
    {
1668
38.6k
        if (at[i].p_parity)
1669
63
        {
1670
            /* stereocenter */
1671
63
            num_stereo_centers++;
1672
63
        }
1673
38.5k
        else
1674
38.5k
        {
1675
38.5k
            for (m = 0; m < MAX_NUM_STEREO_BONDS && at[i].sb_parity[m]; m++)
1676
0
            {
1677
0
                ;
1678
0
            }
1679
38.5k
            num_stereo_bonds += m;
1680
38.5k
        }
1681
38.6k
    }
1682
1683
353
    num_stereo_bonds /= 2;
1684
353
    num_inp_stereo0D = num_stereo_bonds + num_stereo_centers;
1685
1686
353
    if (num_inp_atoms > 0)
1687
353
    {
1688
353
        *atom = (inchi_Atom *) inchi_calloc( num_inp_atoms, sizeof( ( *atom )[0] ) );
1689
353
    }
1690
1691
353
    *num_atoms = num_inp_atoms;
1692
1693
353
    if (num_inp_stereo0D > 0)
1694
34
    {
1695
34
        *stereo0D = (inchi_Stereo0D *) inchi_calloc( num_inp_stereo0D, sizeof( ( *stereo0D )[0] ) );
1696
34
    }
1697
1698
353
    if ((num_inp_atoms && !( *atom )) || (num_inp_stereo0D > 0 && !( *stereo0D ))) /* djb-rwth: addressing LLVM warnings */
1699
0
    {
1700
        /* allocation failed */
1701
0
        ret = -1;
1702
0
        goto exit_function;
1703
0
    }
1704
1705
    /* copy atom properties */
1706
38.9k
    for (i = 0; i < num_inp_atoms; i++)
1707
38.6k
    {
1708
38.6k
        ( *atom )[i].num_bonds = at[i].valence;
1709
44.3k
        for (m = 0; m < at[i].valence; m++)
1710
5.69k
        {
1711
5.69k
            ( *atom )[i].bond_type[m] = at[i].bond_type[m];
1712
5.69k
            ( *atom )[i].neighbor[m] = at[i].neighbor[m];
1713
5.69k
        }
1714
38.6k
        ( *atom )[i].charge = at[i].charge;
1715
#if USE_BCF
1716
        memcpy_s( ( *atom )[i].elname, ATOM_EL_LEN, at[i].elname, ATOM_EL_LEN ); /* djb-rwth: function replaced with its safe C11 variant */
1717
#else
1718
38.6k
        memcpy( ( *atom )[i].elname, at[i].elname, ATOM_EL_LEN );
1719
38.6k
#endif
1720
38.6k
        if (at[i].iso_atw_diff)
1721
17
        {
1722
17
            ( *atom )[i].isotopic_mass = ISOTOPIC_SHIFT_FLAG + ( at[i].iso_atw_diff > 0 ? at[i].iso_atw_diff - 1 : at[i].iso_atw_diff );
1723
17
        }
1724
38.6k
        ( *atom )[i].num_iso_H[0] = at[i].num_H;
1725
154k
        for (m = 0; m < NUM_H_ISOTOPES; m++)
1726
115k
        {
1727
115k
            ( *atom )[i].num_iso_H[m + 1] = at[i].num_iso_H[m];
1728
115k
        }
1729
38.6k
        ( *atom )[i].radical = at[i].radical;
1730
38.6k
    }
1731
1732
    /* stereo */
1733
38.9k
    for (i = n = 0; i < num_inp_atoms; i++)
1734
38.6k
    {
1735
38.6k
        if (at[i].p_parity)
1736
63
        {
1737
63
            if (n < num_inp_stereo0D)
1738
63
            {
1739
63
                ( *stereo0D )[n].central_atom = i;
1740
63
                ( *stereo0D )[n].parity = at[i].p_parity;
1741
63
                ( *stereo0D )[n].type = INCHI_StereoType_Tetrahedral;
1742
315
                for (m = 0; m < MAX_NUM_STEREO_ATOM_NEIGH; m++)
1743
252
                {
1744
252
                    ( *stereo0D )[n].neighbor[m] = at[i].p_orig_at_num[m] - 1;
1745
252
                }
1746
63
                n++;
1747
63
            }
1748
0
            else
1749
0
            {
1750
0
                ret |= 1;
1751
0
                break;
1752
0
            }
1753
63
        }
1754
38.5k
        else
1755
38.5k
        {
1756
38.5k
            for (m1 = 0; m1 < MAX_NUM_STEREO_BONDS && at[i].sb_parity[m1]; m1++)
1757
0
            {
1758
                /* find the opposite atom at the other end of double bond, allene, or cumulene */
1759
0
                int chain[12], len = 0, nxt_neigh, nxt, cur;
1760
0
                cur = chain[len++] = i;
1761
0
                nxt_neigh = at[cur].sb_ord[m1];
1762
1763
0
                do
1764
0
                {
1765
                    /* add next atom */
1766
0
                    chain[len++] = nxt = at[cur].neighbor[nxt_neigh];
1767
0
                    nxt_neigh = ( at[nxt].neighbor[0] == cur );
1768
0
                    cur = nxt;
1769
                    /* find nxt_neigh */
1770
0
                }
1771
0
                while (!at[cur].sb_parity[0] &&
1772
0
                       len < 12 &&
1773
0
                       at[cur].valence == 2);
1774
1775
0
                if (at[cur].sb_parity[0] && len <= 4 && i < cur /* count bonds only one time */)
1776
0
                {
1777
                    /* double bond, cumulene, or allene has been found */
1778
0
                    for (m2 = 0; m2 < MAX_NUM_STEREO_BONDS && at[cur].sb_parity[m2]; m2++)
1779
0
                    {
1780
0
                        if (chain[len - 2] == at[cur].neighbor[(int) at[cur].sb_ord[m2]])
1781
0
                        {
1782
0
                            if (n < num_inp_stereo0D)
1783
0
                            {
1784
0
                                int parity1 = at[i].sb_parity[m1];
1785
0
                                int parity2 = at[cur].sb_parity[m2];
1786
0
                                int parity;
1787
0
                                if (( INCHI_PARITY_ODD == parity1 || INCHI_PARITY_EVEN == parity1 ) &&
1788
0
                                    ( INCHI_PARITY_ODD == parity2 || INCHI_PARITY_EVEN == parity2 ))
1789
0
                                {
1790
                                    /* well-defined parity */
1791
0
                                    parity = ( parity1 == parity2 ) ? INCHI_PARITY_EVEN : INCHI_PARITY_ODD;
1792
0
                                }
1793
0
                                else
1794
0
                                {
1795
0
                                    parity = inchi_max( parity1, parity2 );
1796
0
                                }
1797
0
                                ( *stereo0D )[n].central_atom = ( len == 3 ) ? chain[1] : NO_ATOM;
1798
0
                                ( *stereo0D )[n].parity = parity;
1799
0
                                ( *stereo0D )[n].type = len == 3 ? INCHI_StereoType_Allene : INCHI_StereoType_DoubleBond;
1800
0
                                ( *stereo0D )[n].neighbor[0] = at[i].sn_orig_at_num[m1] - 1;
1801
0
                                ( *stereo0D )[n].neighbor[1] = i;
1802
0
                                ( *stereo0D )[n].neighbor[2] = cur;
1803
0
                                ( *stereo0D )[n].neighbor[3] = at[cur].sn_orig_at_num[m2] - 1;
1804
0
                                n++;
1805
0
                            }
1806
0
                            else
1807
0
                            {
1808
0
                                ret |= 1;
1809
0
                            }
1810
0
                            break;
1811
0
                        }
1812
0
                    }
1813
0
                }
1814
0
            }
1815
38.5k
        }
1816
38.6k
    }
1817
1818
353
    *num_stereo0D = n;
1819
1820
353
exit_function:
1821
353
    if (ret < 0)
1822
0
    {
1823
0
        if (*atom)
1824
0
        {
1825
0
            inchi_free( *atom );
1826
0
        }
1827
0
        if (*stereo0D)
1828
0
        {
1829
0
            inchi_free( *stereo0D );
1830
0
        }
1831
0
        *atom = NULL;
1832
0
        *stereo0D = NULL;
1833
0
        *num_atoms = 0;
1834
0
        *num_stereo0D = 0;
1835
0
    }
1836
1837
353
    return ret;
1838
353
}
1839
1840
1841
/****************************************************************************/
1842
int ExtractOneStructure( STRUCT_DATA *sd,
1843
                         INPUT_PARMS *ip,
1844
                         char *szTitle,
1845
                         inchi_InputEx *inp,
1846
                         INCHI_IOSTREAM *log_file,
1847
                         INCHI_IOSTREAM *out_file,
1848
                         INCHI_IOSTREAM *prb_file,
1849
                         ORIG_ATOM_DATA *orig_inp_data,
1850
                         long *num_inp )
1851
0
{
1852
0
    int         *err = &sd->nStructReadError;
1853
0
    char        *pStrErr = sd->pStrErrStruct;
1854
0
    inp_ATOM    *at = NULL;
1855
0
    MOL_COORD   *szCoord = NULL;
1856
0
    inchi_Atom  *ati = NULL;
1857
0
    int       nNumAtoms = 0;
1858
0
    int       a1, j, valence, nDim, nNumBonds, nRet = 0, max_num_at;
1859
1860
    /* vABParityUnknown holds actual value of an internal constant signifying       */
1861
    /* unknown parity: either the same as for undefined parity (default==standard)  */
1862
    /*  or a specific one (non-std; requested by SLUUD switch).                     */
1863
0
    int vABParityUnknown = AB_PARITY_UNDF;
1864
0
    if (0 != ( ip->nMode & REQ_MODE_DIFF_UU_STEREO ))
1865
0
    {
1866
        /* Make labels for unknown and undefined stereo different */
1867
0
        vABParityUnknown = AB_PARITY_UNKN;
1868
0
    }
1869
1870
    /********************************************************
1871
     *
1872
     *   Extract the structure
1873
     *
1874
     ********************************************************/
1875
1876
0
    FreeOrigAtData( orig_inp_data );
1877
0
    nDim = 0;
1878
0
    nNumBonds = 0;
1879
1880
0
    if (!inp || ( nNumAtoms = inp->num_atoms ) <= 0 || !( ati = inp->atom ))
1881
0
    {
1882
0
        TREAT_ERR( *err, 0, "Empty structure" );
1883
0
        *err = 98;
1884
0
        goto err_exit;
1885
0
    }
1886
1887
0
    max_num_at = ip->bLargeMolecules ? MAX_ATOMS : NORMALLY_ALLOWED_INP_MAX_ATOMS;
1888
0
    if (nNumAtoms >= max_num_at)
1889
0
    {
1890
0
        TREAT_ERR( *err, 0, "Too many atoms [did you forget 'LargeMolecules' switch?]" );
1891
0
        *err = 70;
1892
0
        orig_inp_data->num_inp_atoms = -1;
1893
0
        goto err_exit;
1894
0
    }
1895
1896
0
    at = (inp_ATOM  *) inchi_calloc( nNumAtoms, sizeof( at[0] ) );
1897
0
    szCoord = (MOL_COORD *) inchi_calloc( inchi_max( nNumAtoms, 1 ), sizeof( MOL_COORD ) );
1898
1899
0
    if (!at || !szCoord)
1900
0
    {
1901
0
        TREAT_ERR( *err, 0, "Out of RAM" );
1902
0
        *err = -1;
1903
0
        goto err_exit;
1904
0
    }
1905
1906
    /********************************************************
1907
     *
1908
     *   Extract typical for Molfile structural data
1909
     *
1910
     ********************************************************/
1911
    /* extract atoms and bonds */
1912
0
    for (a1 = 0; a1 < nNumAtoms; a1++)
1913
0
    {
1914
        /* extract atoms */
1915
0
        SetAtomProperties( at, szCoord, ati, a1, &nDim, pStrErr, err );
1916
1917
0
        if (*err)
1918
0
        {
1919
0
            goto err_exit;
1920
0
        }
1921
1922
        /* extract connections */
1923
0
        valence = ati[a1].num_bonds;
1924
0
        for (j = 0; j < valence; j++)
1925
0
        {
1926
0
            SetBondProperties( at, ati, a1, j, nNumAtoms, &nNumBonds, pStrErr, err );
1927
0
        }
1928
1929
0
        if (*err)
1930
0
        {
1931
0
            goto err_exit;
1932
0
        }
1933
0
    }
1934
1935
0
    orig_inp_data->num_inp_atoms = nNumAtoms;
1936
0
    orig_inp_data->num_inp_bonds = nNumBonds;
1937
0
    orig_inp_data->num_dimensions = nDim;
1938
1939
    /* extract elements, chemical valences, implicit H, isotopic shifts */
1940
0
    for (a1 = 0; a1 < nNumAtoms; a1++)
1941
0
    {
1942
        /* set temp flags in at[a1].at_type */
1943
        /* (1: data in atom name; 2: request to add H) */
1944
0
        SetAtomAndBondProperties( at,
1945
0
                                  ati,
1946
0
                                  a1,
1947
0
                                  ip->bDoNotAddH,
1948
0
                                  pStrErr,
1949
0
                                  err );
1950
0
        if (*err)
1951
0
        {
1952
0
            goto err_exit;
1953
0
        }
1954
0
    }
1955
1956
    /* clear temp flags in at[].at_type; add implicit H */
1957
0
    SetNumImplicitH( at, nNumAtoms );
1958
1959
0
    if (*err)
1960
0
    {
1961
0
        goto err_exit;
1962
0
    }
1963
1964
    /********************************************************
1965
     *
1966
     *   Extract the 0D parities (typical for CML)
1967
     *
1968
     ********************************************************/
1969
0
    Extract0DParities( at,
1970
0
                       nNumAtoms,
1971
0
                       inp->stereo0D,
1972
0
                       inp->num_stereo0D,
1973
0
                       pStrErr,
1974
0
                       err,
1975
0
                       vABParityUnknown );
1976
1977
0
    if (*err)
1978
0
    {
1979
0
        goto err_exit;
1980
0
    }
1981
1982
0
    orig_inp_data->at = at;
1983
0
    at = NULL;
1984
0
    orig_inp_data->num_dimensions = nDim;
1985
0
    orig_inp_data->num_inp_atoms = nNumAtoms;
1986
0
    orig_inp_data->num_inp_bonds = nNumBonds;
1987
0
    orig_inp_data->szCoord = szCoord;
1988
0
    szCoord = NULL;
1989
1990
    /* chiral flag */
1991
1992
    /* *****************************************************************************
1993
     * Chiral flags are set in:
1994
     * - ReadTheStructure() inchi-1, wInChI
1995
     * - e_IchiMain.c -- main()               -- C example of calling InChI dll
1996
     * - inchi_dll.c  ExtractOneStructure -- InChI dll code (here)
1997
     *******************************************************************************/
1998
1999
0
    if (( ip->nMode & REQ_MODE_CHIR_FLG_STEREO ) && ( ip->nMode & REQ_MODE_STEREO ))
2000
0
    {
2001
0
        if (ip->bChiralFlag & FLAG_SET_INP_AT_CHIRAL)
2002
0
        {
2003
            /* absolute stereo */
2004
0
            ip->nMode &= ~( REQ_MODE_RELATIVE_STEREO | REQ_MODE_RACEMIC_STEREO );
2005
0
            sd->bChiralFlag &= ~FLAG_INP_AT_NONCHIRAL;
2006
0
            sd->bChiralFlag |= FLAG_INP_AT_CHIRAL; /* write AuxInfo as chiral */
2007
0
        }
2008
0
        else
2009
        /*if ( ip->bChiralFlag & FLAG_SET_INP_AT_NONCHIRAL )*/
2010
0
        {
2011
            /* relative stereo */
2012
0
            ip->nMode &= ~( REQ_MODE_RACEMIC_STEREO );
2013
0
            ip->nMode |= REQ_MODE_RELATIVE_STEREO;
2014
0
            sd->bChiralFlag &= ~FLAG_INP_AT_CHIRAL;
2015
0
            sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL; /* write AuxInfo as non-chiral */
2016
0
        }
2017
0
    }
2018
0
    else if (ip->bChiralFlag & FLAG_SET_INP_AT_CHIRAL)
2019
0
    {
2020
0
        sd->bChiralFlag &= ~FLAG_INP_AT_NONCHIRAL;
2021
0
        sd->bChiralFlag |= FLAG_INP_AT_CHIRAL; /* write AuxInfo as chiral */
2022
0
    }
2023
0
    else if (ip->bChiralFlag & FLAG_SET_INP_AT_NONCHIRAL)
2024
0
    {
2025
0
        sd->bChiralFlag &= ~FLAG_INP_AT_CHIRAL;
2026
0
        sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL; /* write AuxInfo as non-chiral */
2027
0
    }
2028
2029
    /* v. 1.05 extensions  */
2030
0
    {
2031
0
        int res = SetExtOrigAtDataByInChIExtInput( &orig_inp_data->polymer,
2032
0
                                                   &orig_inp_data->v3000,
2033
0
                                                   inp->polymer,
2034
0
                                                   inp->v3000,
2035
0
                                                   orig_inp_data->num_inp_atoms );
2036
0
        if (res)
2037
0
        {
2038
0
            TREAT_ERR( res, 0, "General error on treating polymers" );
2039
0
            *err = -1;
2040
0
            goto err_exit;
2041
0
        }
2042
0
    }
2043
0
    *num_inp += 1;
2044
2045
0
err_exit:
2046
2047
0
    if (at)
2048
0
    {   /* if not moved to orig_inp_data/then nullified */
2049
0
        inchi_free( at );
2050
0
    }
2051
0
    if (szCoord)
2052
0
    {
2053
0
        inchi_free( szCoord );
2054
0
    }
2055
2056
0
    nRet = TreatErrorsInReadTheStructure( sd, ip, LOG_MASK_NO_WARN, NULL,
2057
0
                                          log_file, out_file, prb_file,
2058
0
                                          orig_inp_data, num_inp );
2059
2060
0
    return nRet;
2061
0
}
2062
2063
2064
/****************************************************************************/
2065
int INCHI_DECL GetStringLength( char *p )
2066
0
{
2067
0
    if (p)
2068
0
    {
2069
0
        return (int) strlen( p );
2070
0
    }
2071
0
    else
2072
0
    {
2073
0
        return 0;
2074
0
    }
2075
0
}
2076
2077
8.50k
#define MAX_MSG_LEN 512
2078
2079
2080
/****************************************************************************
2081
 GetINCHIfromINCHI does same as -InChI2InChI option: converts InChI into
2082
 InChI for validation purposes
2083
 It may also be used to filter out specific layers. For instance,
2084
 /Snon would remove stereochemical layer
2085
 Omitting /FixedH and/or /RecMet would remove Fixed-H or Reconnected layers
2086
 To keep all InChI layers use options string "/FixedH /RecMet";
2087
 option /InChI2InChI is not needed
2088
 inchi_InputINCHI is created by the user;
2089
 strings in inchi_Output are allocated and deallocated by InChI
2090
 inchi_Output does not need to be initilized out to zeroes;
2091
 see FreeINCHI() on how to deallocate it
2092
****************************************************************************/
2093
int INCHI_DECL GetINCHIfromINCHI( inchi_InputINCHI *inpInChI,
2094
                                  inchi_Output *out )
2095
2.20k
{
2096
2.20k
    STRUCT_DATA struct_data;
2097
2.20k
    STRUCT_DATA *sd = &struct_data;
2098
2099
2.20k
    static char szMainOption[] = " ?InChI2InChI";
2100
2101
2.20k
    INCHI_CLOCK ic;
2102
2.20k
    CANON_GLOBALS CG;
2103
2104
2.20k
    int i;
2105
2.20k
    char      szSdfDataValue[MAX_SDF_VALUE + 1];
2106
2.20k
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
2107
2108
2.20k
    INPUT_PARMS inp_parms;
2109
2.20k
    INPUT_PARMS *ip = &inp_parms;
2110
2111
2.20k
    int             bReleaseVersion = bRELEASE_VERSION;
2112
2.20k
    int   nRet = 0, nRet1;
2113
2114
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2115
    int  num_repeat = REPEAT_ALL;
2116
#endif
2117
2118
2.20k
    const char *argv[INCHI_MAX_NUM_ARG + 1];
2119
2.20k
    int   argc;
2120
2.20k
    char *szOptions = NULL;
2121
2122
2.20k
    INCHI_IOSTREAM inchi_file[3], *out_file = inchi_file, *log_file = inchi_file + 1, *input_file = inchi_file + 2;
2123
2124
#if( TRACE_MEMORY_LEAKS == 1 )
2125
    _CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF );
2126
/* for execution outside the VC++ debugger uncomment one of the following two */
2127
2128
#ifdef MY_REPORT_FILE
2129
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
2130
    _CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
2131
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
2132
    _CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
2133
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
2134
    _CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
2135
#else
2136
    _CrtSetReportMode( _CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG );
2137
#endif
2138
2139
    /* turn on floating point exceptions */
2140
#if ( !defined(__STDC__) || __STDC__ != 1 )
2141
    {
2142
        /* Get the default control word. */
2143
        int cw = _controlfp( 0, 0 );
2144
2145
        /* Set the exception masks OFF, turn exceptions on. */
2146
        /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
2147
        cw &= ~( EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL );
2148
2149
        /* Set the control word. */
2150
        _controlfp( cw, MCW_EM );
2151
    }
2152
#endif
2153
#endif
2154
2155
2.20k
    memset( out, 0, sizeof( *out ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2156
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2157
repeat:
2158
    FreeINCHI( out );
2159
    inchi_ios_close( out_file );
2160
    inchi_ios_close( log_file );
2161
    inchi_ios_reset( input_file );  /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2162
#endif
2163
2164
    /* Initialize internal for this function I/O streams as string buffers */
2165
2.20k
    inchi_ios_init( input_file, INCHI_IOS_TYPE_STRING, NULL );
2166
2.20k
    inchi_ios_init( out_file, INCHI_IOS_TYPE_STRING, NULL );
2167
2.20k
    inchi_ios_init( log_file, INCHI_IOS_TYPE_STRING, NULL );
2168
2169
2.20k
    sd->bUserQuit = 0;
2170
2171
    /* clear original input structure */
2172
    /* memset( inchi_file, 0, sizeof(inchi_file) ); */
2173
2.20k
    memset( sd, 0, sizeof( *sd ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2174
2.20k
    memset( ip, 0, sizeof( *ip ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2175
2.20k
    memset( szSdfDataValue, 0, sizeof( szSdfDataValue ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2176
2177
2.20k
    memset( &ic, 0, sizeof( ic ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2178
2.20k
    memset( &CG, 0, sizeof( CG ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2179
2180
2.20k
    szMainOption[1] = INCHI_OPTION_PREFX;
2181
2182
2.20k
    if (!inpInChI)
2183
0
    {
2184
0
        nRet = _IS_ERROR;
2185
0
        goto exit_function;
2186
0
    }
2187
2188
    /* options */
2189
2.20k
    if (inpInChI)
2190
2.20k
    {
2191
2.20k
        int opt_len = (int) ( ( inpInChI->szOptions ? strlen( inpInChI->szOptions ) : 0 ) + sizeof( szMainOption ) + 1 );
2192
2.20k
        szOptions = (char*) inchi_calloc( (long long)opt_len + 1, sizeof( szOptions[0] ) ); /* djb-rwth: cast operator added */
2193
2.20k
        if (szOptions)
2194
2.20k
        {
2195
2.20k
            if (inpInChI->szOptions)
2196
0
            {
2197
0
                strcpy( szOptions, inpInChI->szOptions );
2198
0
            }
2199
2.20k
            strcat( szOptions, szMainOption );
2200
2.20k
            argc = parse_options_string( szOptions, argv, INCHI_MAX_NUM_ARG );
2201
2.20k
        }
2202
0
        else
2203
0
        {
2204
0
            nRet = _IS_FATAL;
2205
0
            goto translate_RetVal; /* emergency exit */
2206
0
        }
2207
2.20k
    }
2208
0
    else
2209
0
    {
2210
0
        argc = 1;
2211
0
        argv[0] = "";
2212
0
        argv[1] = NULL;
2213
0
    }
2214
2215
2.20k
    if ((argc == 1
2216
2.20k
#ifdef TARGET_API_LIB
2217
2.20k
        && ( !inpInChI || !inpInChI->szInChI ))
2218
2.20k
#endif
2219
2220
2.20k
        || (argc == 2 && ( argv[1][0] == INCHI_OPTION_PREFX ) &&
2221
2.20k
        ( !strcmp( argv[1] + 1, "?" ) || !inchi_stricmp( argv[1] + 1, "help" ) ))) /* djb-rwth: addressing LLVM warnings */
2222
0
    {
2223
0
        HelpCommandLineParms( log_file );
2224
0
        out->szLog = log_file->s.pStr;
2225
0
        memset( log_file, 0, sizeof( *log_file ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2226
0
        nRet = _IS_EOF;
2227
0
        inchi_free(szOptions); /* djb-rwth: avoiding memory leak */
2228
0
        goto translate_RetVal;
2229
0
    }
2230
2231
2.20k
    nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue,
2232
2.20k
                                &ulDisplTime, bReleaseVersion, log_file );
2233
2234
2.20k
    if (szOptions)
2235
2.20k
    {
2236
        /* argv pointed to strings in szOptions */
2237
2.20k
        inchi_free( szOptions );
2238
2.20k
        szOptions = NULL;
2239
2.20k
    }
2240
    /* INChI DLL specific */
2241
2.20k
    ip->bNoStructLabels = 1;
2242
2243
2.20k
    if (0 > nRet1)
2244
0
    {
2245
0
        goto exit_function;
2246
0
    }
2247
2248
2.20k
    if (ip->bNoStructLabels)
2249
2.20k
    {
2250
2.20k
        ip->pSdfLabel = NULL;
2251
2.20k
        ip->pSdfValue = NULL;
2252
2.20k
    }
2253
0
    else if (ip->nInputType == INPUT_INCHI_XML ||
2254
0
            ip->nInputType == INPUT_INCHI_PLAIN ||
2255
0
            ip->nInputType == INPUT_CMLFILE ||
2256
0
            ip->nInputType == INPUT_INCHI)
2257
0
    {
2258
        /* the input may contain both the header and the label of the structure */
2259
0
        if (!ip->pSdfLabel)
2260
0
        {
2261
0
            ip->pSdfLabel = ip->szSdfDataHeader;
2262
0
        }
2263
0
        if (!ip->pSdfValue)
2264
0
        {
2265
0
            ip->pSdfValue = szSdfDataValue;
2266
0
        }
2267
0
    }
2268
2269
2.20k
    if (ip->nInputType && ip->nInputType != INPUT_INCHI)
2270
0
    {
2271
0
        inchi_ios_eprint( log_file, "Input type set to INPUT_INCHI\n" );
2272
0
        ip->nInputType = INPUT_INCHI;
2273
0
    }
2274
2275
2.20k
    if (!inpInChI->szInChI)
2276
0
    {
2277
0
        nRet = _IS_ERROR;
2278
0
        goto exit_function;
2279
0
    }
2280
2.20k
    else
2281
2.20k
    {
2282
2.20k
        const int strict = 0;
2283
2.20k
        nRet = CheckINCHI( inpInChI->szInChI, strict );
2284
2.20k
        if (nRet != INCHI_VALID_STANDARD     &&
2285
2.20k
            nRet != INCHI_VALID_NON_STANDARD &&
2286
2.20k
            nRet != INCHI_VALID_BETA)
2287
77
        {
2288
77
            nRet = _IS_ERROR;
2289
77
            goto exit_function;
2290
77
        }
2291
2.20k
    }
2292
2293
2294
2.12k
    PrintInputParms( log_file, ip );
2295
2296
    /********************************/
2297
    /* InChI -> InChI               */
2298
    /********************************/
2299
2300
    /* input_file simulation */
2301
2.12k
    input_file->s.pStr = inpInChI->szInChI;
2302
2.12k
    input_file->s.nUsedLength = (int) strlen( input_file->s.pStr ) + 1;
2303
2.12k
    input_file->s.nAllocatedLength = input_file->s.nUsedLength;
2304
2.12k
    input_file->s.nPtr = 0;
2305
2306
    /* buffer for the message */
2307
2.12k
    out->szMessage = (char *) inchi_calloc( MAX_MSG_LEN, sizeof( out->szMessage[0] ) );
2308
2.12k
    if (!out->szMessage)
2309
0
    {
2310
0
        inchi_ios_eprint( log_file, "Cannot allocate output message buffer.\n" );
2311
0
        nRet = -1;
2312
0
    }
2313
2.12k
    else
2314
2.12k
    {
2315
2.12k
        nRet = ReadWriteInChI( &ic, &CG, input_file, out_file, log_file,
2316
2.12k
                                ip, sd,
2317
2.12k
                                NULL, 0, NULL,
2318
2.12k
                                NULL, NULL,
2319
2.12k
                                out->szMessage, MAX_MSG_LEN,
2320
2.12k
                                NULL /*out->WarningFlags*/ );
2321
2.12k
    }
2322
2323
2.12k
    if (nRet >= 0 && out_file->s.pStr)
2324
1.51k
    {
2325
        /* success */
2326
1.51k
        char *p;
2327
1.51k
        out->szInChI = out_file->s.pStr;
2328
1.51k
        out->szAuxInfo = NULL;
2329
2330
1.51k
        for (p = strchr( out->szInChI, '\n' ); p; p = strchr( p + 1, '\n' ))
2331
1.51k
        {
2332
1.51k
            if (!memcmp( p, "\nAuxInfo", 8 ))
2333
0
            {
2334
0
                *p = '\0';            /* remove LF after INChI */
2335
0
                out->szAuxInfo = p + 1; /* save pointer to AuxInfo */
2336
0
            }
2337
1.51k
            else if (out->szAuxInfo || !p[1])
2338
1.51k
            {
2339
                /* remove LF after aux info or from the last char */
2340
1.51k
                *p = '\0';
2341
1.51k
                break;
2342
1.51k
            }
2343
1.51k
        }
2344
1.51k
        out_file->s.pStr = NULL;
2345
1.51k
    }
2346
2347
    /*
2348
    out->szLog = log_file->pStr;
2349
    log_file->pStr   = NULL;
2350
    */
2351
2352
2.20k
exit_function:;
2353
2354
11.0k
    for (i = 0; i < MAX_NUM_PATHS; i++)
2355
8.81k
    {
2356
8.81k
        if (ip->path[i])
2357
0
        {
2358
0
            inchi_free( (char*) ip->path[i] ); /*  cast deliberately discards 'const' qualifier */
2359
0
            ip->path[i] = NULL;
2360
0
        }
2361
8.81k
    }
2362
2363
2.20k
    SetBitFree( &CG );
2364
2365
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2366
    if (num_repeat-- > 0)
2367
    {
2368
        goto repeat;
2369
    }
2370
#endif
2371
2372
2.20k
#ifdef TARGET_API_LIB
2373
    /* output */
2374
2375
2.20k
        if (log_file->s.pStr && log_file->s.nUsedLength > 0)
2376
2.12k
        {
2377
7.28k
            while (log_file->s.nUsedLength && '\n' == log_file->s.pStr[log_file->s.nUsedLength - 1])
2378
5.15k
            {
2379
5.15k
                log_file->s.pStr[--log_file->s.nUsedLength] = '\0'; /* remove last LF */
2380
5.15k
            }
2381
2.12k
            if (out)
2382
2.12k
            {
2383
2.12k
                out->szLog = log_file->s.pStr;
2384
2.12k
                log_file->s.pStr = NULL;
2385
2.12k
            }
2386
2.12k
        }
2387
2388
2.20k
#endif
2389
2390
2.20k
translate_RetVal:
2391
2392
    /* close internal output streams */
2393
2.20k
    inchi_ios_close( out_file );
2394
2.20k
    inchi_ios_close( log_file );
2395
2.20k
    inchi_ios_reset( input_file );  /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2396
2397
2.20k
    switch (nRet)
2398
2.20k
    {
2399
8
        case -3: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2400
499
        case -2: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2401
0
        case -1: nRet = inchi_Ret_FATAL; break; /* Severe error: no Structure has been created (typically; break; memory allocation failed) */
2402
1.69k
        default:
2403
            /*
2404
            if ( !outStruct->atom || !outStruct->num_atoms )
2405
            {
2406
                nRet = inchi_Ret_EOF;
2407
            }
2408
            else
2409
            {
2410
                int m,n,t=0;
2411
                for ( m=0; m < 2; m ++ )
2412
                {
2413
                    for ( n=0; n < 2; n ++ )
2414
                    {
2415
                        if ( outStruct->WarningFlags[m][n] ) {
2416
                            t ++;
2417
                        }
2418
                    }
2419
                }
2420
                nRet = t? inchi_Ret_WARNING : inchi_Ret_OKAY;
2421
            }
2422
            */
2423
1.69k
            break;
2424
2.20k
    }
2425
2426
2.20k
    return nRet;
2427
2.20k
}
2428
2429
2430
/****************************************************************************
2431
2432
    GetStructFromStdINCHI
2433
2434
****************************************************************************/
2435
EXPIMP_TEMPLATE INCHI_API
2436
int INCHI_DECL GetStructFromStdINCHI( inchi_InputINCHI *inpInChI,
2437
                                      inchi_OutputStruct *outStruct )
2438
0
{
2439
0
    if (( inpInChI ) &&
2440
0
        ( inpInChI->szInChI ) &&
2441
0
        ( strlen( inpInChI->szInChI ) >= LEN_INCHI_STRING_PREFIX + 3 ) &&
2442
0
        ( inpInChI->szInChI[LEN_INCHI_STRING_PREFIX + 1] == 'S' ))
2443
0
    {
2444
         /* brief check indicated valid std input (more checks in GetStructFromINCHI) */
2445
0
        return GetStructFromINCHI( inpInChI, outStruct );
2446
0
    }
2447
0
    else
2448
0
    {
2449
        /* non-std or just invalid input */
2450
0
        return inchi_Ret_ERROR;
2451
0
    }
2452
0
}
2453
2454
2455
/****************************************************************************
2456
2457
    GetStructFromINCHIEx
2458
****************************************************************************/
2459
EXPIMP_TEMPLATE INCHI_API
2460
int INCHI_DECL GetStructFromINCHIEx( inchi_InputINCHI *inpInChI,
2461
                                     inchi_OutputStructEx *outStruct )
2462
2.20k
{
2463
2.20k
    INCHI_CLOCK ic;
2464
2.20k
    CANON_GLOBALS CG;
2465
2.20k
    STRUCT_DATA struct_data;
2466
2.20k
    STRUCT_DATA *sd = &struct_data;
2467
2.20k
    INPUT_PARMS inp_parms;
2468
2.20k
    INPUT_PARMS *ip = &inp_parms;
2469
2.20k
    INCHI_IOSTREAM inchi_file[3];
2470
2.20k
    INCHI_IOSTREAM *out_file = inchi_file, *log_file = inchi_file + 1, *input_file = inchi_file + 2;
2471
2.20k
    int    i, nRet = 0, nRet1;
2472
    /* djb-rwth: removing redundant variables/code */
2473
2.20k
    int bReleaseVersion = bRELEASE_VERSION; /* djb-rwth: ignoring LLVM warning: variable used in function call */
2474
2.20k
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
2475
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2476
    int  num_repeat = REPEAT_ALL;
2477
#endif
2478
2.20k
    static char szMainOption[] = " ?InChI2Struct";
2479
2.20k
    char szSdfDataValue[MAX_SDF_VALUE + 1];
2480
2.20k
    const char *argv[INCHI_MAX_NUM_ARG + 1];
2481
2.20k
    int   argc;
2482
2.20k
    char *szOptions = NULL;
2483
    /* conversion result */
2484
2.20k
    inp_ATOM *at = NULL;
2485
2.20k
    int num_at = 0;
2486
2.20k
    OAD_Polymer *polymer = NULL;
2487
2.20k
    OAD_V3000    *v3000 = NULL;
2488
2489
#if( TRACE_MEMORY_LEAKS == 1 )
2490
    _CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF );
2491
2492
/* for execution outside the VC++ debugger uncomment one of the following two */
2493
#ifdef MY_REPORT_FILE
2494
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
2495
    _CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
2496
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
2497
    _CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
2498
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
2499
    _CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
2500
#else
2501
    _CrtSetReportMode( _CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG );
2502
#endif
2503
2504
    /* turn on floating point exceptions */
2505
#if ( !defined(__STDC__) || __STDC__ != 1 )
2506
    {
2507
        /* Get the default control word. */
2508
        int cw = _controlfp( 0, 0 );
2509
2510
        /* Set the exception masks OFF, turn exceptions on. */
2511
        /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
2512
        cw &= ~( EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL );
2513
2514
        /* Set the control word. */
2515
        _controlfp( cw, MCW_EM );
2516
    }
2517
#endif
2518
#endif
2519
2520
2.20k
    memset( outStruct, 0, sizeof( *outStruct ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2521
2522
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2523
    repeat:
2524
    FreeStructFromINCHI( &outStruct );
2525
    inchi_ios_reset( input_file );  /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2526
    inchi_ios_close( out_file );
2527
    inchi_ios_close( log_file );
2528
#endif
2529
2530
2.20k
    sd->bUserQuit = 0;
2531
2532
    /* Initialize internal for this function I/O streams as string buffers */
2533
2.20k
    inchi_ios_init( input_file, INCHI_IOS_TYPE_STRING, NULL );
2534
2.20k
    inchi_ios_init( out_file, INCHI_IOS_TYPE_STRING, NULL );
2535
2.20k
    inchi_ios_init( log_file, INCHI_IOS_TYPE_STRING, NULL );
2536
2537
    /* clear original input structure */
2538
2.20k
    memset( sd, 0, sizeof( *sd ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2539
2.20k
    memset( ip, 0, sizeof( *ip ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2540
2.20k
    memset( szSdfDataValue, 0, sizeof( szSdfDataValue ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2541
2542
2.20k
    memset( &ic, 0, sizeof( ic ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2543
2.20k
    memset( &CG, 0, sizeof( CG ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2544
2545
2.20k
    szMainOption[1] = INCHI_OPTION_PREFX;
2546
2547
2.20k
    if (!inpInChI)
2548
0
    {
2549
0
        nRet = _IS_ERROR;
2550
0
        goto exit_function;
2551
0
    }
2552
2553
    /* options */
2554
2.20k
    if (inpInChI /*&& inpInChI->szOptions*/)
2555
2.20k
    {
2556
        /* fix bug discovered by Burt Leland 2008-12-23 */
2557
2.20k
        int opt_len = ( inpInChI->szOptions ? strlen( inpInChI->szOptions ) : 0 ) + sizeof( szMainOption ) + 1;
2558
2.20k
        szOptions = (char*)inchi_calloc((long long)opt_len + 1, sizeof(szOptions[0])); /* djb-rwth: cast operator added */
2559
2.20k
        if (szOptions)
2560
2.20k
        {
2561
2.20k
            if (inpInChI->szOptions)
2562
                /* fix bug discovered by Burt Leland 2008-12-23 */
2563
0
                strcpy(szOptions, inpInChI->szOptions);
2564
2.20k
            strcat(szOptions, szMainOption);
2565
2.20k
            argc = parse_options_string( szOptions, argv, INCHI_MAX_NUM_ARG );
2566
2.20k
        }
2567
0
        else
2568
0
        {
2569
0
            nRet = _IS_FATAL;
2570
0
            goto translate_RetVal; /* emergency exit */
2571
0
        }
2572
2.20k
    }
2573
0
    else
2574
0
    {
2575
0
        argc = 1;
2576
0
            argv[0] = "";
2577
0
        argv[1] = NULL;
2578
0
    }
2579
2580
2.20k
    if ((argc == 1
2581
2.20k
#ifdef TARGET_API_LIB
2582
2.20k
        && ( !inpInChI || !inpInChI->szInChI ))
2583
2.20k
#endif
2584
2.20k
        || (argc == 2 && ( argv[1][0] == INCHI_OPTION_PREFX ) &&
2585
2.20k
        ( !strcmp( argv[1] + 1, "?" ) || !inchi_stricmp( argv[1] + 1, "help" ) ))) /* djb-rwth: addressing LLVM warnings */
2586
0
    {
2587
0
        HelpCommandLineParms( log_file );
2588
0
        outStruct->szLog = log_file->s.pStr;
2589
0
        nRet = _IS_EOF;
2590
0
        goto translate_RetVal;
2591
0
    }
2592
2593
2.20k
    nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue,
2594
2.20k
                                  &ulDisplTime, bReleaseVersion,
2595
2.20k
                                  log_file );
2596
2597
2.20k
    if (szOptions)
2598
2.20k
    {
2599
        /* argv pointed to strings in szOptions */
2600
2.20k
        inchi_free( szOptions );
2601
2.20k
        szOptions = NULL;
2602
2.20k
    }
2603
2604
    /* INChI DLL specific */
2605
2.20k
    ip->bNoStructLabels = 1;
2606
2607
2.20k
    if (0 > nRet1)
2608
0
    {
2609
0
        goto exit_function;
2610
0
    }
2611
2612
2.20k
    if (ip->bNoStructLabels)
2613
2.20k
    {
2614
2.20k
        ip->pSdfLabel = NULL;
2615
2.20k
        ip->pSdfValue = NULL;
2616
2.20k
    }
2617
0
    else if (ip->nInputType == INPUT_INCHI_XML ||
2618
0
            ip->nInputType == INPUT_INCHI_PLAIN ||
2619
0
            ip->nInputType == INPUT_CMLFILE ||
2620
0
            ip->nInputType == INPUT_INCHI)
2621
0
    {
2622
        /* the input may contain both the header and the label of the structure */
2623
0
        if (!ip->pSdfLabel)
2624
0
            ip->pSdfLabel = ip->szSdfDataHeader;
2625
0
        if (!ip->pSdfValue)
2626
0
            ip->pSdfValue = szSdfDataValue;
2627
0
    }
2628
2629
2.20k
    if (ip->nInputType && ip->nInputType != INPUT_INCHI)
2630
0
    {
2631
0
        inchi_ios_eprint( log_file, "Input type set to INPUT_INCHI\n" );
2632
0
        ip->nInputType = INPUT_INCHI;
2633
0
    }
2634
2635
2.20k
    if (!inpInChI->szInChI)
2636
0
    {
2637
0
        nRet = _IS_ERROR;
2638
0
        goto exit_function;
2639
0
    }
2640
2.20k
    else
2641
2.20k
    {
2642
2.20k
        const int strict = 0;                     /* do not use strict mode, it may be too alarmous */
2643
2.20k
        nRet = CheckINCHI( inpInChI->szInChI, strict );
2644
2.20k
        if (nRet == INCHI_VALID_STANDARD || nRet == INCHI_VALID_NON_STANDARD || nRet == INCHI_VALID_BETA) /* djb-rwth: removing redundant code */
2645
2.12k
        {
2646
2.12k
            ;
2647
2.12k
        }
2648
77
        else
2649
77
        {
2650
77
            nRet = _IS_ERROR;
2651
77
            goto exit_function;
2652
77
        }
2653
2.20k
    }
2654
2655
2.12k
    PrintInputParms( log_file, ip );
2656
2657
    /*********************************/
2658
    /* InChI -> Structure conversion */
2659
    /*********************************/
2660
2661
    /* input_file simulation */
2662
2663
    /*
2664
    that was incorrect simulation, and correct one is much simpler, see below
2665
    input_file->s.pStr = inpInChI->szInChI;
2666
    input_file->s.nUsedLength = (int) strlen(input_file->s.pStr)+1;
2667
    input_file->s.nAllocatedLength = input_file->s.nUsedLength;
2668
    input_file->s.nPtr = 0;
2669
    */
2670
2.12k
    inchi_ios_print_nodisplay( input_file, inpInChI->szInChI );
2671
2672
    /* buffer for the message */
2673
    /* outStruct->szMessage = (char *)inchi_calloc( MAX_MSG_LEN, sizeof(outStruct->szMessage[0])); */
2674
2675
2.12k
    outStruct->szMessage = (char *) inchi_calloc( MAX_MSG_LEN, sizeof( char ) );
2676
2.12k
    if (!outStruct->szMessage)
2677
0
    {
2678
0
        inchi_ios_eprint( log_file, "Cannot allocate output message buffer.\n" );
2679
0
        nRet = -1;
2680
0
    }
2681
2.12k
    else
2682
2.12k
    {
2683
2.12k
        int num_bonds;
2684
2.12k
        nRet = ReadWriteInChI( &ic, &CG , input_file, out_file, log_file,
2685
2.12k
                                ip, sd, &at, &num_at, &num_bonds,
2686
2.12k
                                &polymer, &v3000,
2687
2.12k
                                outStruct->szMessage,
2688
2.12k
                                MAX_MSG_LEN, outStruct->WarningFlags );
2689
2690
2.12k
        if (nRet >= 0 && polymer)
2691
0
        {
2692
0
            OAD_Polymer_SmartReopenCyclizedUnits( polymer, at,
2693
0
                                                 num_at, &num_bonds );
2694
0
        }
2695
2.12k
    }
2696
2697
2.12k
    if (nRet >= 0 && at && num_at)
2698
353
    {
2699
        /* success */
2700
353
        nRet = InpAtom0DToInchiAtom( at, num_at,
2701
353
                                    &outStruct->num_atoms,
2702
353
                                    &outStruct->atom,
2703
353
                                    &outStruct->num_stereo0D,
2704
353
                                    &outStruct->stereo0D );
2705
2706
353
        if (at)
2707
353
        {
2708
353
            inchi_free( at );
2709
353
            at = NULL;
2710
353
        }
2711
2712
353
        if (nRet >= 0 && polymer)
2713
0
        {
2714
            /* Check for and then replace ZZ for star atoms if Polymer extension is supplied */
2715
0
            for (i = 0; i < outStruct->num_atoms; i++)
2716
0
            {
2717
0
                if (!strcmp( outStruct->atom[i].elname, "Zz" ))
2718
0
                {
2719
0
                    strcpy( outStruct->atom[i].elname, "*" );
2720
0
                }
2721
0
            }
2722
0
        }
2723
2724
353
        if (nRet >= 0)
2725
353
        {
2726
353
            if (polymer || v3000)
2727
0
            {
2728
0
                nRet = SetInChIExtInputByExtOrigAtData( polymer, v3000,
2729
0
                                                        &outStruct->polymer,
2730
0
                                                        &outStruct->v3000,
2731
0
                                                        outStruct->num_atoms ); /* pair to SetExtOrigAtDataByInChIExtInput */
2732
0
                FreeExtOrigAtData( polymer, v3000 );
2733
0
                polymer = NULL;
2734
0
                v3000 = NULL;
2735
0
            }
2736
353
        }
2737
353
        if (nRet < 0)
2738
0
        {
2739
0
            inchi_ios_eprint( log_file, "Final structure conversion failed\n" );
2740
0
        }
2741
353
    }
2742
2.12k
    outStruct->szLog = log_file->s.pStr;
2743
2744
2.20k
exit_function:;
2745
2746
11.0k
    for (i = 0; i < MAX_NUM_PATHS; i++)
2747
8.81k
    {
2748
8.81k
        if (ip->path[i])
2749
0
        {
2750
0
            inchi_free( (char*) ip->path[i] ); /*  cast deliberately discards 'const' qualifier */
2751
0
            ip->path[i] = NULL;
2752
0
        }
2753
8.81k
    }
2754
2755
2.20k
    SetBitFree( &CG );
2756
2757
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2758
    if (num_repeat-- > 0)
2759
    {
2760
        goto repeat;
2761
    }
2762
#endif
2763
2764
2.20k
#ifdef TARGET_API_LIB
2765
    /* output */
2766
2.20k
    if (log_file->s.pStr && log_file->s.nUsedLength > 0)
2767
2.12k
    {
2768
4.41k
        while (log_file->s.nUsedLength &&
2769
4.41k
                '\n' == log_file->s.pStr[log_file->s.nUsedLength - 1])
2770
2.29k
        {
2771
2.29k
            log_file->s.pStr[--log_file->s.nUsedLength] = '\0'; /* remove last LF */
2772
2.29k
        }
2773
2.12k
        if (outStruct)
2774
2.12k
        {
2775
2.12k
            outStruct->szLog = log_file->s.pStr;
2776
2.12k
            log_file->s.pStr = NULL;
2777
2.12k
        }
2778
2.12k
    }
2779
2.20k
#endif
2780
2781
2.20k
translate_RetVal:
2782
2783
    /* Close internal I/O streams */
2784
    /* that was incorrect also
2785
    inchi_ios_reset(input_file);  */    /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2786
2.20k
    inchi_ios_close( input_file );
2787
2.20k
    inchi_ios_close( out_file );
2788
2.20k
    inchi_ios_close( log_file );
2789
2790
2.20k
    switch (nRet)
2791
2.20k
    {
2792
1.16k
        case -3: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2793
540
        case -2: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2794
0
        case -1: nRet = inchi_Ret_FATAL; break; /* Severe error: no Structure has been created (typically; break; memory allocation failed) */
2795
499
        default:
2796
499
            if (outStruct) /* djb-rwth: fixing a NULL pointer dereference */
2797
499
            {
2798
499
                if (!outStruct->atom || !outStruct->num_atoms)
2799
146
                {
2800
146
                    nRet = inchi_Ret_EOF;
2801
146
                }
2802
353
                else
2803
353
                {
2804
353
                    int m, n, t = 0;
2805
1.05k
                    for (m = 0; m < 2; m++)
2806
706
                    {
2807
2.11k
                        for (n = 0; n < 2; n++)
2808
1.41k
                        {
2809
1.41k
                            if (outStruct->WarningFlags[m][n])
2810
316
                            {
2811
316
                                t++;
2812
316
                            }
2813
1.41k
                        }
2814
706
                    }
2815
353
                    nRet = t ? inchi_Ret_WARNING : inchi_Ret_OKAY;
2816
353
                }
2817
499
                break;
2818
499
            }
2819
2.20k
    }
2820
2821
2.20k
    return nRet;
2822
2.20k
}
2823
2824
2825
/****************************************************************************
2826
2827
    GetStructFromINCHI
2828
2829
****************************************************************************/
2830
EXPIMP_TEMPLATE INCHI_API
2831
int INCHI_DECL GetStructFromINCHI( inchi_InputINCHI *inpInChI,
2832
                                   inchi_OutputStruct *out )
2833
2.20k
{
2834
2.20k
    int ret = 0;
2835
2836
2.20k
    inchi_OutputStructEx outex;
2837
2.20k
    memset( out, 0, sizeof( *out ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2838
2839
2.20k
    ret = GetStructFromINCHIEx( inpInChI, &outex );
2840
2841
2.20k
    out->szLog = outex.szLog;
2842
2.20k
    out->szMessage = outex.szMessage;
2843
2.20k
    out->WarningFlags[0][0] = outex.WarningFlags[0][0];
2844
2.20k
    out->WarningFlags[0][1] = outex.WarningFlags[0][1];
2845
2.20k
    out->WarningFlags[1][0] = outex.WarningFlags[1][0];
2846
2.20k
    out->WarningFlags[1][1] = outex.WarningFlags[1][1];
2847
2848
2.20k
    if (ret == inchi_Ret_OKAY || ret == inchi_Ret_WARNING)
2849
353
    {
2850
353
        out->num_atoms = outex.num_atoms;
2851
353
        out->atom = outex.atom;
2852
353
        out->num_stereo0D = outex.num_stereo0D;
2853
353
        out->stereo0D = outex.stereo0D;
2854
353
    }
2855
2856
2.20k
    return ret;
2857
2.20k
}
2858
2859
2860
2861
/****************************************************************************
2862
2863
    FreeStructFromINCHIEx
2864
2865
****************************************************************************/
2866
EXPIMP_TEMPLATE INCHI_API
2867
void INCHI_DECL FreeStructFromINCHIEx( inchi_OutputStructEx *out )
2868
0
{
2869
0
    if (!out)
2870
0
        return;
2871
2872
0
    if (out->atom)
2873
0
    {
2874
0
        inchi_free( out->atom );
2875
0
    }
2876
0
    if (out->stereo0D)
2877
0
    {
2878
0
        inchi_free( out->stereo0D );
2879
0
    }
2880
0
    if (out->szLog)
2881
0
    {
2882
0
        inchi_free( out->szLog );
2883
0
    }
2884
0
    if (out->szMessage)
2885
0
    {
2886
0
        inchi_free( out->szMessage );
2887
0
    }
2888
0
    if (out->polymer || out->v3000)
2889
0
    {
2890
0
        FreeInChIExtInput( out->polymer, out->v3000 );
2891
0
    }
2892
2893
0
    memset( out, 0, sizeof( *out ) ); /* djb-rwth: memset_s C11/Annex K variant? */
2894
0
}
2895
2896
2897
/****************************************************************************/
2898
void FreeInChIExtInput( inchi_Input_Polymer *polymer, inchi_Input_V3000 *v3000 )
2899
0
{
2900
0
    int k;
2901
0
    if (polymer)
2902
0
    {
2903
0
        if (polymer->n && polymer->units)
2904
0
        {
2905
0
            for (k = 0; k < polymer->n; k++)
2906
0
            {
2907
0
                if (polymer->units[k])
2908
0
                {
2909
0
                    if (polymer->units[k]->alist)
2910
0
                    {
2911
0
                        inchi_free( polymer->units[k]->alist );  polymer->units[k]->alist = NULL;
2912
0
                    }
2913
0
                    if (polymer->units[k]->blist)
2914
0
                    {
2915
0
                        inchi_free( polymer->units[k]->blist );  polymer->units[k]->blist = NULL;
2916
0
                    }
2917
0
                }
2918
0
                inchi_free( polymer->units[k] );
2919
0
            }
2920
0
            inchi_free( polymer->units );
2921
0
            polymer->units = NULL;
2922
0
            inchi_free( polymer );
2923
0
        }
2924
0
    }
2925
0
    if (v3000)
2926
0
    {
2927
0
        if (v3000->atom_index_orig)
2928
0
        {
2929
0
            inchi_free( v3000->atom_index_orig );
2930
0
            v3000->atom_index_orig = NULL;
2931
0
        }
2932
0
        if (v3000->atom_index_fin)
2933
0
        {
2934
0
            inchi_free( v3000->atom_index_fin );
2935
0
            v3000->atom_index_fin = NULL;
2936
0
        }
2937
0
        if (v3000->n_haptic_bonds && v3000->lists_haptic_bonds)
2938
0
        {
2939
0
            for (k = 0; k < v3000->n_haptic_bonds; k++)
2940
0
            {
2941
0
                if (v3000->lists_haptic_bonds[k])
2942
0
                {
2943
0
                    inchi_free( v3000->lists_haptic_bonds[k] );
2944
0
                    v3000->lists_haptic_bonds[k] = NULL;
2945
0
                }
2946
0
            }
2947
0
            inchi_free( v3000->lists_haptic_bonds );
2948
0
            v3000->lists_haptic_bonds = NULL;
2949
0
        }
2950
0
        if (v3000->n_steabs && v3000->lists_steabs)
2951
0
        {
2952
0
            for (k = 0; k < v3000->n_steabs; k++)
2953
0
            {
2954
0
                if (v3000->lists_steabs[k])
2955
0
                {
2956
0
                    inchi_free( v3000->lists_steabs[k] );
2957
0
                    v3000->lists_steabs[k] = NULL;
2958
0
                }
2959
0
            }
2960
0
            inchi_free( v3000->lists_steabs );
2961
0
            v3000->lists_steabs = NULL;
2962
0
        }
2963
0
        if (v3000->n_sterel && v3000->lists_sterel)
2964
0
        {
2965
0
            for (k = 0; k < v3000->n_sterel; k++)
2966
0
            {
2967
0
                if (v3000->lists_sterel[k])
2968
0
                {
2969
0
                    inchi_free( v3000->lists_sterel[k] );
2970
0
                    v3000->lists_sterel[k] = NULL;
2971
0
                }
2972
0
            }
2973
0
            inchi_free( v3000->lists_sterel );
2974
0
            v3000->lists_sterel = NULL;
2975
0
        }
2976
0
        if (v3000->n_sterac && v3000->lists_sterac)
2977
0
        {
2978
0
            for (k = 0; k < v3000->n_sterac; k++)
2979
0
            {
2980
0
                if (v3000->lists_sterac[k])
2981
0
                {
2982
0
                    inchi_free( v3000->lists_sterac[k] );
2983
0
                    v3000->lists_sterac[k] = NULL;
2984
0
                }
2985
0
            }
2986
0
            inchi_free( v3000->lists_sterac );
2987
0
            v3000->lists_sterac = NULL;
2988
0
        }
2989
0
        inchi_free( v3000 );
2990
        /*memset( v3000, 0, sizeof( *v3000 ) );*/
2991
0
    }
2992
0
}
2993
2994
2995
/****************************************************************************/
2996
int SetExtOrigAtDataByInChIExtInput( OAD_Polymer **ppPolymer,
2997
                                     OAD_V3000 **ppV3000,
2998
                                     inchi_Input_Polymer *iep,
2999
                                     inchi_Input_V3000 *iev,
3000
                                     int nat )
3001
0
{
3002
0
    int    k, m, err = 0;
3003
0
    OAD_V3000 *pv = NULL;
3004
3005
    /* Polymers */
3006
0
    if (iep && iep->n)
3007
0
    {
3008
        /* Prepare OAD_Polymer container */
3009
0
        *ppPolymer = (OAD_Polymer *) inchi_calloc( 1, sizeof( OAD_Polymer ) );
3010
0
        if (!*ppPolymer)
3011
0
        {
3012
0
            err = 9001;
3013
0
            goto exitf;
3014
0
        }
3015
3016
        /* Convert Molfile's Sgroup's to OAD_PolymerUnit's */
3017
0
        ( *ppPolymer )->units = (OAD_PolymerUnit**) inchi_calloc( iep->n, sizeof( ( *ppPolymer )->units[0] ) );
3018
0
        if (!( *ppPolymer )->units)
3019
0
        {
3020
0
            err = 9001;
3021
0
            goto exitf;
3022
0
        }
3023
0
        memset( ( *ppPolymer )->units, 0, sizeof( *( *ppPolymer )->units ) ); /* djb-rwth: memset_s C11/Annex K variant? */
3024
3025
0
        ( *ppPolymer )->n = iep->n;
3026
        /*( *ppPolymer )->valid = -1;*/
3027
0
        ( *ppPolymer )->really_do_frame_shift = 0;
3028
3029
0
        for (k = 0; k < iep->n; k++)
3030
0
        {
3031
0
            int q = 0;
3032
0
            OAD_PolymerUnit *unitk;
3033
3034
0
            inchi_Input_PolymerUnit *groupk = iep->units[k];
3035
0
            ( *ppPolymer )->units[k] = (OAD_PolymerUnit*) inchi_calloc( 1, sizeof( OAD_PolymerUnit ) );
3036
0
            unitk = ( *ppPolymer )->units[k];
3037
0
            if (!unitk)
3038
0
            {
3039
0
                err = 9001;
3040
0
                goto exitf;
3041
0
            }
3042
3043
0
            memset( unitk, 0, sizeof( *unitk ) ); /* djb-rwth: memset_s C11/Annex K variant? */
3044
0
            unitk->id = groupk->id;
3045
0
            unitk->type = groupk->type;
3046
0
            unitk->subtype = groupk->subtype;
3047
0
            unitk->conn = groupk->conn;
3048
0
            unitk->label = groupk->label;
3049
3050
0
            for (q = 0; q < 4; q++)
3051
0
            {
3052
0
                unitk->xbr1[q] = groupk->xbr1[q];
3053
0
                unitk->xbr2[q] = groupk->xbr2[q];
3054
0
            }
3055
0
            strcpy( unitk->smt, groupk->smt );
3056
0
            unitk->na = groupk->na;
3057
0
            unitk->alist = (int *) inchi_calloc( unitk->na, sizeof( int ) );
3058
0
            if (!unitk->alist )
3059
0
            {
3060
0
                err = 9001;
3061
0
                goto exitf;
3062
0
            }
3063
0
            for (m = 0; m < unitk->na; m++)
3064
0
            {
3065
0
                unitk->alist[m] = groupk->alist[m];
3066
0
            }
3067
0
            unitk->nb = groupk->nb;
3068
0
            if (unitk->nb > 0)
3069
0
            {
3070
0
                unitk->blist = (int *) inchi_calloc( 2 * (long long)unitk->nb, sizeof( int ) ); /* djb-rwth: cast operator added */
3071
0
                if (!unitk->blist )
3072
0
                {
3073
0
                    err = 9001;
3074
0
                    goto exitf;
3075
0
                }
3076
0
                for (m = 0; m < 2 * groupk->nb; m++)
3077
0
                {
3078
0
                    unitk->blist[m] = groupk->blist[m];
3079
0
                }
3080
0
            }
3081
0
            else
3082
0
            {
3083
0
                unitk->blist = NULL;
3084
0
            }
3085
0
        }
3086
0
    }
3087
3088
    /* V3000 Extensions */
3089
0
    if (iev)
3090
0
    {
3091
0
        int nn;
3092
0
        *ppV3000 = (OAD_V3000 *) inchi_calloc( 1, sizeof( OAD_V3000 ) );
3093
0
        pv = *ppV3000;
3094
0
        if (!pv)
3095
0
        {
3096
0
            err = 9001;
3097
0
            goto exitf;
3098
0
        }
3099
0
        memset( pv, 0, sizeof( *pv ) ); /* djb-rwth: memset_s C11/Annex K variant? */
3100
3101
0
        pv->n_collections = iev->n_collections;
3102
0
        pv->n_haptic_bonds = iev->n_haptic_bonds;
3103
0
        pv->n_non_haptic_bonds = iev->n_non_haptic_bonds;
3104
0
        pv->n_sgroups = iev->n_sgroups;
3105
0
        pv->n_non_star_atoms = iev->n_non_star_atoms;
3106
0
        pv->n_star_atoms = iev->n_star_atoms;
3107
0
        pv->n_steabs = iev->n_steabs;
3108
0
        pv->n_sterac = iev->n_sterac;
3109
0
        pv->n_sterel = iev->n_sterel;
3110
0
        pv->n_3d_constraints = iev->n_3d_constraints;
3111
3112
0
        if (iev->atom_index_orig)
3113
0
        {
3114
0
            pv->atom_index_orig = (int *) inchi_calloc( nat, sizeof( int ) );
3115
0
            if (NULL == pv->atom_index_orig)
3116
0
            {
3117
0
                err = 9001;
3118
0
                goto exitf;
3119
0
            }
3120
0
            memcpy( pv->atom_index_orig, iev->atom_index_orig, nat );
3121
0
        }
3122
0
        if (iev->atom_index_fin)
3123
0
        {
3124
0
            pv->atom_index_fin = (int *) inchi_calloc( nat, sizeof( int ) );
3125
0
            if (NULL == pv->atom_index_fin)
3126
0
            {
3127
0
                err = 9001;
3128
0
                goto exitf;
3129
0
            }
3130
0
            memcpy( pv->atom_index_fin, iev->atom_index_fin, nat );
3131
0
        }
3132
0
        if (iev->n_haptic_bonds && iev->lists_haptic_bonds)
3133
0
        {
3134
0
            pv->lists_haptic_bonds = (int **) inchi_calloc( iev->n_haptic_bonds, sizeof( int* ) );
3135
0
            if (NULL == pv->lists_haptic_bonds)
3136
0
            {
3137
0
                err = 9001;
3138
0
                goto exitf;
3139
0
            }
3140
0
            for (m = 0; m < iev->n_haptic_bonds; m++)
3141
0
            {
3142
0
                int *lst = NULL;
3143
0
                int *mol_lst = iev->lists_haptic_bonds[m];
3144
0
                nn = mol_lst[2] + 3;
3145
0
                lst = pv->lists_haptic_bonds[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3146
0
                if (NULL == lst)
3147
0
                {
3148
0
                    err = 9001;
3149
0
                    goto exitf;
3150
0
                }
3151
0
                for (k = 0; k < nn; k++)
3152
0
                {
3153
0
                    lst[k] = mol_lst[k];
3154
0
                }
3155
0
            }
3156
0
        }
3157
0
        if (iev->n_steabs && iev->lists_steabs)
3158
0
        {
3159
0
            pv->lists_steabs = (int **) inchi_calloc( iev->n_steabs, sizeof( int* ) );
3160
0
            if (NULL == pv->lists_steabs) { err = 9001; goto exitf; }
3161
0
            for (m = 0; m < iev->n_steabs; m++)
3162
0
            {
3163
0
                int *lst = NULL;
3164
0
                int *mol_lst = iev->lists_steabs[m];
3165
0
                nn = mol_lst[1] + 2;
3166
0
                lst = pv->lists_steabs[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3167
0
                if (NULL == lst)
3168
0
                {
3169
0
                    err = 9001;
3170
0
                    goto exitf;
3171
0
                }
3172
0
                for (k = 0; k < nn; k++)
3173
0
                {
3174
0
                    lst[k] = mol_lst[k];
3175
0
                }
3176
0
            }
3177
0
        }
3178
0
        if (iev->n_sterac && iev->lists_sterac)
3179
0
        {
3180
0
            pv->lists_sterac = (int **) inchi_calloc( iev->n_sterac, sizeof( int* ) );
3181
0
            if (NULL == pv->lists_sterac) { err = 9001; goto exitf; }
3182
0
            for (m = 0; m < iev->n_sterac; m++)
3183
0
            {
3184
0
                int *lst = NULL;
3185
0
                int *mol_lst = iev->lists_sterac[m];
3186
0
                nn = mol_lst[1] + 2;
3187
0
                lst = pv->lists_sterac[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3188
0
                if (NULL == lst)
3189
0
                {
3190
0
                    err = 9001;
3191
0
                    goto exitf;
3192
0
                }
3193
0
                for (k = 0; k < nn; k++)
3194
0
                {
3195
0
                    lst[k] = mol_lst[k];
3196
0
                }
3197
0
            }
3198
0
        }
3199
0
        if (iev->n_sterel && iev->lists_sterel)
3200
0
        {
3201
0
            pv->lists_sterel = (int **) inchi_calloc( iev->n_sterel, sizeof( int* ) );
3202
0
            if (NULL == pv->lists_sterel) { err = 9001; goto exitf; }
3203
0
            for (m = 0; m < iev->n_sterel; m++)
3204
0
            {
3205
0
                int *lst = NULL;
3206
0
                int *mol_lst = iev->lists_sterel[m];
3207
0
                nn = mol_lst[1] + 2;
3208
0
                lst = pv->lists_sterel[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3209
0
                if (NULL == lst)
3210
0
                {
3211
0
                    err = 9001;
3212
0
                    goto exitf;
3213
0
                }
3214
0
                for (k = 0; k < nn; k++)
3215
0
                {
3216
0
                    lst[k] = mol_lst[k];
3217
0
                }
3218
0
            }
3219
0
        }
3220
0
    }
3221
3222
0
exitf:
3223
0
    if (err)
3224
0
    {
3225
0
        FreeExtOrigAtData( *ppPolymer, pv );
3226
0
    }
3227
3228
0
    return err;
3229
0
}
3230
3231
3232
/****************************************************************************/
3233
int SetInChIExtInputByExtOrigAtData( OAD_Polymer     *orp,
3234
                                     OAD_V3000     *orv,
3235
                                     inchi_Input_Polymer **iip,
3236
                                     inchi_Input_V3000     **iiv,
3237
                                     int nat )
3238
0
{
3239
0
    int    k, m, err = 0;
3240
3241
        /* Polymers */
3242
0
    if (orp && orp->n > 0)
3243
0
    {
3244
0
        *iip = (inchi_Input_Polymer *) inchi_calloc( 1, sizeof( inchi_Input_Polymer ) );
3245
0
        if (!*iip)
3246
0
        {
3247
0
            err = 9001;
3248
0
            goto exitf;
3249
0
        }
3250
0
        ( *iip )->n = orp->n;
3251
0
        ( *iip )->units = (inchi_Input_PolymerUnit**) inchi_calloc( orp->n, sizeof( ( *iip )->units[0] ) );
3252
0
        if (!( *iip )->units)
3253
0
        {
3254
0
            err = 9001; goto exitf;
3255
0
        }
3256
0
        memset( ( *iip )->units, 0, sizeof( *( *iip )->units ) ); /* djb-rwth: memset_s C11/Annex K variant? */
3257
0
        for (k = 0; k < orp->n; k++)
3258
0
        {
3259
0
            int q = 0;
3260
0
            inchi_Input_PolymerUnit *unitk;
3261
0
            OAD_PolymerUnit    *groupk = orp->units[k];
3262
0
            ( *iip )->units[k] = (inchi_Input_PolymerUnit*) inchi_calloc( 1, sizeof( inchi_Input_PolymerUnit ) );
3263
0
            unitk = ( *iip )->units[k];
3264
0
            if (!unitk)
3265
0
            {
3266
0
                err = 9001; goto exitf;
3267
0
            }
3268
0
            memset( unitk, 0, sizeof( *unitk ) ); /* djb-rwth: memset_s C11/Annex K variant? */
3269
0
            unitk->id = groupk->id;
3270
0
            unitk->type = groupk->type;
3271
0
            unitk->subtype = groupk->subtype;
3272
0
            unitk->conn = groupk->conn;
3273
0
            unitk->label = groupk->label;
3274
0
            for (q = 0; q < 4; q++)
3275
0
            {
3276
0
                unitk->xbr1[q] = groupk->xbr1[q];
3277
0
                unitk->xbr2[q] = groupk->xbr2[q];
3278
0
            }
3279
0
            strcpy( unitk->smt, groupk->smt );
3280
0
            unitk->na = groupk->na;
3281
0
            unitk->alist = (int *) inchi_calloc( unitk->na, sizeof( int ) );
3282
0
            if (!unitk->alist)
3283
0
            {
3284
0
                err = 9001; goto exitf;
3285
0
            }
3286
0
            for (m = 0; m < unitk->na; m++)
3287
0
            {
3288
0
                unitk->alist[m] = groupk->alist[m];
3289
0
            }
3290
0
            unitk->nb = groupk->nb;
3291
0
            if (unitk->nb > 0)
3292
0
            {
3293
0
                unitk->blist = (int *) inchi_calloc( 2 * (long long)unitk->nb, sizeof( int ) ); /* djb-rwth: cast operator added */
3294
0
                if (!unitk->blist)
3295
0
                {
3296
0
                    err = 9001; goto exitf;
3297
0
                }
3298
0
                for (m = 0; m < 2 * groupk->nb; m++)
3299
0
                {
3300
0
                    unitk->blist[m] = groupk->blist[m];
3301
0
                }
3302
0
            }
3303
0
            else
3304
0
            {
3305
0
                unitk->blist = NULL;
3306
0
            }
3307
0
        }
3308
0
    }
3309
3310
0
    if (orv)
3311
0
    {
3312
0
        int nn;
3313
0
        *iiv = (inchi_Input_V3000 *) inchi_calloc( 1, sizeof(inchi_Input_V3000) ); /* djb-rwth: fixing the incorrect type of variable */
3314
0
        if (!*iiv)
3315
0
        {
3316
0
            err = 9001; goto exitf;
3317
0
        }
3318
0
        memset( *iiv, 0, sizeof( **iiv ) ); /* djb-rwth: memset_s C11/Annex K variant? */
3319
3320
0
        ( *iiv )->n_collections = orv->n_collections;
3321
0
        ( *iiv )->n_haptic_bonds = orv->n_haptic_bonds;
3322
0
        ( *iiv )->n_non_haptic_bonds = orv->n_non_haptic_bonds;
3323
0
        ( *iiv )->n_sgroups = orv->n_sgroups;
3324
0
        ( *iiv )->n_non_star_atoms = orv->n_non_star_atoms;
3325
0
        ( *iiv )->n_star_atoms = orv->n_star_atoms;
3326
0
        ( *iiv )->n_steabs = orv->n_steabs;
3327
0
        ( *iiv )->n_sterac = orv->n_sterac;
3328
0
        ( *iiv )->n_sterel = orv->n_sterel;
3329
0
        ( *iiv )->n_3d_constraints = orv->n_3d_constraints;
3330
3331
0
        if (orv->atom_index_orig)
3332
0
        {
3333
0
            ( *iiv )->atom_index_orig = (int *) inchi_calloc( nat, sizeof( int ) );
3334
0
            if (NULL == ( *iiv )->atom_index_orig)
3335
0
            {
3336
0
                err = 9001;
3337
0
                goto exitf;
3338
0
            }
3339
0
            memcpy( ( *iiv )->atom_index_orig, orv->atom_index_orig, nat );
3340
0
        }
3341
0
        if (orv->atom_index_fin)
3342
0
        {
3343
0
            ( *iiv )->atom_index_fin = (int *) inchi_calloc( nat, sizeof( int ) );
3344
0
            if (NULL == ( *iiv )->atom_index_fin)
3345
0
            {
3346
0
                err = 9001;
3347
0
                goto exitf;
3348
0
            }
3349
0
            memcpy( ( *iiv )->atom_index_fin, orv->atom_index_fin, nat );
3350
0
        }
3351
0
        if (orv->n_haptic_bonds && orv->lists_haptic_bonds)
3352
0
        {
3353
0
            ( *iiv )->lists_haptic_bonds = (int **) inchi_calloc( orv->n_haptic_bonds, sizeof( int* ) );
3354
0
            if (NULL == ( *iiv )->lists_haptic_bonds)
3355
0
            {
3356
0
                err = 9001;
3357
0
                goto exitf;
3358
0
            }
3359
0
            for (m = 0; m < orv->n_haptic_bonds; m++)
3360
0
            {
3361
0
                int *lst = NULL;
3362
0
                int *mol_lst = orv->lists_haptic_bonds[m];
3363
0
                nn = mol_lst[2] + 3;
3364
0
                lst = ( *iiv )->lists_haptic_bonds[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3365
0
                if (NULL == lst)
3366
0
                {
3367
0
                    err = 9001;
3368
0
                    goto exitf;
3369
0
                }
3370
0
                for (k = 0; k < nn; k++)
3371
0
                {
3372
0
                    lst[k] = mol_lst[k];
3373
0
                }
3374
0
            }
3375
0
        }
3376
0
        if (orv->n_steabs && orv->lists_steabs)
3377
0
        {
3378
0
            ( *iiv )->lists_steabs = (int **) inchi_calloc( orv->n_steabs, sizeof( int* ) );
3379
0
            if (NULL == ( *iiv )->lists_steabs) { err = 9001; goto exitf; }
3380
0
            for (m = 0; m < orv->n_steabs; m++)
3381
0
            {
3382
0
                int *lst = NULL;
3383
0
                int *mol_lst = orv->lists_steabs[m];
3384
0
                nn = mol_lst[1] + 2;
3385
0
                lst = ( *iiv )->lists_steabs[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3386
0
                if (NULL == lst)
3387
0
                {
3388
0
                    err = 9001;
3389
0
                    goto exitf;
3390
0
                }
3391
0
                for (k = 0; k < nn; k++)
3392
0
                {
3393
0
                    lst[k] = mol_lst[k];
3394
0
                }
3395
0
            }
3396
0
        }
3397
0
        if (orv->n_sterac && orv->lists_sterac)
3398
0
        {
3399
0
            ( *iiv )->lists_sterac = (int **) inchi_calloc( orv->n_sterac, sizeof( int* ) );
3400
0
            if (NULL == ( *iiv )->lists_sterac) { err = 9001; goto exitf; }
3401
0
            for (m = 0; m < orv->n_sterac; m++)
3402
0
            {
3403
0
                int *lst = NULL;
3404
0
                int *mol_lst = orv->lists_sterac[m];
3405
0
                nn = mol_lst[1] + 2;
3406
0
                lst = ( *iiv )->lists_sterac[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3407
0
                if (NULL == lst)
3408
0
                {
3409
0
                    err = 9001;
3410
0
                    goto exitf;
3411
0
                }
3412
0
                for (k = 0; k < nn; k++)
3413
0
                {
3414
0
                    lst[k] = mol_lst[k];
3415
0
                }
3416
0
            }
3417
0
        }
3418
0
        if (orv->n_sterel && orv->lists_sterel)
3419
0
        {
3420
0
            ( *iiv )->lists_sterel = (int **) inchi_calloc( orv->n_sterel, sizeof( int* ) );
3421
0
            if (NULL == ( *iiv )->lists_sterel) { err = 9001; goto exitf; }
3422
0
            for (m = 0; m < orv->n_sterel; m++)
3423
0
            {
3424
0
                int *lst = NULL;
3425
0
                int *mol_lst = orv->lists_sterel[m];
3426
0
                nn = mol_lst[1] + 2;
3427
0
                lst = ( *iiv )->lists_sterel[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3428
0
                if (NULL == lst)
3429
0
                {
3430
0
                    err = 9001;
3431
0
                    goto exitf;
3432
0
                }
3433
0
                for (k = 0; k < nn; k++)
3434
0
                {
3435
0
                    lst[k] = mol_lst[k];
3436
0
                }
3437
0
            }
3438
0
        }
3439
0
    }
3440
3441
0
exitf:
3442
0
    if (err)
3443
0
    {
3444
0
        FreeInChIExtInput( *iip, *iiv );
3445
0
    }
3446
3447
0
    return err;
3448
0
}
3449
3450
3451
#if( defined( _WIN32 ) && defined( _MSC_VER ) && _MSC_VER >= 800 && defined(_USRDLL) && defined(BUILD_LINK_AS_DLL) )
3452
/* Win32 & MS VC ++, compile and link as a DLL */
3453
3454
/*********************************************************/
3455
/*   C calling conventions export from Win32 dll         */
3456
/*********************************************************/
3457
3458
/* prototypes */
3459
#ifndef COMPILE_ALL_CPP
3460
#ifdef __cplusplus
3461
extern "C" {
3462
#endif
3463
#endif
3464
3465
    int cdecl_GetINCHI( inchi_Input *inp, inchi_Output *out );
3466
    int cdecl_GetStdINCHI( inchi_Input *inp, inchi_Output *out );
3467
    void cdecl_FreeINCHI( inchi_Output *out );
3468
    void cdecl_FreeStdINCHI( inchi_Output *out );
3469
    int  cdecl_GetStringLength( char *p );
3470
    int  cdecl_Get_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3471
                                            int bDoNotAddH,
3472
                                            int bDiffUnkUndfStereo,
3473
                                            InchiInpData *pInchiInp );
3474
    int  cdecl_Get_std_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3475
                                                int bDoNotAddH,
3476
                                                InchiInpData *pInchiInp );
3477
    /*void cdecl_Free_inchi_Input( inchi_Input *pInp );*/
3478
    void cdecl_Free_std_inchi_Input( inchi_Input *pInp );
3479
    int cdecl_GetStructFromINCHI( inchi_InputINCHI *inpInChI,
3480
                                  inchi_OutputStruct *outStruct );
3481
    int cdecl_GetStructFromStdINCHI( inchi_InputINCHI *inpInChI,
3482
                                     inchi_OutputStruct *outStruct );
3483
    int cdecl_GetINCHIfromINCHI( inchi_InputINCHI *inpInChI,
3484
                                 inchi_Output *out );
3485
    void cdecl_FreeStructFromINCHI( inchi_OutputStruct *outStruct );
3486
    void cdecl_FreeStructFromStdINCHI( inchi_OutputStruct *outStruct );
3487
    int cdecl_CheckINCHI( const char *szINCHI, const int strict );
3488
3489
#ifndef COMPILE_ALL_CPP
3490
#ifdef __cplusplus
3491
}
3492
#endif
3493
#endif
3494
3495
/* implementation */
3496
/* libinchi.def provides export without cdecl_ prefixes */
3497
3498
3499
/****************************************************************************/
3500
int cdecl_GetINCHI( inchi_Input *inp, inchi_Output *out )
3501
{
3502
    return GetINCHI( inp, out );
3503
}
3504
3505
3506
/****************************************************************************/
3507
int cdecl_GetStdINCHI( inchi_Input *inp, inchi_Output *out )
3508
{
3509
    return GetStdINCHI( inp, out );
3510
}
3511
3512
3513
/****************************************************************************/
3514
void cdecl_FreeINCHI( inchi_Output *out )
3515
{
3516
    FreeINCHI( out );
3517
}
3518
3519
3520
/****************************************************************************/
3521
void cdecl_FreeStdINCHI( inchi_Output *out )
3522
{
3523
    FreeStdINCHI( out );
3524
}
3525
3526
3527
/****************************************************************************/
3528
int cdecl_GetStringLength( char *p )
3529
{
3530
    return GetStringLength( p );
3531
}
3532
3533
3534
/****************************************************************************/
3535
int cdecl_Get_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3536
                                      int bDoNotAddH,
3537
                                      int bDiffUnkUndfStereo,
3538
                                      InchiInpData *pInchiInp )
3539
{
3540
    return Get_inchi_Input_FromAuxInfo( szInchiAuxInfo,
3541
                                        bDoNotAddH,
3542
                                        bDiffUnkUndfStereo,
3543
                                        pInchiInp );
3544
}
3545
3546
3547
/****************************************************************************/
3548
int cdecl_Get_std_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3549
                                          int bDoNotAddH,
3550
                                          InchiInpData *pInchiInp )
3551
{
3552
    return Get_std_inchi_Input_FromAuxInfo( szInchiAuxInfo,
3553
                                            bDoNotAddH,
3554
                                            pInchiInp );
3555
}
3556
3557
3558
/****************************************************************************/
3559
void cdecl_Free_std_inchi_Input( inchi_Input *pInp )
3560
{
3561
    Free_std_inchi_Input( pInp );
3562
}
3563
3564
3565
/****************************************************************************/
3566
void cdecl_Free_inchi_Input( inchi_Input *pInp )
3567
{
3568
    Free_inchi_Input( pInp );
3569
}
3570
3571
3572
/****************************************************************************/
3573
int cdecl_GetStructFromINCHI( inchi_InputINCHI *inpInChI,
3574
                              inchi_OutputStruct *outStruct )
3575
{
3576
    return GetStructFromINCHI( inpInChI, outStruct );
3577
}
3578
3579
3580
/****************************************************************************/
3581
int cdecl_GetStructFromStdINCHI( inchi_InputINCHI *inpInChI,
3582
                                 inchi_OutputStruct *outStruct )
3583
{
3584
    return GetStructFromStdINCHI( inpInChI, outStruct );
3585
}
3586
3587
/********************************************************/
3588
void cdecl_FreeStructFromINCHI( inchi_OutputStruct *outStruct )
3589
{
3590
    FreeStructFromINCHI( outStruct );
3591
}
3592
3593
3594
/****************************************************************************/
3595
int cdecl_GetINCHIfromINCHI( inchi_InputINCHI *inpInChI,
3596
                             inchi_Output *out )
3597
{
3598
    return GetINCHIfromINCHI( inpInChI, out );
3599
}
3600
3601
3602
/****************************************************************************/
3603
void cdecl_FreeStructFromStdINCHI( inchi_OutputStruct *outStruct )
3604
{
3605
    FreeStructFromStdINCHI( outStruct );
3606
}
3607
3608
3609
/****************************************************************************/
3610
int cdecl_CheckINCHI( const char *szINCHI, const int strict )
3611
{
3612
    return CheckINCHI( szINCHI, strict );
3613
}
3614
#endif
3615
3616
#if( defined(__GNUC__) && __GNUC__ >= 3 && defined(__MINGW32__) && defined(_WIN32) )
3617
#include <windows.h>
3618
/*********************************************************/
3619
/*   Pacal calling conventions export from Win32 dll     */
3620
/*********************************************************/
3621
#ifndef COMPILE_ALL_CPP
3622
#ifdef __cplusplus
3623
extern "C" {
3624
#endif
3625
#endif
3626
/* prototypes */
3627
3628
    int  PASCAL pasc_GetINCHI( inchi_Input *inp, inchi_Output *out );
3629
    int  PASCAL pasc_GetStdINCHI( inchi_Input *inp, inchi_Output *out );
3630
    void PASCAL pasc_FreeINCHI( inchi_Output *out );
3631
    void PASCAL pasc_FreeStdINCHI( inchi_Output *out );
3632
    int  PASCAL pasc_GetStringLength( char *p );
3633
    int  PASCAL pasc_Get_std_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3634
                                                      int bDoNotAddH,
3635
                                                      InchiInpData *pInchiInp );
3636
    int  PASCAL pasc_Get_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3637
                                                      int bDoNotAddH,
3638
                                                      int bDiffUnkUndfStereo,
3639
                                                      InchiInpData *pInchiInp );
3640
    void PASCAL pasc_Free_inchi_Input( inchi_Input *pInp );
3641
    void PASCAL pasc_Free_std_inchi_Input( inchi_Input *pInp );
3642
    void PASCAL pasc_FreeStructFromINCHI( inchi_OutputStruct *out );
3643
    void PASCAL pasc_FreeStructFromStdINCHI( inchi_OutputStruct *out );
3644
    int PASCAL pasc_GetStructFromINCHI( inchi_InputINCHI *inp, inchi_OutputStruct *out );
3645
    int PASCAL pasc_GetStructFromStdINCHI( inchi_InputINCHI *inp, inchi_OutputStruct *out );
3646
    int PASCAL pasc_CheckINCHI( const char *szINCHI, const int strict );
3647
3648
#ifndef COMPILE_ALL_CPP
3649
#ifdef __cplusplus
3650
}
3651
#endif
3652
#endif
3653
3654
/* implementation */
3655
/* libinchi.def provides export without PASCAL pasc_ prefixes */
3656
3657
3658
/****************************************************************************/
3659
int PASCAL pasc_GetINCHI( inchi_Input *inp, inchi_Output *out )
3660
{
3661
    return GetINCHI( inp, out );
3662
}
3663
3664
3665
/****************************************************************************/
3666
int PASCAL pasc_GetStdINCHI( inchi_Input *inp, inchi_Output *out )
3667
{
3668
    return GetStdINCHI( inp, out );
3669
}
3670
3671
3672
/****************************************************************************/
3673
void PASCAL pasc_FreeINCHI( inchi_Output *out )
3674
{
3675
    FreeINCHI( out );
3676
}
3677
3678
3679
/****************************************************************************/
3680
void PASCAL pasc_FreeStdINCHI( inchi_Output *out )
3681
{
3682
    FreeStdINCHI( out );
3683
}
3684
3685
3686
/****************************************************************************/
3687
int PASCAL pasc_GetStringLength( char *p )
3688
{
3689
    return GetStringLength( p );
3690
}
3691
3692
3693
/****************************************************************************/
3694
int PASCAL pasc_Get_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3695
                                                int bDoNotAddH,
3696
                                                int bDiffUnkUndfStereo,
3697
                                                InchiInpData *pInchiInp )
3698
{
3699
    return Get_inchi_Input_FromAuxInfo( szInchiAuxInfo, bDoNotAddH,
3700
                                            bDiffUnkUndfStereo, pInchiInp );
3701
}
3702
3703
3704
/****************************************************************************/
3705
int PASCAL pasc_Get_std_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3706
                                                int bDoNotAddH,
3707
                                                InchiInpData *pInchiInp )
3708
{
3709
    return Get_std_inchi_Input_FromAuxInfo( szInchiAuxInfo, bDoNotAddH, pInchiInp );
3710
}
3711
3712
3713
/****************************************************************************/
3714
void PASCAL pasc_Free_inchi_Input( inchi_Input *pInp )
3715
{
3716
    Free_inchi_Input( pInp );
3717
}
3718
3719
3720
/****************************************************************************/
3721
void PASCAL pasc_Free_std_inchi_Input( inchi_Input *pInp )
3722
{
3723
    Free_std_inchi_Input( pInp );
3724
}
3725
3726
3727
/****************************************************************************/
3728
void PASCAL pasc_FreeStructFromINCHI( inchi_OutputStruct *out )
3729
{
3730
    FreeStructFromINCHI( out );
3731
}
3732
3733
3734
/****************************************************************************/
3735
void PASCAL pasc_FreeStructFromStdINCHI( inchi_OutputStruct *out )
3736
{
3737
    FreeStructFromStdINCHI( out );
3738
}
3739
3740
3741
/****************************************************************************/
3742
int PASCAL pasc_GetStructFromINCHI( inchi_InputINCHI *inp, inchi_OutputStruct *out )
3743
{
3744
    return GetStructFromINCHI( inp, out );
3745
}
3746
3747
3748
/****************************************************************************/
3749
int PASCAL pasc_GetStructFromStdINCHI( inchi_InputINCHI *inp, inchi_OutputStruct *out )
3750
{
3751
    return GetStructFromStdINCHI( inp, out );
3752
}
3753
3754
3755
/****************************************************************************/
3756
int PASCAL pasc_CheckINCHI( const char *szINCHI, const int strict )
3757
{
3758
    return CheckINCHI( szINCHI, strict );
3759
}
3760
3761
#endif