Coverage Report

Created: 2023-11-19 06:41

/src/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.06
5
 * December 15, 2020
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
65
#include "inchi_dll.h"
66
67
/*************************************************************************
68
 *
69
 *   Local prototypes
70
 *
71
 *************************************************************************/
72
73
int SetAtomProperties( inp_ATOM *at,
74
                       MOL_COORD *szCoord,
75
                       inchi_Atom *ati,
76
                       int a1,
77
                       int *nDim,
78
                       char *pStrErr,
79
                       int *err );
80
void SetNumImplicitH( inp_ATOM* at, int num_atoms );
81
int SetBondProperties( inp_ATOM *at,
82
                       inchi_Atom *ati,
83
                       int a1,
84
                       int j,
85
                       int nNumAtoms,
86
                       int *nNumBonds,
87
                       char *pStrErr,
88
                       int *err );
89
int SetAtomAndBondProperties( inp_ATOM *at,
90
                              inchi_Atom *ati,
91
                              int a1,
92
                              int bDoNotAddH,
93
                              char *pStrErr,
94
                              int *err );
95
int InpAtom0DToInchiAtom( inp_ATOM *at,
96
                          int num_inp_atoms,
97
                          AT_NUM *num_atoms,
98
                          inchi_Atom **atom,
99
                          AT_NUM *num_stereo0D,
100
                          inchi_Stereo0D **stereo0D );
101
int ExtractOneStructure( STRUCT_DATA *sd,
102
                         INPUT_PARMS *ip,
103
                         char *szTitle,
104
                         inchi_InputEx *inp,
105
                         INCHI_IOSTREAM *log_file,
106
                         INCHI_IOSTREAM *out_file,
107
                         INCHI_IOSTREAM *prb_file,
108
                         ORIG_ATOM_DATA *orig_inp_data,
109
                         long *num_inp );
110
111
static int GetINCHI1( inchi_InputEx *inp, inchi_Output *out, int enforce_std_format );
112
113
int SetExtOrigAtDataByInChIExtInput( OAD_Polymer **ppPolymer,
114
                                     OAD_V3000 **ppV3000,
115
                                     inchi_Input_Polymer *polymer,
116
                                     inchi_Input_V3000 *v3000,
117
                                     int nat );
118
int SetInChIExtInputByExtOrigAtData( OAD_Polymer *pPolymer,
119
                                     OAD_V3000 *pV3000,
120
                                     inchi_Input_Polymer **ipolymer,
121
                                     inchi_Input_V3000 **iv3000,
122
                                     int nat );
123
124
/****************************************************************************/
125
126
int bInterrupted = 0;
127
128
129
130
/****************************************************************************
131
 *
132
 * INCHI API
133
 *
134
 ****************************************************************************/
135
136
137
138
/****************************************************************************
139
140
    FreeINCHI
141
142
****************************************************************************/
143
EXPIMP_TEMPLATE INCHI_API
144
void INCHI_DECL FreeINCHI( inchi_Output *out )
145
253
{
146
253
    if (!out)
147
0
    {
148
0
        return;
149
0
    }
150
151
253
    if (out->szInChI)
152
72
    {
153
72
        inchi_free( out->szInChI );
154
72
    }
155
253
    if (out->szLog)
156
213
    {
157
213
        inchi_free( out->szLog );
158
213
    }
159
253
    if (out->szMessage)
160
213
    {
161
213
        inchi_free( out->szMessage );
162
213
    }
163
164
253
    memset( out, 0, sizeof( *out ) );
165
253
}
166
167
168
/****************************************************************************
169
170
    FreeStdINCHI
171
172
****************************************************************************/
173
EXPIMP_TEMPLATE INCHI_API
174
void INCHI_DECL FreeStdINCHI( inchi_Output *out )
175
0
{
176
0
    FreeINCHI( out );
177
0
}
178
179
180
181
/****************************************************************************
182
183
    FreeStructFromStdINCHI
184
****************************************************************************/
185
EXPIMP_TEMPLATE INCHI_API
186
void INCHI_DECL FreeStructFromStdINCHI( inchi_OutputStruct *out )
187
0
{
188
0
    FreeStructFromINCHI( out );
189
0
}
190
191
192
193
/****************************************************************************
194
195
    FreeStructFromINCHI
196
197
****************************************************************************/
198
EXPIMP_TEMPLATE INCHI_API
199
void INCHI_DECL FreeStructFromINCHI( inchi_OutputStruct *out )
200
253
{
201
253
    if (!out)
202
0
    {
203
0
        return;
204
0
    }
205
206
253
    if (out->atom)
207
15
    {
208
15
        inchi_free( out->atom );
209
15
    }
210
253
    if (out->stereo0D)
211
0
    {
212
0
        inchi_free( out->stereo0D );
213
0
    }
214
253
    if (out->szLog)
215
213
    {
216
213
        inchi_free( out->szLog );
217
213
    }
218
253
    if (out->szMessage)
219
213
    {
220
213
        inchi_free( out->szMessage );
221
213
    }
222
223
253
    memset( out, 0, sizeof( *out ) );
224
253
}
225
226
227
/****************************************************************************
228
229
    GetStdINCHI
230
231
****************************************************************************/
232
EXPIMP_TEMPLATE INCHI_API
233
int INCHI_DECL GetStdINCHI( inchi_Input *inp, inchi_Output *out )
234
0
{
235
0
    inchi_InputEx extended_input;
236
237
    /* No '*' or 'Zz' elements are allowed in the input . */
238
0
    if (input_erroneously_contains_pseudoatoms(inp, out))
239
0
    {
240
0
        return _IS_ERROR;
241
0
    }
242
243
0
    extended_input.atom = inp->atom;
244
0
    extended_input.num_atoms = inp->num_atoms;
245
0
    extended_input.num_stereo0D = inp->num_stereo0D;
246
0
    extended_input.stereo0D = inp->stereo0D;
247
0
    extended_input.szOptions = inp->szOptions;
248
0
    extended_input.polymer = NULL;
249
0
    extended_input.v3000 = NULL;
250
251
0
    return GetINCHI1( &extended_input, out, 1 );
252
0
}
253
254
255
/****************************************************************************
256
257
    GetINCHI
258
259
****************************************************************************/
260
EXPIMP_TEMPLATE INCHI_API
261
int INCHI_DECL GetINCHI( inchi_Input *inp, inchi_Output *out )
262
0
{
263
0
    inchi_InputEx extended_input;
264
265
    /* For back compatibility: no '*' or 'Zz' elements are allowed in the input to GetINCHI() ! */
266
0
    if ( input_erroneously_contains_pseudoatoms( inp, out) )
267
0
    {
268
0
        return _IS_ERROR;
269
0
    }
270
271
0
    extended_input.atom = inp->atom;
272
0
    extended_input.num_atoms = inp->num_atoms;
273
0
    extended_input.stereo0D = inp->stereo0D;
274
0
    extended_input.num_stereo0D = inp->num_stereo0D;
275
0
    extended_input.szOptions = inp->szOptions;
276
0
    extended_input.polymer = NULL;
277
0
    extended_input.v3000 = NULL;
278
279
0
    return GetINCHI1( &extended_input, out, 0 );
280
0
}
281
282
283
/****************************************************************************/
284
int input_erroneously_contains_pseudoatoms( inchi_Input *inp,
285
                                            inchi_Output *out)
286
0
{
287
0
    char *str_noz = "Unsupported in this mode element \'*\'";
288
0
    int i;
289
    /* Supposed that no '*' or 'Zz' elements are allowed in the input. */
290
0
    for (i = 0; i < inp->num_atoms; i++)
291
0
    {
292
0
        if (!strcmp(inp->atom->elname, "Zz") || !strcmp(inp->atom->elname, "*"))
293
0
        {
294
0
            if (out)
295
0
            {
296
0
                memset(out, 0, sizeof(*out));
297
0
                if (out->szMessage = (char *)inchi_malloc(strlen(str_noz) + 1))
298
0
                {
299
0
                    strcpy(out->szMessage, str_noz);
300
0
                }
301
0
            }
302
0
            return 1;
303
0
        }
304
0
    }
305
306
0
    return 0;
307
0
}
308
309
310
/****************************************************************************
311
312
    GetINCHIEx
313
314
****************************************************************************/
315
EXPIMP_TEMPLATE INCHI_API
316
int INCHI_DECL GetINCHIEx( inchi_InputEx *inp, inchi_Output *out )
317
0
{
318
0
    int i;
319
320
    /* Check for star atoms and replace them by Zz atoms */
321
0
    for (i = 0; i < inp->num_atoms; i++)
322
0
    {
323
0
        if (!strcmp( inp->atom[i].elname, "*" ))
324
0
        {
325
0
            strcpy( inp->atom[i].elname, "Zz" );
326
0
        }
327
0
    }
328
329
0
    return GetINCHI1( inp, out, 0 );
330
0
}
331
332
333
/****************************************************************************
334
    GetINCHI1 (major worker)
335
****************************************************************************/
336
static int GetINCHI1( inchi_InputEx *extended_input,
337
                      inchi_Output *out,
338
                      int enforce_std_format )
339
0
{
340
0
    STRUCT_DATA struct_data;
341
0
    STRUCT_DATA *sd = &struct_data;
342
0
    char szTitle[MAX_SDF_HEADER + MAX_SDF_VALUE + 256];
343
344
0
    int i;
345
0
    long num_inp, num_err;
346
0
    char      szSdfDataValue[MAX_SDF_VALUE + 1];
347
0
    PINChI2     *pINChI[INCHI_NUM];
348
0
    PINChI_Aux2 *pINChI_Aux[INCHI_NUM];
349
350
0
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
351
0
    unsigned long  ulTotalProcessingTime = 0;
352
353
0
    INPUT_PARMS inp_parms;
354
0
    INPUT_PARMS *ip = &inp_parms;
355
356
0
    ORIG_ATOM_DATA OrigAtData; /* 0=> disconnected, 1=> original */
357
0
    ORIG_ATOM_DATA *orig_inp_data = &OrigAtData;
358
0
    ORIG_ATOM_DATA PrepAtData[2]; /* 0=> disconnected, 1=> original */
359
0
    ORIG_ATOM_DATA *prep_inp_data = PrepAtData;
360
0
    int             bReleaseVersion = bRELEASE_VERSION;
361
0
    int   nRet = 0, nRet1;
362
363
0
    CANON_GLOBALS CG;
364
0
    INCHI_CLOCK ic;
365
366
0
    STRUCT_FPTRS *pStructPtrs = NULL;
367
368
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
369
    int  num_repeat = REPEAT_ALL;
370
#endif
371
372
0
    const char *argv[INCHI_MAX_NUM_ARG + 1];
373
0
    int   argc;
374
0
    char *szOptions = NULL;
375
376
0
    INCHI_IOSTREAM inchi_file[3], *out_file = inchi_file, *log_file = inchi_file + 1;
377
0
    INCHI_IOSTREAM prb_file0, *prb_file = &prb_file0;
378
0
    INCHI_IOS_STRING temp_string_container;
379
0
    INCHI_IOS_STRING *strbuf = &temp_string_container;
380
381
0
    inchi_Input prev_versions_input;
382
0
    inchi_Input *pvinp = &prev_versions_input;
383
384
0
    pvinp->atom = extended_input->atom;
385
0
    pvinp->num_atoms = extended_input->num_atoms;
386
0
    pvinp->num_stereo0D = extended_input->num_stereo0D;
387
0
    pvinp->stereo0D = extended_input->stereo0D;
388
0
    pvinp->szOptions = extended_input->szOptions;
389
390
#if( TRACE_MEMORY_LEAKS == 1 )
391
    _CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF );
392
/* for execution outside the VC++ debugger uncomment one of the following two */
393
#ifdef MY_REPORT_FILE
394
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
395
    _CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
396
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
397
    _CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
398
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
399
    _CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
400
#else
401
    _CrtSetReportMode( _CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG );
402
#endif
403
404
#if ( !defined(__STDC__) || __STDC__ != 1 )
405
    /* turn on floating point exceptions */
406
    {
407
        /* Get the default control word. */
408
        int cw = _controlfp( 0, 0 );
409
410
        /* Set the exception masks OFF, turn exceptions on. */
411
        /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
412
        cw &= ~( EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL );
413
414
        /* Set the control word. */
415
        _controlfp( cw, MCW_EM );
416
    }
417
#endif
418
#endif
419
420
0
    szTitle[0] = '\0';
421
422
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
423
    repeat:
424
          inchi_ios_close( out_file );
425
          inchi_ios_close( log_file );
426
          inchi_ios_close( prb_file );
427
          pStr = NULL;
428
#endif
429
430
    /* Initialize internal for this function output streams as string buffers */
431
0
    inchi_ios_init( out_file, INCHI_IOS_TYPE_STRING, NULL );
432
0
    inchi_ios_init( log_file, INCHI_IOS_TYPE_STRING, NULL );
433
0
    inchi_ios_init( prb_file, INCHI_IOS_TYPE_STRING, NULL );
434
435
0
    num_inp = 0;
436
0
    num_err = 0;
437
0
    sd->bUserQuit = 0;
438
439
    /* clear original input structure */
440
0
    memset( pINChI, 0, sizeof( pINChI ) );
441
0
    memset( pINChI_Aux, 0, sizeof( pINChI_Aux ) );
442
0
    memset( sd, 0, sizeof( *sd ) );
443
0
    memset( ip, 0, sizeof( *ip ) );
444
0
    memset( orig_inp_data, 0, sizeof( *orig_inp_data ) );
445
0
    memset( prep_inp_data, 0, 2 * sizeof( *prep_inp_data ) );
446
0
    memset( szSdfDataValue, 0, sizeof( szSdfDataValue ) );
447
448
0
    memset( &CG, 0, sizeof( CG ) );
449
0
    memset( &ic, 0, sizeof( ic ) );
450
451
0
    if (!out)
452
0
    {
453
0
        nRet = _IS_ERROR;
454
0
        goto exit_function;
455
0
    }
456
0
    memset( out, 0, sizeof( *out ) );
457
458
    /* options */
459
0
    if (pvinp && pvinp->szOptions)
460
0
    {
461
0
        szOptions = (char*) inchi_malloc( strlen( pvinp->szOptions ) + 1 );
462
0
        if (szOptions)
463
0
        {
464
0
            strcpy( szOptions, pvinp->szOptions );
465
0
            argc = parse_options_string( szOptions, argv, INCHI_MAX_NUM_ARG );
466
0
        }
467
0
        else
468
0
        {
469
0
            nRet = _IS_FATAL;
470
0
            goto translate_RetVal; /* emergency exit */
471
0
        }
472
0
    }
473
0
    else
474
0
    {
475
0
        argc = 1;
476
0
        argv[0] = "";
477
0
        argv[1] = NULL;
478
0
    }
479
480
0
    if (argc == 1
481
0
#ifdef TARGET_API_LIB
482
0
              && ( !pvinp || pvinp->num_atoms <= 0 || !pvinp->atom )
483
0
#endif
484
0
              || argc == 2 && ( argv[1][0] == INCHI_OPTION_PREFX ) &&
485
0
                    ( !strcmp( argv[1] + 1, "?" ) || !inchi_stricmp( argv[1] + 1, "help" ) ))
486
0
    {
487
0
        HelpCommandLineParms( log_file );
488
0
        out->szLog = log_file->s.pStr;
489
0
        memset( log_file, 0, sizeof( *log_file ) );
490
0
        nRet = _IS_EOF;
491
0
        goto translate_RetVal;
492
0
    }
493
494
0
    nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue, &ulDisplTime, bReleaseVersion, log_file );
495
0
    if (szOptions)
496
0
    {
497
0
        inchi_free( szOptions );
498
0
        szOptions = NULL;
499
0
    }
500
    /* INChI DLL specific */
501
0
    ip->bNoStructLabels = 1;
502
503
0
    if (0 > nRet1)
504
0
    {
505
0
        nRet = _IS_FATAL;
506
0
        goto exit_function;
507
0
    }
508
0
    if (ip->bNoStructLabels)
509
0
    {
510
0
        ip->pSdfLabel = NULL;
511
0
        ip->pSdfValue = NULL;
512
0
    }
513
0
    else
514
0
    {
515
0
        if (ip->nInputType == INPUT_INCHI_XML || ip->nInputType == INPUT_INCHI_PLAIN || ip->nInputType == INPUT_CMLFILE)
516
0
        {
517
            /* the input may contain both the header and the label of the structure */
518
0
            if (!ip->pSdfLabel)
519
0
                ip->pSdfLabel = ip->szSdfDataHeader;
520
0
            if (!ip->pSdfValue)
521
0
                ip->pSdfValue = szSdfDataValue;
522
0
        }
523
0
    }
524
525
    /* Ensure standardness */
526
0
    if (enforce_std_format)
527
0
    {
528
0
        if (ip->bINChIOutputOptions & INCHI_OUT_SAVEOPT)
529
0
        {
530
0
            ip->bINChIOutputOptions &= ~INCHI_OUT_SAVEOPT;
531
0
        }
532
0
        if (0 != ( ip->bTautFlags & TG_FLAG_RECONNECT_COORD ))
533
0
        {
534
0
            ip->bTautFlags &= ~TG_FLAG_RECONNECT_COORD;
535
0
        }
536
0
        if (0 != ( ip->nMode & REQ_MODE_BASIC ))
537
0
        {
538
0
            ip->nMode &= ~REQ_MODE_BASIC;
539
0
        }
540
0
        if (0 != ( ip->nMode & REQ_MODE_RELATIVE_STEREO ))
541
0
        {
542
0
            ip->nMode &= ~( REQ_MODE_RACEMIC_STEREO | REQ_MODE_RELATIVE_STEREO | REQ_MODE_CHIR_FLG_STEREO );
543
0
        }
544
0
        if (0 != ( ip->nMode & REQ_MODE_RACEMIC_STEREO ))
545
0
        {
546
0
            ip->nMode &= ~( REQ_MODE_RACEMIC_STEREO | REQ_MODE_RELATIVE_STEREO | REQ_MODE_CHIR_FLG_STEREO );
547
0
        }
548
0
        if (0 != ( ip->nMode & REQ_MODE_CHIR_FLG_STEREO ))
549
0
        {
550
0
            ip->nMode &= ~( REQ_MODE_RACEMIC_STEREO | REQ_MODE_RELATIVE_STEREO | REQ_MODE_CHIR_FLG_STEREO );
551
0
        }
552
0
        if (0 != ( ip->nMode & REQ_MODE_DIFF_UU_STEREO ))
553
0
        {
554
0
            ip->nMode &= ~REQ_MODE_DIFF_UU_STEREO;
555
0
        }
556
0
        if (0 == ( ip->nMode & ( REQ_MODE_SB_IGN_ALL_UU | REQ_MODE_SC_IGN_ALL_UU ) ))
557
0
        {
558
0
            ip->nMode |= REQ_MODE_SB_IGN_ALL_UU;
559
0
            ip->nMode |= REQ_MODE_SC_IGN_ALL_UU;
560
0
        }
561
0
        if (0 != ( ip->bTautFlags & TG_FLAG_KETO_ENOL_TAUT ))
562
0
        {
563
0
            ip->bTautFlags &= ~TG_FLAG_KETO_ENOL_TAUT;
564
0
        }
565
0
        if (0 != ( ip->bTautFlags & TG_FLAG_1_5_TAUT ))
566
0
        {
567
0
            ip->bTautFlags &= ~TG_FLAG_1_5_TAUT;
568
0
        }
569
        /* And anyway... */
570
0
        ip->bINChIOutputOptions |= INCHI_OUT_STDINCHI;
571
0
        ip->bINChIOutputOptions &= ~INCHI_OUT_SAVEOPT;
572
0
    }
573
    /* */
574
575
0
    PrintInputParms( log_file, ip );
576
577
0
    if (0 >= inchi_strbuf_init( strbuf, INCHI_STRBUF_INITIAL_SIZE, INCHI_STRBUF_SIZE_INCREMENT ))
578
0
    {
579
0
        inchi_ios_eprint( log_file, "Cannot allocate internal string buffer. Terminating\n" );
580
0
        nRet = _IS_FATAL;
581
0
        goto exit_function;
582
0
    }
583
584
    /***************************************************
585
    /*  Main cycle                                     */
586
    /*  read input structures and create their INChI's */
587
0
    ulTotalProcessingTime = 0;
588
589
0
    if (pStructPtrs)
590
0
    {
591
0
        memset( pStructPtrs, 0, sizeof( pStructPtrs[0] ) );
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
506
{
822
506
    int ret = INCHI_VALID_NON_STANDARD;
823
506
    int ret_i2i;
824
506
    inchi_InputINCHI    inchi_inp;
825
506
    inchi_Output        inchi_out;
826
506
    size_t slen, pos_slash1 = 0;
827
506
    char *str = NULL;
828
506
    size_t i;
829
506
    size_t slen0;
830
506
    char pp;
831
832
    /* .. non-empty */
833
506
    if (szINCHI == NULL)
834
0
    {
835
0
        return INCHI_INVALID_PREFIX;
836
0
    }
837
838
506
    slen = strlen( szINCHI );
839
840
841
    /* .. has valid prefix */
842
506
    if (slen < LEN_INCHI_STRING_PREFIX + 3)
843
2
    {
844
2
        return INCHI_INVALID_PREFIX;
845
2
    }
846
504
    if (memcmp( szINCHI, INCHI_STRING_PREFIX, LEN_INCHI_STRING_PREFIX ))
847
6
    {
848
6
        return INCHI_INVALID_PREFIX;
849
6
    }
850
851
    /* .. has InChI version 1 */
852
    /* if (!isdigit(szINCHI[LEN_INCHI_STRING_PREFIX]) )  */
853
498
    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
498
    pos_slash1 = LEN_INCHI_STRING_PREFIX + 1;
860
498
    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
498
    else if (szINCHI[pos_slash1] == 'B')
867
8
    {
868
        /* Beta version InChI ==> non-standard */
869
8
        ret = INCHI_VALID_BETA;
870
8
        pos_slash1++;
871
8
    }
872
873
    /* .. has trailing slash in the right place */
874
498
    if (szINCHI[pos_slash1] != '/')
875
0
    {
876
0
        return INCHI_INVALID_LAYOUT;
877
0
    }
878
879
    /* .. the rest of source string contains valid literals */
880
881
882
    /* adjust line len so we not check trailing whitespaces */
883
498
    i = slen - 1;
884
498
    while (isspace(UCINT szINCHI[i--])) slen--;
885
886
    /* Treat possible SaveOpt letters  */
887
498
    slen0 = slen;
888
498
    if (( szINCHI[slen - 3] == '\\' ) &&
889
498
        ( szINCHI[slen - 2] >= 'A' ) && ( szINCHI[slen - 2] <= 'Z' ) &&
890
498
        ( szINCHI[slen - 1] >= 'A' ) && ( szINCHI[slen - 1] <= 'Z' )
891
498
        )
892
0
    {
893
0
        slen0 = slen - 3;
894
0
    }
895
896
498
    int prev_is_slash = 1;
897
2.44M
    for (i = pos_slash1 + 1; i < slen0; i++)
898
2.44M
    {
899
2.44M
        pp = szINCHI[i];
900
2.44M
#if ( FIX_GAF_2020_GENERIC==1 )
901
2.44M
        if (prev_is_slash)
902
18.1k
        {
903
            /* After slash: */
904
18.1k
            if (pp == '0')
905
0
            {
906
                /* '0' is never allowed */
907
0
                return INCHI_INVALID_LAYOUT;
908
0
            }
909
18.1k
            if (i > pos_slash1 + 1)
910
17.6k
            {
911
                /* Not in main formula layer... */ 
912
17.6k
                if (!islower(pp))
913
10
                {
914
                    /* only lowercase letters are allowed */
915
10
                    return INCHI_INVALID_LAYOUT;
916
10
                }
917
17.6k
            }
918
18.1k
        }
919
2.44M
        prev_is_slash = (pp != '/') ? 0 : 1;
920
2.44M
#endif
921
2.44M
        if (pp >= 'A' && pp <= 'Z')   continue;
922
2.21M
        if (pp >= 'a' && pp <= 'z')   continue;
923
1.61M
        if (pp >= '0' && pp <= '9')  continue;
924
515k
        switch (pp)
925
515k
        {
926
214k
            case '(': case ')':
927
218k
            case '*': case '+':
928
452k
            case ',': case '-':
929
474k
            case '.': case '/':
930
474k
#if ( FIX_GAF_2020_GENERIC==1 )
931
515k
            case ';': case '?':     continue;
932
#else
933
            case ';': case '=':
934
            case '?': case '@':     continue;
935
#endif
936
62
            default:            return INCHI_INVALID_LAYOUT;
937
515k
        }
938
515k
    }
939
940
426
    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
426
fin:if (strict)
970
0
{
971
0
    if (NULL != str)
972
0
        inchi_free( str );
973
0
}
974
975
426
    return ret;
976
426
}
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
506
{
1025
506
    char    *p;
1026
506
    char    *pArgCurChar;
1027
506
    int      bInsideQuotes;
1028
506
    int      bCopyCharToArg;
1029
506
    int      nNumBackSlashes;
1030
506
    int      i;
1031
1032
506
    i = 0;
1033
506
    argv[i++] = ""; /* zeroth argument is not used */
1034
506
    p = cmd;
1035
506
    bInsideQuotes = 0;
1036
1037
    /* arguments, one by one */
1038
1.01k
    while (i < maxargs - 1)
1039
1.01k
    {
1040
        /* bypass spaces */
1041
1.51k
        while (*p == ' ' || *p == '\t')
1042
506
        {
1043
506
            p++;
1044
506
        }
1045
1.01k
        if (!*p)
1046
506
        {
1047
506
            break;
1048
506
        }
1049
1050
        /* scan an argument */
1051
506
        argv[i++] = pArgCurChar = p;     /* store preliminary ptr to arg */
1052
1053
6.83k
        while (1)
1054
6.83k
        {
1055
6.83k
            bCopyCharToArg = 1;
1056
6.83k
            nNumBackSlashes = 0;
1057
6.83k
            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
6.83k
            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
6.83k
            while (nNumBackSlashes--)
1089
0
            {
1090
0
                *pArgCurChar++ = '\\';
1091
0
            }
1092
6.83k
            if (!*p)
1093
506
            {
1094
506
                break;
1095
506
            }
1096
6.32k
            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
6.32k
            if (bCopyCharToArg)
1104
6.32k
            {
1105
6.32k
                *pArgCurChar++ = *p;
1106
6.32k
            }
1107
6.32k
            ++p;
1108
6.32k
        }
1109
506
        *pArgCurChar++ = '\0';  /* argument zero termination */
1110
506
    }
1111
1112
    /* The last argument is NULL */
1113
506
    argv[i] = NULL;
1114
1115
506
    return i;
1116
506
}
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 ))
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 ))
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 */
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)
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
15
{
1656
15
    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
15
    num_stereo_centers = num_stereo_bonds = ret = 0;
1660
1661
15
    *atom = NULL;
1662
15
    *num_atoms = 0;
1663
15
    *stereo0D = NULL;
1664
15
    *num_stereo0D = 0;
1665
1666
27.1k
    for (i = 0; i < num_inp_atoms; i++)
1667
27.1k
    {
1668
27.1k
        if (at[i].p_parity)
1669
0
        {
1670
            /* stereocenter */
1671
0
            num_stereo_centers++;
1672
0
        }
1673
27.1k
        else
1674
27.1k
        {
1675
27.1k
            for (m = 0; m < MAX_NUM_STEREO_BONDS && at[i].sb_parity[m]; m++)
1676
0
            {
1677
0
                ;
1678
0
            }
1679
27.1k
            num_stereo_bonds += m;
1680
27.1k
        }
1681
27.1k
    }
1682
1683
15
    num_stereo_bonds /= 2;
1684
15
    num_inp_stereo0D = num_stereo_bonds + num_stereo_centers;
1685
1686
15
    if (num_inp_atoms > 0)
1687
15
    {
1688
15
        *atom = (inchi_Atom *) inchi_calloc( num_inp_atoms, sizeof( ( *atom )[0] ) );
1689
15
    }
1690
1691
15
    *num_atoms = num_inp_atoms;
1692
1693
15
    if (num_inp_stereo0D > 0)
1694
0
    {
1695
0
        *stereo0D = (inchi_Stereo0D *) inchi_calloc( num_inp_stereo0D, sizeof( ( *stereo0D )[0] ) );
1696
0
    }
1697
1698
15
    if (num_inp_atoms && !( *atom ) || num_inp_stereo0D > 0 && !( *stereo0D ))
1699
0
    {
1700
        /* allocation failed */
1701
0
        ret = -1;
1702
0
        goto exit_function;
1703
0
    }
1704
1705
    /* copy atom properties */
1706
27.1k
    for (i = 0; i < num_inp_atoms; i++)
1707
27.1k
    {
1708
27.1k
        ( *atom )[i].num_bonds = at[i].valence;
1709
27.1k
        for (m = 0; m < at[i].valence; m++)
1710
14
        {
1711
14
            ( *atom )[i].bond_type[m] = at[i].bond_type[m];
1712
14
            ( *atom )[i].neighbor[m] = at[i].neighbor[m];
1713
14
        }
1714
27.1k
        ( *atom )[i].charge = at[i].charge;
1715
27.1k
        memcpy( ( *atom )[i].elname, at[i].elname, ATOM_EL_LEN );
1716
27.1k
        if (at[i].iso_atw_diff)
1717
13
        {
1718
13
            ( *atom )[i].isotopic_mass = ISOTOPIC_SHIFT_FLAG + ( at[i].iso_atw_diff > 0 ? at[i].iso_atw_diff - 1 : at[i].iso_atw_diff );
1719
13
        }
1720
27.1k
        ( *atom )[i].num_iso_H[0] = at[i].num_H;
1721
108k
        for (m = 0; m < NUM_H_ISOTOPES; m++)
1722
81.5k
        {
1723
81.5k
            ( *atom )[i].num_iso_H[m + 1] = at[i].num_iso_H[m];
1724
81.5k
        }
1725
27.1k
        ( *atom )[i].radical = at[i].radical;
1726
27.1k
    }
1727
1728
    /* stereo */
1729
27.1k
    for (i = n = 0; i < num_inp_atoms; i++)
1730
27.1k
    {
1731
27.1k
        if (at[i].p_parity)
1732
0
        {
1733
0
            if (n < num_inp_stereo0D)
1734
0
            {
1735
0
                ( *stereo0D )[n].central_atom = i;
1736
0
                ( *stereo0D )[n].parity = at[i].p_parity;
1737
0
                ( *stereo0D )[n].type = INCHI_StereoType_Tetrahedral;
1738
0
                for (m = 0; m < MAX_NUM_STEREO_ATOM_NEIGH; m++)
1739
0
                {
1740
0
                    ( *stereo0D )[n].neighbor[m] = at[i].p_orig_at_num[m] - 1;
1741
0
                }
1742
0
                n++;
1743
0
            }
1744
0
            else
1745
0
            {
1746
0
                ret |= 1;
1747
0
                break;
1748
0
            }
1749
0
        }
1750
27.1k
        else
1751
27.1k
        {
1752
27.1k
            for (m1 = 0; m1 < MAX_NUM_STEREO_BONDS && at[i].sb_parity[m1]; m1++)
1753
0
            {
1754
                /* find the opposite atom at the other end of double bond, allene, or cumulene */
1755
0
                int chain[12], len = 0, nxt_neigh, nxt, cur;
1756
0
                cur = chain[len++] = i;
1757
0
                nxt_neigh = at[cur].sb_ord[m1];
1758
1759
0
                do
1760
0
                {
1761
                    /* add next atom */
1762
0
                    chain[len++] = nxt = at[cur].neighbor[nxt_neigh];
1763
0
                    nxt_neigh = ( at[nxt].neighbor[0] == cur );
1764
0
                    cur = nxt;
1765
                    /* find nxt_neigh */
1766
0
                }
1767
0
                while (!at[cur].sb_parity[0] &&
1768
0
                       len < 12 &&
1769
0
                       at[cur].valence == 2);
1770
1771
0
                if (at[cur].sb_parity[0] && len <= 4 && i < cur /* count bonds only one time */)
1772
0
                {
1773
                    /* double bond, cumulene, or allene has been found */
1774
0
                    for (m2 = 0; m2 < MAX_NUM_STEREO_BONDS && at[cur].sb_parity[m2]; m2++)
1775
0
                    {
1776
0
                        if (chain[len - 2] == at[cur].neighbor[(int) at[cur].sb_ord[m2]])
1777
0
                        {
1778
0
                            if (n < num_inp_stereo0D)
1779
0
                            {
1780
0
                                int parity1 = at[i].sb_parity[m1];
1781
0
                                int parity2 = at[cur].sb_parity[m2];
1782
0
                                int parity;
1783
0
                                if (( INCHI_PARITY_ODD == parity1 || INCHI_PARITY_EVEN == parity1 ) &&
1784
0
                                    ( INCHI_PARITY_ODD == parity2 || INCHI_PARITY_EVEN == parity2 ))
1785
0
                                {
1786
                                    /* well-defined parity */
1787
0
                                    parity = ( parity1 == parity2 ) ? INCHI_PARITY_EVEN : INCHI_PARITY_ODD;
1788
0
                                }
1789
0
                                else
1790
0
                                {
1791
0
                                    parity = inchi_max( parity1, parity2 );
1792
0
                                }
1793
0
                                ( *stereo0D )[n].central_atom = ( len == 3 ) ? chain[1] : NO_ATOM;
1794
0
                                ( *stereo0D )[n].parity = parity;
1795
0
                                ( *stereo0D )[n].type = len == 3 ? INCHI_StereoType_Allene : INCHI_StereoType_DoubleBond;
1796
0
                                ( *stereo0D )[n].neighbor[0] = at[i].sn_orig_at_num[m1] - 1;
1797
0
                                ( *stereo0D )[n].neighbor[1] = i;
1798
0
                                ( *stereo0D )[n].neighbor[2] = cur;
1799
0
                                ( *stereo0D )[n].neighbor[3] = at[cur].sn_orig_at_num[m2] - 1;
1800
0
                                n++;
1801
0
                            }
1802
0
                            else
1803
0
                            {
1804
0
                                ret |= 1;
1805
0
                            }
1806
0
                            break;
1807
0
                        }
1808
0
                    }
1809
0
                }
1810
0
            }
1811
27.1k
        }
1812
27.1k
    }
1813
1814
15
    *num_stereo0D = n;
1815
1816
15
exit_function:
1817
15
    if (ret < 0)
1818
0
    {
1819
0
        if (*atom)
1820
0
        {
1821
0
            inchi_free( *atom );
1822
0
        }
1823
0
        if (*stereo0D)
1824
0
        {
1825
0
            inchi_free( *stereo0D );
1826
0
        }
1827
0
        *atom = NULL;
1828
0
        *stereo0D = NULL;
1829
0
        *num_atoms = 0;
1830
0
        *num_stereo0D = 0;
1831
0
    }
1832
1833
15
    return ret;
1834
15
}
1835
1836
1837
/****************************************************************************/
1838
int ExtractOneStructure( STRUCT_DATA *sd,
1839
                         INPUT_PARMS *ip,
1840
                         char *szTitle,
1841
                         inchi_InputEx *inp,
1842
                         INCHI_IOSTREAM *log_file,
1843
                         INCHI_IOSTREAM *out_file,
1844
                         INCHI_IOSTREAM *prb_file,
1845
                         ORIG_ATOM_DATA *orig_inp_data,
1846
                         long *num_inp )
1847
0
{
1848
0
    int         *err = &sd->nStructReadError;
1849
0
    char        *pStrErr = sd->pStrErrStruct;
1850
0
    inp_ATOM    *at = NULL;
1851
0
    MOL_COORD   *szCoord = NULL;
1852
0
    inchi_Atom  *ati = NULL;
1853
0
    int       nNumAtoms = 0;
1854
0
    int       a1, j, valence, nDim, nNumBonds, nRet = 0, max_num_at;
1855
1856
    /* vABParityUnknown holds actual value of an internal constant signifying       */
1857
    /* unknown parity: either the same as for undefined parity (default==standard)  */
1858
    /*  or a specific one (non-std; requested by SLUUD switch).                     */
1859
0
    int vABParityUnknown = AB_PARITY_UNDF;
1860
0
    if (0 != ( ip->nMode & REQ_MODE_DIFF_UU_STEREO ))
1861
0
    {
1862
        /* Make labels for unknown and undefined stereo different */
1863
0
        vABParityUnknown = AB_PARITY_UNKN;
1864
0
    }
1865
1866
    /********************************************************
1867
     *
1868
     *   Extract the structure
1869
     *
1870
     ********************************************************/
1871
1872
0
    FreeOrigAtData( orig_inp_data );
1873
0
    nDim = 0;
1874
0
    nNumBonds = 0;
1875
1876
0
    if (!inp || ( nNumAtoms = inp->num_atoms ) <= 0 || !( ati = inp->atom ))
1877
0
    {
1878
0
        TREAT_ERR( *err, 0, "Empty structure" );
1879
0
        *err = 98;
1880
0
        goto err_exit;
1881
0
    }
1882
1883
0
    max_num_at = ip->bLargeMolecules ? MAX_ATOMS : NORMALLY_ALLOWED_INP_MAX_ATOMS;
1884
0
    if (nNumAtoms >= max_num_at)
1885
0
    {
1886
0
        TREAT_ERR( *err, 0, "Too many atoms [did you forget 'LargeMolecules' switch?]" );
1887
0
        *err = 70;
1888
0
        orig_inp_data->num_inp_atoms = -1;
1889
0
        goto err_exit;
1890
0
    }
1891
1892
0
    at = (inp_ATOM  *) inchi_calloc( nNumAtoms, sizeof( at[0] ) );
1893
0
    szCoord = (MOL_COORD *) inchi_calloc( inchi_max( nNumAtoms, 1 ), sizeof( MOL_COORD ) );
1894
1895
0
    if (!at || !szCoord)
1896
0
    {
1897
0
        TREAT_ERR( *err, 0, "Out of RAM" );
1898
0
        *err = -1;
1899
0
        goto err_exit;
1900
0
    }
1901
1902
    /********************************************************
1903
     *
1904
     *   Extract typical for Molfile structural data
1905
     *
1906
     ********************************************************/
1907
    /* extract atoms and bonds */
1908
0
    for (a1 = 0; a1 < nNumAtoms; a1++)
1909
0
    {
1910
        /* extract atoms */
1911
0
        SetAtomProperties( at, szCoord, ati, a1, &nDim, pStrErr, err );
1912
1913
0
        if (*err)
1914
0
        {
1915
0
            goto err_exit;
1916
0
        }
1917
1918
        /* extract connections */
1919
0
        valence = ati[a1].num_bonds;
1920
0
        for (j = 0; j < valence; j++)
1921
0
        {
1922
0
            SetBondProperties( at, ati, a1, j, nNumAtoms, &nNumBonds, pStrErr, err );
1923
0
        }
1924
1925
0
        if (*err)
1926
0
        {
1927
0
            goto err_exit;
1928
0
        }
1929
0
    }
1930
1931
0
    orig_inp_data->num_inp_atoms = nNumAtoms;
1932
0
    orig_inp_data->num_inp_bonds = nNumBonds;
1933
0
    orig_inp_data->num_dimensions = nDim;
1934
1935
    /* extract elements, chemical valences, implicit H, isotopic shifts */
1936
0
    for (a1 = 0; a1 < nNumAtoms; a1++)
1937
0
    {
1938
        /* set temp flags in at[a1].at_type */
1939
        /* (1: data in atom name; 2: request to add H) */
1940
0
        SetAtomAndBondProperties( at,
1941
0
                                  ati,
1942
0
                                  a1,
1943
0
                                  ip->bDoNotAddH,
1944
0
                                  pStrErr,
1945
0
                                  err );
1946
0
        if (*err)
1947
0
        {
1948
0
            goto err_exit;
1949
0
        }
1950
0
    }
1951
1952
    /* clear temp flags in at[].at_type; add implicit H */
1953
0
    SetNumImplicitH( at, nNumAtoms );
1954
1955
0
    if (*err)
1956
0
    {
1957
0
        goto err_exit;
1958
0
    }
1959
1960
    /********************************************************
1961
     *
1962
     *   Extract the 0D parities (typical for CML)
1963
     *
1964
     ********************************************************/
1965
0
    Extract0DParities( at,
1966
0
                       nNumAtoms,
1967
0
                       inp->stereo0D,
1968
0
                       inp->num_stereo0D,
1969
0
                       pStrErr,
1970
0
                       err,
1971
0
                       vABParityUnknown );
1972
1973
0
    if (*err)
1974
0
    {
1975
0
        goto err_exit;
1976
0
    }
1977
1978
0
    orig_inp_data->at = at;
1979
0
    at = NULL;
1980
0
    orig_inp_data->num_dimensions = nDim;
1981
0
    orig_inp_data->num_inp_atoms = nNumAtoms;
1982
0
    orig_inp_data->num_inp_bonds = nNumBonds;
1983
0
    orig_inp_data->szCoord = szCoord;
1984
0
    szCoord = NULL;
1985
1986
    /* chiral flag */
1987
1988
    /* *****************************************************************************
1989
     * Chiral flags are set in:
1990
     * - ReadTheStructure() inchi-1, wInChI
1991
     * - e_IchiMain.c -- main()               -- C example of calling InChI dll
1992
     * - inchi_dll.c  ExtractOneStructure -- InChI dll code (here)
1993
     *******************************************************************************/
1994
1995
0
    if (( ip->nMode & REQ_MODE_CHIR_FLG_STEREO ) && ( ip->nMode & REQ_MODE_STEREO ))
1996
0
    {
1997
0
        if (ip->bChiralFlag & FLAG_SET_INP_AT_CHIRAL)
1998
0
        {
1999
            /* absolute stereo */
2000
0
            ip->nMode &= ~( REQ_MODE_RELATIVE_STEREO | REQ_MODE_RACEMIC_STEREO );
2001
0
            sd->bChiralFlag &= ~FLAG_INP_AT_NONCHIRAL;
2002
0
            sd->bChiralFlag |= FLAG_INP_AT_CHIRAL; /* write AuxInfo as chiral */
2003
0
        }
2004
0
        else
2005
        /*if ( ip->bChiralFlag & FLAG_SET_INP_AT_NONCHIRAL )*/
2006
0
        {
2007
            /* relative stereo */
2008
0
            ip->nMode &= ~( REQ_MODE_RACEMIC_STEREO );
2009
0
            ip->nMode |= REQ_MODE_RELATIVE_STEREO;
2010
0
            sd->bChiralFlag &= ~FLAG_INP_AT_CHIRAL;
2011
0
            sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL; /* write AuxInfo as non-chiral */
2012
0
        }
2013
0
    }
2014
0
    else if (ip->bChiralFlag & FLAG_SET_INP_AT_CHIRAL)
2015
0
    {
2016
0
        sd->bChiralFlag &= ~FLAG_INP_AT_NONCHIRAL;
2017
0
        sd->bChiralFlag |= FLAG_INP_AT_CHIRAL; /* write AuxInfo as chiral */
2018
0
    }
2019
0
    else if (ip->bChiralFlag & FLAG_SET_INP_AT_NONCHIRAL)
2020
0
    {
2021
0
        sd->bChiralFlag &= ~FLAG_INP_AT_CHIRAL;
2022
0
        sd->bChiralFlag |= FLAG_INP_AT_NONCHIRAL; /* write AuxInfo as non-chiral */
2023
0
    }
2024
2025
    /* v. 1.05 extensions  */
2026
0
    {
2027
0
        int res = SetExtOrigAtDataByInChIExtInput( &orig_inp_data->polymer,
2028
0
                                                   &orig_inp_data->v3000,
2029
0
                                                   inp->polymer,
2030
0
                                                   inp->v3000,
2031
0
                                                   orig_inp_data->num_inp_atoms );
2032
0
        if (res)
2033
0
        {
2034
0
            TREAT_ERR( res, 0, "General error on treating polymers" );
2035
0
            *err = -1;
2036
0
            goto err_exit;
2037
0
        }
2038
0
    }
2039
0
    *num_inp += 1;
2040
2041
0
err_exit:
2042
2043
0
    if (at)
2044
0
    {   /* if not moved to orig_inp_data/then nullified */
2045
0
        inchi_free( at );
2046
0
    }
2047
0
    if (szCoord)
2048
0
    {
2049
0
        inchi_free( szCoord );
2050
0
    }
2051
2052
0
    nRet = TreatErrorsInReadTheStructure( sd, ip, LOG_MASK_NO_WARN, NULL,
2053
0
                                          log_file, out_file, prb_file,
2054
0
                                          orig_inp_data, num_inp );
2055
2056
0
    return nRet;
2057
0
}
2058
2059
2060
/****************************************************************************/
2061
int INCHI_DECL GetStringLength( char *p )
2062
0
{
2063
0
    if (p)
2064
0
    {
2065
0
        return (int) strlen( p );
2066
0
    }
2067
0
    else
2068
0
    {
2069
0
        return 0;
2070
0
    }
2071
0
}
2072
2073
852
#define MAX_MSG_LEN 512
2074
2075
2076
/****************************************************************************
2077
 GetINCHIfromINCHI does same as -InChI2InChI option: converts InChI into
2078
 InChI for validation purposes
2079
 It may also be used to filter out specific layers. For instance,
2080
 /Snon would remove stereochemical layer
2081
 Omitting /FixedH and/or /RecMet would remove Fixed-H or Reconnected layers
2082
 To keep all InChI layers use options string "/FixedH /RecMet";
2083
 option /InChI2InChI is not needed
2084
 inchi_InputINCHI is created by the user;
2085
 strings in inchi_Output are allocated and deallocated by InChI
2086
 inchi_Output does not need to be initilized out to zeroes;
2087
 see FreeINCHI() on how to deallocate it
2088
****************************************************************************/
2089
int INCHI_DECL GetINCHIfromINCHI( inchi_InputINCHI *inpInChI,
2090
                                  inchi_Output *out )
2091
253
{
2092
253
    STRUCT_DATA struct_data;
2093
253
    STRUCT_DATA *sd = &struct_data;
2094
2095
253
    static char szMainOption[] = " ?InChI2InChI";
2096
2097
253
    INCHI_CLOCK ic;
2098
253
    CANON_GLOBALS CG;
2099
2100
253
    int i;
2101
253
    char      szSdfDataValue[MAX_SDF_VALUE + 1];
2102
253
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
2103
2104
253
    INPUT_PARMS inp_parms;
2105
253
    INPUT_PARMS *ip = &inp_parms;
2106
2107
253
    int             bReleaseVersion = bRELEASE_VERSION;
2108
253
    int   nRet = 0, nRet1;
2109
2110
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2111
    int  num_repeat = REPEAT_ALL;
2112
#endif
2113
2114
253
    const char *argv[INCHI_MAX_NUM_ARG + 1];
2115
253
    int   argc;
2116
253
    char *szOptions = NULL;
2117
2118
253
    INCHI_IOSTREAM inchi_file[3], *out_file = inchi_file, *log_file = inchi_file + 1, *input_file = inchi_file + 2;
2119
2120
#if( TRACE_MEMORY_LEAKS == 1 )
2121
    _CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF );
2122
/* for execution outside the VC++ debugger uncomment one of the following two */
2123
2124
#ifdef MY_REPORT_FILE
2125
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
2126
    _CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
2127
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
2128
    _CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
2129
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
2130
    _CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
2131
#else
2132
    _CrtSetReportMode( _CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG );
2133
#endif
2134
2135
    /* turn on floating point exceptions */
2136
#if ( !defined(__STDC__) || __STDC__ != 1 )
2137
    {
2138
        /* Get the default control word. */
2139
        int cw = _controlfp( 0, 0 );
2140
2141
        /* Set the exception masks OFF, turn exceptions on. */
2142
        /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
2143
        cw &= ~( EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL );
2144
2145
        /* Set the control word. */
2146
        _controlfp( cw, MCW_EM );
2147
    }
2148
#endif
2149
#endif
2150
2151
253
    memset( out, 0, sizeof( *out ) );
2152
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2153
repeat:
2154
    FreeINCHI( out );
2155
    inchi_ios_close( out_file );
2156
    inchi_ios_close( log_file );
2157
    inchi_ios_reset( input_file );  /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2158
#endif
2159
2160
    /* Initialize internal for this function I/O streams as string buffers */
2161
253
    inchi_ios_init( input_file, INCHI_IOS_TYPE_STRING, NULL );
2162
253
    inchi_ios_init( out_file, INCHI_IOS_TYPE_STRING, NULL );
2163
253
    inchi_ios_init( log_file, INCHI_IOS_TYPE_STRING, NULL );
2164
2165
253
    sd->bUserQuit = 0;
2166
2167
    /* clear original input structure */
2168
    /* memset( inchi_file, 0, sizeof(inchi_file) ); */
2169
253
    memset( sd, 0, sizeof( *sd ) );
2170
253
    memset( ip, 0, sizeof( *ip ) );
2171
253
    memset( szSdfDataValue, 0, sizeof( szSdfDataValue ) );
2172
2173
253
    memset( &ic, 0, sizeof( ic ) );
2174
253
    memset( &CG, 0, sizeof( CG ) );
2175
2176
253
    szMainOption[1] = INCHI_OPTION_PREFX;
2177
2178
253
    if (!inpInChI)
2179
0
    {
2180
0
        nRet = _IS_ERROR;
2181
0
        goto exit_function;
2182
0
    }
2183
2184
    /* options */
2185
253
    if (inpInChI)
2186
253
    {
2187
253
        int opt_len = (int) ( ( inpInChI->szOptions ? strlen( inpInChI->szOptions ) : 0 ) + sizeof( szMainOption ) + 1 );
2188
253
        szOptions = (char*) inchi_calloc( opt_len + 1, sizeof( szOptions[0] ) );
2189
253
        if (szOptions)
2190
253
        {
2191
253
            if (inpInChI->szOptions)
2192
0
            {
2193
0
                strcpy( szOptions, inpInChI->szOptions );
2194
0
            }
2195
253
            strcat( szOptions, szMainOption );
2196
253
            argc = parse_options_string( szOptions, argv, INCHI_MAX_NUM_ARG );
2197
253
        }
2198
0
        else
2199
0
        {
2200
0
            nRet = _IS_FATAL;
2201
0
            goto translate_RetVal; /* emergency exit */
2202
0
        }
2203
253
    }
2204
0
    else
2205
0
    {
2206
0
        argc = 1;
2207
0
        argv[0] = "";
2208
0
        argv[1] = NULL;
2209
0
    }
2210
2211
253
    if (argc == 1
2212
253
#ifdef TARGET_API_LIB
2213
253
        && ( !inpInChI || !inpInChI->szInChI )
2214
253
#endif
2215
2216
253
        || argc == 2 && ( argv[1][0] == INCHI_OPTION_PREFX ) &&
2217
253
        ( !strcmp( argv[1] + 1, "?" ) || !inchi_stricmp( argv[1] + 1, "help" ) ))
2218
0
    {
2219
0
        HelpCommandLineParms( log_file );
2220
0
        out->szLog = log_file->s.pStr;
2221
0
        memset( log_file, 0, sizeof( *log_file ) );
2222
0
        nRet = _IS_EOF;
2223
0
        goto translate_RetVal;
2224
0
    }
2225
2226
253
    nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue,
2227
253
                                &ulDisplTime, bReleaseVersion, log_file );
2228
2229
253
    if (szOptions)
2230
253
    {
2231
        /* argv pointed to strings in szOptions */
2232
253
        inchi_free( szOptions );
2233
253
        szOptions = NULL;
2234
253
    }
2235
    /* INChI DLL specific */
2236
253
    ip->bNoStructLabels = 1;
2237
2238
253
    if (0 > nRet1)
2239
0
    {
2240
0
        goto exit_function;
2241
0
    }
2242
2243
253
    if (ip->bNoStructLabels)
2244
253
    {
2245
253
        ip->pSdfLabel = NULL;
2246
253
        ip->pSdfValue = NULL;
2247
253
    }
2248
0
    else if (ip->nInputType == INPUT_INCHI_XML ||
2249
0
            ip->nInputType == INPUT_INCHI_PLAIN ||
2250
0
            ip->nInputType == INPUT_CMLFILE ||
2251
0
            ip->nInputType == INPUT_INCHI)
2252
0
    {
2253
        /* the input may contain both the header and the label of the structure */
2254
0
        if (!ip->pSdfLabel)
2255
0
        {
2256
0
            ip->pSdfLabel = ip->szSdfDataHeader;
2257
0
        }
2258
0
        if (!ip->pSdfValue)
2259
0
        {
2260
0
            ip->pSdfValue = szSdfDataValue;
2261
0
        }
2262
0
    }
2263
2264
253
    if (ip->nInputType && ip->nInputType != INPUT_INCHI)
2265
0
    {
2266
0
        inchi_ios_eprint( log_file, "Input type set to INPUT_INCHI\n" );
2267
0
        ip->nInputType = INPUT_INCHI;
2268
0
    }
2269
2270
253
    if (!inpInChI->szInChI)
2271
0
    {
2272
0
        nRet = _IS_ERROR;
2273
0
        goto exit_function;
2274
0
    }
2275
253
    else
2276
253
    {
2277
253
        const int strict = 0;
2278
253
        nRet = CheckINCHI( inpInChI->szInChI, strict );
2279
253
        if (nRet != INCHI_VALID_STANDARD     &&
2280
253
            nRet != INCHI_VALID_NON_STANDARD &&
2281
253
            nRet != INCHI_VALID_BETA)
2282
40
        {
2283
40
            nRet = _IS_ERROR;
2284
40
            goto exit_function;
2285
40
        }
2286
253
    }
2287
2288
2289
213
    PrintInputParms( log_file, ip );
2290
2291
    /********************************/
2292
    /* InChI -> InChI               */
2293
    /********************************/
2294
2295
    /* input_file simulation */
2296
213
    input_file->s.pStr = inpInChI->szInChI;
2297
213
    input_file->s.nUsedLength = (int) strlen( input_file->s.pStr ) + 1;
2298
213
    input_file->s.nAllocatedLength = input_file->s.nUsedLength;
2299
213
    input_file->s.nPtr = 0;
2300
2301
    /* buffer for the message */
2302
213
    out->szMessage = (char *) inchi_calloc( MAX_MSG_LEN, sizeof( out->szMessage[0] ) );
2303
213
    if (!out->szMessage)
2304
0
    {
2305
0
        inchi_ios_eprint( log_file, "Cannot allocate output message buffer.\n" );
2306
0
        nRet = -1;
2307
0
    }
2308
213
    else
2309
213
    {
2310
213
        nRet = ReadWriteInChI( &ic, &CG, input_file, out_file, log_file,
2311
213
                                ip, sd,
2312
213
                                NULL, 0, NULL,
2313
213
                                NULL, NULL,
2314
213
                                out->szMessage, MAX_MSG_LEN,
2315
213
                                NULL /*out->WarningFlags*/ );
2316
213
    }
2317
2318
213
    if (nRet >= 0 && out_file->s.pStr)
2319
72
    {
2320
        /* success */
2321
72
        char *p;
2322
72
        out->szInChI = out_file->s.pStr;
2323
72
        out->szAuxInfo = NULL;
2324
2325
72
        for (p = strchr( out->szInChI, '\n' ); p; p = strchr( p + 1, '\n' ))
2326
72
        {
2327
72
            if (!memcmp( p, "\nAuxInfo", 8 ))
2328
0
            {
2329
0
                *p = '\0';            /* remove LF after INChI */
2330
0
                out->szAuxInfo = p + 1; /* save pointer to AuxInfo */
2331
0
            }
2332
72
            else if (out->szAuxInfo || !p[1])
2333
72
            {
2334
                /* remove LF after aux info or from the last char */
2335
72
                *p = '\0';
2336
72
                break;
2337
72
            }
2338
72
        }
2339
72
        out_file->s.pStr = NULL;
2340
72
    }
2341
2342
    /*
2343
    out->szLog = log_file->pStr;
2344
    log_file->pStr   = NULL;
2345
    */
2346
2347
253
exit_function:;
2348
2349
1.26k
    for (i = 0; i < MAX_NUM_PATHS; i++)
2350
1.01k
    {
2351
1.01k
        if (ip->path[i])
2352
0
        {
2353
0
            inchi_free( (char*) ip->path[i] ); /*  cast deliberately discards 'const' qualifier */
2354
0
            ip->path[i] = NULL;
2355
0
        }
2356
1.01k
    }
2357
2358
253
    SetBitFree( &CG );
2359
2360
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2361
    if (num_repeat-- > 0)
2362
    {
2363
        goto repeat;
2364
    }
2365
#endif
2366
2367
253
#ifdef TARGET_API_LIB
2368
    /* output */
2369
2370
253
        if (log_file->s.pStr && log_file->s.nUsedLength > 0)
2371
213
        {
2372
570
            while (log_file->s.nUsedLength && '\n' == log_file->s.pStr[log_file->s.nUsedLength - 1])
2373
357
            {
2374
357
                log_file->s.pStr[--log_file->s.nUsedLength] = '\0'; /* remove last LF */
2375
357
            }
2376
213
            if (out)
2377
213
            {
2378
213
                out->szLog = log_file->s.pStr;
2379
213
                log_file->s.pStr = NULL;
2380
213
            }
2381
213
        }
2382
2383
253
#endif
2384
2385
253
translate_RetVal:
2386
2387
    /* close internal output streams */
2388
253
    inchi_ios_close( out_file );
2389
253
    inchi_ios_close( log_file );
2390
253
    inchi_ios_reset( input_file );  /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2391
2392
253
    switch (nRet)
2393
253
    {
2394
3
        case -3: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2395
116
        case -2: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2396
0
        case -1: nRet = inchi_Ret_FATAL; break; /* Severe error: no Structure has been created (typically; break; memory allocation failed) */
2397
134
        default:
2398
            /*
2399
            if ( !outStruct->atom || !outStruct->num_atoms )
2400
            {
2401
                nRet = inchi_Ret_EOF;
2402
            }
2403
            else
2404
            {
2405
                int m,n,t=0;
2406
                for ( m=0; m < 2; m ++ )
2407
                {
2408
                    for ( n=0; n < 2; n ++ )
2409
                    {
2410
                        if ( outStruct->WarningFlags[m][n] ) {
2411
                            t ++;
2412
                        }
2413
                    }
2414
                }
2415
                nRet = t? inchi_Ret_WARNING : inchi_Ret_OKAY;
2416
            }
2417
            */
2418
134
            break;
2419
253
    }
2420
2421
253
    return nRet;
2422
253
}
2423
2424
2425
/****************************************************************************
2426
2427
    GetStructFromStdINCHI
2428
2429
****************************************************************************/
2430
EXPIMP_TEMPLATE INCHI_API
2431
int INCHI_DECL GetStructFromStdINCHI( inchi_InputINCHI *inpInChI,
2432
                                      inchi_OutputStruct *outStruct )
2433
0
{
2434
0
    if (( inpInChI ) &&
2435
0
        ( inpInChI->szInChI ) &&
2436
0
        ( strlen( inpInChI->szInChI ) >= LEN_INCHI_STRING_PREFIX + 3 ) &&
2437
0
        ( inpInChI->szInChI[LEN_INCHI_STRING_PREFIX + 1] == 'S' ))
2438
0
    {
2439
         /* brief check indicated valid std input (more checks in GetStructFromINCHI) */
2440
0
        return GetStructFromINCHI( inpInChI, outStruct );
2441
0
    }
2442
0
    else
2443
0
    {
2444
        /* non-std or just invalid input */
2445
0
        return inchi_Ret_ERROR;
2446
0
    }
2447
0
}
2448
2449
2450
/****************************************************************************
2451
2452
    GetStructFromINCHIEx
2453
****************************************************************************/
2454
EXPIMP_TEMPLATE INCHI_API
2455
int INCHI_DECL GetStructFromINCHIEx( inchi_InputINCHI *inpInChI,
2456
                                     inchi_OutputStructEx *outStruct )
2457
253
{
2458
253
    INCHI_CLOCK ic;
2459
253
    CANON_GLOBALS CG;
2460
253
    STRUCT_DATA struct_data;
2461
253
    STRUCT_DATA *sd = &struct_data;
2462
253
    INPUT_PARMS inp_parms;
2463
253
    INPUT_PARMS *ip = &inp_parms;
2464
253
    INCHI_IOSTREAM inchi_file[3];
2465
253
    INCHI_IOSTREAM *out_file = inchi_file, *log_file = inchi_file + 1, *input_file = inchi_file + 2;
2466
253
    int    i, nRet = 0, nRet1;
2467
253
    int bStdFormat = 0;
2468
253
    int bReleaseVersion = bRELEASE_VERSION;
2469
253
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
2470
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2471
    int  num_repeat = REPEAT_ALL;
2472
#endif
2473
253
    static char szMainOption[] = " ?InChI2Struct";
2474
253
    char szSdfDataValue[MAX_SDF_VALUE + 1];
2475
253
    const char *argv[INCHI_MAX_NUM_ARG + 1];
2476
253
    int   argc;
2477
253
    char *szOptions = NULL;
2478
    /* conversion result */
2479
253
    inp_ATOM *at = NULL;
2480
253
    int num_at = 0;
2481
253
    OAD_Polymer *polymer = NULL;
2482
253
    OAD_V3000    *v3000 = NULL;
2483
2484
#if( TRACE_MEMORY_LEAKS == 1 )
2485
    _CrtSetDbgFlag( _CRTDBG_CHECK_ALWAYS_DF | _CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF );
2486
2487
/* for execution outside the VC++ debugger uncomment one of the following two */
2488
#ifdef MY_REPORT_FILE
2489
    _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE );
2490
    _CrtSetReportFile( _CRT_WARN, MY_REPORT_FILE );
2491
    _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE );
2492
    _CrtSetReportFile( _CRT_ERROR, MY_REPORT_FILE );
2493
    _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE );
2494
    _CrtSetReportFile( _CRT_ASSERT, MY_REPORT_FILE );
2495
#else
2496
    _CrtSetReportMode( _CRT_WARN | _CRT_ERROR, _CRTDBG_MODE_DEBUG );
2497
#endif
2498
2499
    /* turn on floating point exceptions */
2500
#if ( !defined(__STDC__) || __STDC__ != 1 )
2501
    {
2502
        /* Get the default control word. */
2503
        int cw = _controlfp( 0, 0 );
2504
2505
        /* Set the exception masks OFF, turn exceptions on. */
2506
        /*cw &=~(EM_OVERFLOW|EM_UNDERFLOW|EM_INEXACT|EM_ZERODIVIDE|EM_DENORMAL);*/
2507
        cw &= ~( EM_OVERFLOW | EM_UNDERFLOW | EM_ZERODIVIDE | EM_DENORMAL );
2508
2509
        /* Set the control word. */
2510
        _controlfp( cw, MCW_EM );
2511
    }
2512
#endif
2513
#endif
2514
2515
253
    memset( outStruct, 0, sizeof( *outStruct ) );
2516
2517
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2518
    repeat:
2519
    FreeStructFromINCHI( &outStruct );
2520
    inchi_ios_reset( input_file );  /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2521
    inchi_ios_close( out_file );
2522
    inchi_ios_close( log_file );
2523
#endif
2524
2525
253
    sd->bUserQuit = 0;
2526
2527
    /* Initialize internal for this function I/O streams as string buffers */
2528
253
    inchi_ios_init( input_file, INCHI_IOS_TYPE_STRING, NULL );
2529
253
    inchi_ios_init( out_file, INCHI_IOS_TYPE_STRING, NULL );
2530
253
    inchi_ios_init( log_file, INCHI_IOS_TYPE_STRING, NULL );
2531
2532
    /* clear original input structure */
2533
253
    memset( sd, 0, sizeof( *sd ) );
2534
253
    memset( ip, 0, sizeof( *ip ) );
2535
253
    memset( szSdfDataValue, 0, sizeof( szSdfDataValue ) );
2536
2537
253
    memset( &ic, 0, sizeof( ic ) );
2538
253
    memset( &CG, 0, sizeof( CG ) );
2539
2540
253
    szMainOption[1] = INCHI_OPTION_PREFX;
2541
2542
253
    if (!inpInChI)
2543
0
    {
2544
0
        nRet = _IS_ERROR;
2545
0
        goto exit_function;
2546
0
    }
2547
2548
    /* options */
2549
253
    if (inpInChI /*&& inpInChI->szOptions*/)
2550
253
    {
2551
        /* fix bug discovered by Burt Leland 2008-12-23 */
2552
253
        int opt_len = ( inpInChI->szOptions ? strlen( inpInChI->szOptions ) : 0 ) + sizeof( szMainOption ) + 1;
2553
253
        szOptions = (char*) inchi_calloc( opt_len + 1, sizeof( szOptions[0] ) );
2554
253
        if (szOptions)
2555
253
        {
2556
253
            if (inpInChI->szOptions)
2557
                /* fix bug discovered by Burt Leland 2008-12-23 */
2558
0
                strcpy( szOptions, inpInChI->szOptions );
2559
253
            strcat( szOptions, szMainOption );
2560
253
            argc = parse_options_string( szOptions, argv, INCHI_MAX_NUM_ARG );
2561
253
        }
2562
0
        else
2563
0
        {
2564
0
            nRet = _IS_FATAL;
2565
0
            goto translate_RetVal; /* emergency exit */
2566
0
        }
2567
253
    }
2568
0
    else
2569
0
    {
2570
0
        argc = 1;
2571
0
            argv[0] = "";
2572
0
        argv[1] = NULL;
2573
0
    }
2574
2575
253
    if (argc == 1
2576
253
#ifdef TARGET_API_LIB
2577
253
        && ( !inpInChI || !inpInChI->szInChI )
2578
253
#endif
2579
253
        || argc == 2 && ( argv[1][0] == INCHI_OPTION_PREFX ) &&
2580
253
        ( !strcmp( argv[1] + 1, "?" ) || !inchi_stricmp( argv[1] + 1, "help" ) ))
2581
0
    {
2582
0
        HelpCommandLineParms( log_file );
2583
0
        outStruct->szLog = log_file->s.pStr;
2584
0
        nRet = _IS_EOF;
2585
0
        goto translate_RetVal;
2586
0
    }
2587
2588
253
    nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue,
2589
253
                                  &ulDisplTime, bReleaseVersion,
2590
253
                                  log_file );
2591
2592
253
    if (szOptions)
2593
253
    {
2594
        /* argv pointed to strings in szOptions */
2595
253
        inchi_free( szOptions );
2596
253
        szOptions = NULL;
2597
253
    }
2598
2599
    /* INChI DLL specific */
2600
253
    ip->bNoStructLabels = 1;
2601
2602
253
    if (0 > nRet1)
2603
0
    {
2604
0
        goto exit_function;
2605
0
    }
2606
2607
253
    if (ip->bNoStructLabels)
2608
253
    {
2609
253
        ip->pSdfLabel = NULL;
2610
253
        ip->pSdfValue = NULL;
2611
253
    }
2612
0
    else if (ip->nInputType == INPUT_INCHI_XML ||
2613
0
            ip->nInputType == INPUT_INCHI_PLAIN ||
2614
0
            ip->nInputType == INPUT_CMLFILE ||
2615
0
            ip->nInputType == INPUT_INCHI)
2616
0
    {
2617
        /* the input may contain both the header and the label of the structure */
2618
0
        if (!ip->pSdfLabel)
2619
0
            ip->pSdfLabel = ip->szSdfDataHeader;
2620
0
        if (!ip->pSdfValue)
2621
0
            ip->pSdfValue = szSdfDataValue;
2622
0
    }
2623
2624
253
    if (ip->nInputType && ip->nInputType != INPUT_INCHI)
2625
0
    {
2626
0
        inchi_ios_eprint( log_file, "Input type set to INPUT_INCHI\n" );
2627
0
        ip->nInputType = INPUT_INCHI;
2628
0
    }
2629
2630
253
    if (!inpInChI->szInChI)
2631
0
    {
2632
0
        nRet = _IS_ERROR;
2633
0
        goto exit_function;
2634
0
    }
2635
253
    else
2636
253
    {
2637
253
        const int strict = 0;                     /* do not use strict mode, it may be too alarmous */
2638
253
        nRet = CheckINCHI( inpInChI->szInChI, strict );
2639
253
        if (nRet == INCHI_VALID_STANDARD)
2640
0
        {
2641
0
            bStdFormat = 1;
2642
0
        }
2643
253
        else if (nRet == INCHI_VALID_NON_STANDARD || nRet == INCHI_VALID_BETA)
2644
213
        {
2645
213
            ;
2646
213
        }
2647
40
        else
2648
40
        {
2649
40
            nRet = _IS_ERROR;
2650
40
            goto exit_function;
2651
40
        }
2652
253
    }
2653
2654
213
    PrintInputParms( log_file, ip );
2655
2656
    /*********************************/
2657
    /* InChI -> Structure conversion */
2658
    /*********************************/
2659
2660
    /* input_file simulation */
2661
2662
    /*
2663
    that was incorrect simulation, and correct one is much simpler, see below
2664
    input_file->s.pStr = inpInChI->szInChI;
2665
    input_file->s.nUsedLength = (int) strlen(input_file->s.pStr)+1;
2666
    input_file->s.nAllocatedLength = input_file->s.nUsedLength;
2667
    input_file->s.nPtr = 0;
2668
    */
2669
213
    inchi_ios_print_nodisplay( input_file, inpInChI->szInChI );
2670
2671
    /* buffer for the message */
2672
    /* outStruct->szMessage = (char *)inchi_calloc( MAX_MSG_LEN, sizeof(outStruct->szMessage[0])); */
2673
2674
213
    outStruct->szMessage = (char *) inchi_calloc( MAX_MSG_LEN, sizeof( char ) );
2675
213
    if (!outStruct->szMessage)
2676
0
    {
2677
0
        inchi_ios_eprint( log_file, "Cannot allocate output message buffer.\n" );
2678
0
        nRet = -1;
2679
0
    }
2680
213
    else
2681
213
    {
2682
213
        int num_bonds;
2683
213
        nRet = ReadWriteInChI( &ic, &CG , input_file, out_file, log_file,
2684
213
                                ip, sd, &at, &num_at, &num_bonds,
2685
213
                                &polymer, &v3000,
2686
213
                                outStruct->szMessage,
2687
213
                                MAX_MSG_LEN, outStruct->WarningFlags );
2688
2689
213
        if (nRet >= 0 && polymer)
2690
0
        {
2691
0
            OAD_Polymer_SmartReopenCyclizedUnits( polymer, at,
2692
0
                                                 num_at, &num_bonds );
2693
0
        }
2694
213
    }
2695
2696
213
    if (nRet >= 0 && at && num_at)
2697
15
    {
2698
        /* success */
2699
15
        nRet = InpAtom0DToInchiAtom( at, num_at,
2700
15
                                    &outStruct->num_atoms,
2701
15
                                    &outStruct->atom,
2702
15
                                    &outStruct->num_stereo0D,
2703
15
                                    &outStruct->stereo0D );
2704
2705
15
        if (at)
2706
15
        {
2707
15
            inchi_free( at );
2708
15
            at = NULL;
2709
15
        }
2710
2711
15
        if (nRet >= 0 && polymer)
2712
0
        {
2713
            /* Check for and then replace ZZ for star atoms if Polymer extension is supplied */
2714
0
            for (i = 0; i < outStruct->num_atoms; i++)
2715
0
            {
2716
0
                if (!strcmp( outStruct->atom[i].elname, "Zz" ))
2717
0
                {
2718
0
                    strcpy( outStruct->atom[i].elname, "*" );
2719
0
                }
2720
0
            }
2721
0
        }
2722
2723
15
        if (nRet >= 0)
2724
15
        {
2725
15
            if (polymer || v3000)
2726
0
            {
2727
0
                nRet = SetInChIExtInputByExtOrigAtData( polymer, v3000,
2728
0
                                                        &outStruct->polymer,
2729
0
                                                        &outStruct->v3000,
2730
0
                                                        outStruct->num_atoms ); /* pair to SetExtOrigAtDataByInChIExtInput */
2731
0
                FreeExtOrigAtData( polymer, v3000 );
2732
0
                polymer = NULL;
2733
0
                v3000 = NULL;
2734
0
            }
2735
15
        }
2736
15
        if (nRet < 0)
2737
0
        {
2738
0
            inchi_ios_eprint( log_file, "Final structure conversion failed\n" );
2739
0
        }
2740
15
    }
2741
213
    outStruct->szLog = log_file->s.pStr;
2742
2743
253
exit_function:;
2744
2745
1.26k
    for (i = 0; i < MAX_NUM_PATHS; i++)
2746
1.01k
    {
2747
1.01k
        if (ip->path[i])
2748
0
        {
2749
0
            inchi_free( (char*) ip->path[i] ); /*  cast deliberately discards 'const' qualifier */
2750
0
            ip->path[i] = NULL;
2751
0
        }
2752
1.01k
    }
2753
2754
253
    SetBitFree( &CG );
2755
2756
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2757
    if (num_repeat-- > 0)
2758
    {
2759
        goto repeat;
2760
    }
2761
#endif
2762
2763
253
#ifdef TARGET_API_LIB
2764
    /* output */
2765
253
    if (log_file->s.pStr && log_file->s.nUsedLength > 0)
2766
213
    {
2767
426
        while (log_file->s.nUsedLength &&
2768
426
                '\n' == log_file->s.pStr[log_file->s.nUsedLength - 1])
2769
213
        {
2770
213
            log_file->s.pStr[--log_file->s.nUsedLength] = '\0'; /* remove last LF */
2771
213
        }
2772
213
        if (outStruct)
2773
213
        {
2774
213
            outStruct->szLog = log_file->s.pStr;
2775
213
            log_file->s.pStr = NULL;
2776
213
        }
2777
213
    }
2778
253
#endif
2779
2780
253
translate_RetVal:
2781
2782
    /* Close internal I/O streams */
2783
    /* that was incorrect also
2784
    inchi_ios_reset(input_file);  */    /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2785
253
    inchi_ios_close( input_file );
2786
253
    inchi_ios_close( out_file );
2787
253
    inchi_ios_close( log_file );
2788
2789
253
    switch (nRet)
2790
253
    {
2791
63
        case -3: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2792
119
        case -2: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2793
0
        case -1: nRet = inchi_Ret_FATAL; break; /* Severe error: no Structure has been created (typically; break; memory allocation failed) */
2794
71
        default:
2795
71
            if (!outStruct->atom || !outStruct->num_atoms)
2796
56
            {
2797
56
                nRet = inchi_Ret_EOF;
2798
56
            }
2799
15
            else
2800
15
            {
2801
15
                int m, n, t = 0;
2802
45
                for (m = 0; m < 2; m++)
2803
30
                {
2804
90
                    for (n = 0; n < 2; n++)
2805
60
                    {
2806
60
                        if (outStruct->WarningFlags[m][n])
2807
15
                        {
2808
15
                            t++;
2809
15
                        }
2810
60
                    }
2811
30
                }
2812
15
                nRet = t ? inchi_Ret_WARNING : inchi_Ret_OKAY;
2813
15
            }
2814
71
            break;
2815
253
    }
2816
2817
253
    return nRet;
2818
253
}
2819
2820
2821
/****************************************************************************
2822
2823
    GetStructFromINCHI
2824
2825
****************************************************************************/
2826
EXPIMP_TEMPLATE INCHI_API
2827
int INCHI_DECL GetStructFromINCHI( inchi_InputINCHI *inpInChI,
2828
                                   inchi_OutputStruct *out )
2829
253
{
2830
253
    int ret = 0;
2831
2832
253
    inchi_OutputStructEx outex;
2833
253
    memset( out, 0, sizeof( *out ) );
2834
2835
253
    ret = GetStructFromINCHIEx( inpInChI, &outex );
2836
2837
253
    out->szLog = outex.szLog;
2838
253
    out->szMessage = outex.szMessage;
2839
253
    out->WarningFlags[0][0] = outex.WarningFlags[0][0];
2840
253
    out->WarningFlags[0][1] = outex.WarningFlags[0][1];
2841
253
    out->WarningFlags[1][0] = outex.WarningFlags[1][0];
2842
253
    out->WarningFlags[1][1] = outex.WarningFlags[1][1];
2843
2844
253
    if (ret == inchi_Ret_OKAY || ret == inchi_Ret_WARNING)
2845
15
    {
2846
15
        out->num_atoms = outex.num_atoms;
2847
15
        out->atom = outex.atom;
2848
15
        out->num_stereo0D = outex.num_stereo0D;
2849
15
        out->stereo0D = outex.stereo0D;
2850
15
    }
2851
2852
253
    return ret;
2853
253
}
2854
2855
2856
2857
/****************************************************************************
2858
2859
    FreeStructFromINCHIEx
2860
2861
****************************************************************************/
2862
EXPIMP_TEMPLATE INCHI_API
2863
void INCHI_DECL FreeStructFromINCHIEx( inchi_OutputStructEx *out )
2864
0
{
2865
0
    if (!out)
2866
0
        return;
2867
2868
0
    if (out->atom)
2869
0
    {
2870
0
        inchi_free( out->atom );
2871
0
    }
2872
0
    if (out->stereo0D)
2873
0
    {
2874
0
        inchi_free( out->stereo0D );
2875
0
    }
2876
0
    if (out->szLog)
2877
0
    {
2878
0
        inchi_free( out->szLog );
2879
0
    }
2880
0
    if (out->szMessage)
2881
0
    {
2882
0
        inchi_free( out->szMessage );
2883
0
    }
2884
0
    if (out->polymer || out->v3000)
2885
0
    {
2886
0
        FreeInChIExtInput( out->polymer, out->v3000 );
2887
0
    }
2888
2889
0
    memset( out, 0, sizeof( *out ) );
2890
0
}
2891
2892
2893
/****************************************************************************/
2894
void FreeInChIExtInput( inchi_Input_Polymer *polymer, inchi_Input_V3000 *v3000 )
2895
0
{
2896
0
    int k;
2897
0
    if (polymer)
2898
0
    {
2899
0
        if (polymer->n && polymer->units)
2900
0
        {
2901
0
            for (k = 0; k < polymer->n; k++)
2902
0
            {
2903
0
                if (polymer->units[k])
2904
0
                {
2905
0
                    if (polymer->units[k]->alist)
2906
0
                    {
2907
0
                        inchi_free( polymer->units[k]->alist );  polymer->units[k]->alist = NULL;
2908
0
                    }
2909
0
                    if (polymer->units[k]->blist)
2910
0
                    {
2911
0
                        inchi_free( polymer->units[k]->blist );  polymer->units[k]->blist = NULL;
2912
0
                    }
2913
0
                }
2914
0
                inchi_free( polymer->units[k] );
2915
0
            }
2916
0
            inchi_free( polymer->units );
2917
0
            polymer->units = NULL;
2918
0
            inchi_free( polymer );
2919
0
        }
2920
0
    }
2921
0
    if (v3000)
2922
0
    {
2923
0
        if (v3000->atom_index_orig)
2924
0
        {
2925
0
            inchi_free( v3000->atom_index_orig );
2926
0
            v3000->atom_index_orig = NULL;
2927
0
        }
2928
0
        if (v3000->atom_index_fin)
2929
0
        {
2930
0
            inchi_free( v3000->atom_index_fin );
2931
0
            v3000->atom_index_fin = NULL;
2932
0
        }
2933
0
        if (v3000->n_haptic_bonds && v3000->lists_haptic_bonds)
2934
0
        {
2935
0
            for (k = 0; k < v3000->n_haptic_bonds; k++)
2936
0
            {
2937
0
                if (v3000->lists_haptic_bonds[k])
2938
0
                {
2939
0
                    inchi_free( v3000->lists_haptic_bonds[k] );
2940
0
                    v3000->lists_haptic_bonds[k] = NULL;
2941
0
                }
2942
0
            }
2943
0
            inchi_free( v3000->lists_haptic_bonds );
2944
0
            v3000->lists_haptic_bonds = NULL;
2945
0
        }
2946
0
        if (v3000->n_steabs && v3000->lists_steabs)
2947
0
        {
2948
0
            for (k = 0; k < v3000->n_steabs; k++)
2949
0
            {
2950
0
                if (v3000->lists_steabs[k])
2951
0
                {
2952
0
                    inchi_free( v3000->lists_steabs[k] );
2953
0
                    v3000->lists_steabs[k] = NULL;
2954
0
                }
2955
0
            }
2956
0
            inchi_free( v3000->lists_steabs );
2957
0
            v3000->lists_steabs = NULL;
2958
0
        }
2959
0
        if (v3000->n_sterel && v3000->lists_sterel)
2960
0
        {
2961
0
            for (k = 0; k < v3000->n_sterel; k++)
2962
0
            {
2963
0
                if (v3000->lists_sterel[k])
2964
0
                {
2965
0
                    inchi_free( v3000->lists_sterel[k] );
2966
0
                    v3000->lists_sterel[k] = NULL;
2967
0
                }
2968
0
            }
2969
0
            inchi_free( v3000->lists_sterel );
2970
0
            v3000->lists_sterel = NULL;
2971
0
        }
2972
0
        if (v3000->n_sterac && v3000->lists_sterac)
2973
0
        {
2974
0
            for (k = 0; k < v3000->n_sterac; k++)
2975
0
            {
2976
0
                if (v3000->lists_sterac[k])
2977
0
                {
2978
0
                    inchi_free( v3000->lists_sterac[k] );
2979
0
                    v3000->lists_sterac[k] = NULL;
2980
0
                }
2981
0
            }
2982
0
            inchi_free( v3000->lists_sterac );
2983
0
            v3000->lists_sterac = NULL;
2984
0
        }
2985
0
        inchi_free( v3000 );
2986
        /*memset( v3000, 0, sizeof( *v3000 ) );*/
2987
0
    }
2988
0
}
2989
2990
2991
/****************************************************************************/
2992
int SetExtOrigAtDataByInChIExtInput( OAD_Polymer **ppPolymer,
2993
                                     OAD_V3000 **ppV3000,
2994
                                     inchi_Input_Polymer *iep,
2995
                                     inchi_Input_V3000 *iev,
2996
                                     int nat )
2997
0
{
2998
0
    int    k, m, err = 0;
2999
0
    OAD_V3000 *pv = NULL;
3000
3001
    /* Polymers */
3002
0
    if (iep && iep->n)
3003
0
    {
3004
        /* Prepare OAD_Polymer container */
3005
0
        *ppPolymer = (OAD_Polymer *) inchi_calloc( 1, sizeof( OAD_Polymer ) );
3006
0
        if (!*ppPolymer)
3007
0
        {
3008
0
            err = 9001;
3009
0
            goto exitf;
3010
0
        }
3011
3012
        /* Convert Molfile's Sgroup's to OAD_PolymerUnit's */
3013
0
        ( *ppPolymer )->units = (OAD_PolymerUnit**) inchi_calloc( iep->n, sizeof( ( *ppPolymer )->units[0] ) );
3014
0
        if (!( *ppPolymer )->units)
3015
0
        {
3016
0
            err = 9001;
3017
0
            goto exitf;
3018
0
        }
3019
0
        memset( ( *ppPolymer )->units, 0, sizeof( *( *ppPolymer )->units ) );
3020
3021
0
        ( *ppPolymer )->n = iep->n;
3022
        /*( *ppPolymer )->valid = -1;*/
3023
0
        ( *ppPolymer )->really_do_frame_shift = 0;
3024
3025
0
        for (k = 0; k < iep->n; k++)
3026
0
        {
3027
0
            int q = 0;
3028
0
            OAD_PolymerUnit *unitk;
3029
3030
0
            inchi_Input_PolymerUnit *groupk = iep->units[k];
3031
0
            ( *ppPolymer )->units[k] = (OAD_PolymerUnit*) inchi_calloc( 1, sizeof( OAD_PolymerUnit ) );
3032
0
            unitk = ( *ppPolymer )->units[k];
3033
0
            if (!unitk)
3034
0
            {
3035
0
                err = 9001;
3036
0
                goto exitf;
3037
0
            }
3038
3039
0
            memset( unitk, 0, sizeof( *unitk ) );
3040
0
            unitk->id = groupk->id;
3041
0
            unitk->type = groupk->type;
3042
0
            unitk->subtype = groupk->subtype;
3043
0
            unitk->conn = groupk->conn;
3044
0
            unitk->label = groupk->label;
3045
3046
0
            for (q = 0; q < 4; q++)
3047
0
            {
3048
0
                unitk->xbr1[q] = groupk->xbr1[q];
3049
0
                unitk->xbr2[q] = groupk->xbr2[q];
3050
0
            }
3051
0
            strcpy( unitk->smt, groupk->smt );
3052
0
            unitk->na = groupk->na;
3053
0
            unitk->alist = (int *) inchi_calloc( unitk->na, sizeof( int ) );
3054
0
            if (!unitk->alist )
3055
0
            {
3056
0
                err = 9001;
3057
0
                goto exitf;
3058
0
            }
3059
0
            for (m = 0; m < unitk->na; m++)
3060
0
            {
3061
0
                unitk->alist[m] = groupk->alist[m];
3062
0
            }
3063
0
            unitk->nb = groupk->nb;
3064
0
            if (unitk->nb > 0)
3065
0
            {
3066
0
                unitk->blist = (int *) inchi_calloc( 2 * unitk->nb, sizeof( int ) );
3067
0
                if (!unitk->blist )
3068
0
                {
3069
0
                    err = 9001;
3070
0
                    goto exitf;
3071
0
                }
3072
0
                for (m = 0; m < 2 * groupk->nb; m++)
3073
0
                {
3074
0
                    unitk->blist[m] = groupk->blist[m];
3075
0
                }
3076
0
            }
3077
0
            else
3078
0
            {
3079
0
                unitk->blist = NULL;
3080
0
            }
3081
0
        }
3082
0
    }
3083
3084
    /* V3000 Extensions */
3085
0
    if (iev)
3086
0
    {
3087
0
        int nn;
3088
0
        *ppV3000 = (OAD_V3000 *) inchi_calloc( 1, sizeof( OAD_V3000 ) );
3089
0
        pv = *ppV3000;
3090
0
        if (!pv)
3091
0
        {
3092
0
            err = 9001;
3093
0
            goto exitf;
3094
0
        }
3095
0
        memset( pv, 0, sizeof( *pv ) );
3096
3097
0
        pv->n_collections = iev->n_collections;
3098
0
        pv->n_haptic_bonds = iev->n_haptic_bonds;
3099
0
        pv->n_non_haptic_bonds = iev->n_non_haptic_bonds;
3100
0
        pv->n_sgroups = iev->n_sgroups;
3101
0
        pv->n_non_star_atoms = iev->n_non_star_atoms;
3102
0
        pv->n_star_atoms = iev->n_star_atoms;
3103
0
        pv->n_steabs = iev->n_steabs;
3104
0
        pv->n_sterac = iev->n_sterac;
3105
0
        pv->n_sterel = iev->n_sterel;
3106
0
        pv->n_3d_constraints = iev->n_3d_constraints;
3107
3108
0
        if (iev->atom_index_orig)
3109
0
        {
3110
0
            pv->atom_index_orig = (int *) inchi_calloc( nat, sizeof( int ) );
3111
0
            if (NULL == pv->atom_index_orig)
3112
0
            {
3113
0
                err = 9001;
3114
0
                goto exitf;
3115
0
            }
3116
0
            memcpy( pv->atom_index_orig, iev->atom_index_orig, nat );
3117
0
        }
3118
0
        if (iev->atom_index_fin)
3119
0
        {
3120
0
            pv->atom_index_fin = (int *) inchi_calloc( nat, sizeof( int ) );
3121
0
            if (NULL == pv->atom_index_fin)
3122
0
            {
3123
0
                err = 9001;
3124
0
                goto exitf;
3125
0
            }
3126
0
            memcpy( pv->atom_index_fin, iev->atom_index_fin, nat );
3127
0
        }
3128
0
        if (iev->n_haptic_bonds && iev->lists_haptic_bonds)
3129
0
        {
3130
0
            pv->lists_haptic_bonds = (int **) inchi_calloc( iev->n_haptic_bonds, sizeof( int* ) );
3131
0
            if (NULL == pv->lists_haptic_bonds)
3132
0
            {
3133
0
                err = 9001;
3134
0
                goto exitf;
3135
0
            }
3136
0
            for (m = 0; m < iev->n_haptic_bonds; m++)
3137
0
            {
3138
0
                int *lst = NULL;
3139
0
                int *mol_lst = iev->lists_haptic_bonds[m];
3140
0
                nn = mol_lst[2] + 3;
3141
0
                lst = pv->lists_haptic_bonds[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3142
0
                if (NULL == lst)
3143
0
                {
3144
0
                    err = 9001;
3145
0
                    goto exitf;
3146
0
                }
3147
0
                for (k = 0; k < nn; k++)
3148
0
                {
3149
0
                    lst[k] = mol_lst[k];
3150
0
                }
3151
0
            }
3152
0
        }
3153
0
        if (iev->n_steabs && iev->lists_steabs)
3154
0
        {
3155
0
            pv->lists_steabs = (int **) inchi_calloc( iev->n_steabs, sizeof( int* ) );
3156
0
            if (NULL == pv->lists_steabs) { err = 9001; goto exitf; }
3157
0
            for (m = 0; m < iev->n_steabs; m++)
3158
0
            {
3159
0
                int *lst = NULL;
3160
0
                int *mol_lst = iev->lists_steabs[m];
3161
0
                nn = mol_lst[1] + 2;
3162
0
                lst = pv->lists_steabs[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3163
0
                if (NULL == lst)
3164
0
                {
3165
0
                    err = 9001;
3166
0
                    goto exitf;
3167
0
                }
3168
0
                for (k = 0; k < nn; k++)
3169
0
                {
3170
0
                    lst[k] = mol_lst[k];
3171
0
                }
3172
0
            }
3173
0
        }
3174
0
        if (iev->n_sterac && iev->lists_sterac)
3175
0
        {
3176
0
            pv->lists_sterac = (int **) inchi_calloc( iev->n_sterac, sizeof( int* ) );
3177
0
            if (NULL == pv->lists_sterac) { err = 9001; goto exitf; }
3178
0
            for (m = 0; m < iev->n_sterac; m++)
3179
0
            {
3180
0
                int *lst = NULL;
3181
0
                int *mol_lst = iev->lists_sterac[m];
3182
0
                nn = mol_lst[1] + 2;
3183
0
                lst = pv->lists_sterac[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3184
0
                if (NULL == lst)
3185
0
                {
3186
0
                    err = 9001;
3187
0
                    goto exitf;
3188
0
                }
3189
0
                for (k = 0; k < nn; k++)
3190
0
                {
3191
0
                    lst[k] = mol_lst[k];
3192
0
                }
3193
0
            }
3194
0
        }
3195
0
        if (iev->n_sterel && iev->lists_sterel)
3196
0
        {
3197
0
            pv->lists_sterel = (int **) inchi_calloc( iev->n_sterel, sizeof( int* ) );
3198
0
            if (NULL == pv->lists_sterel) { err = 9001; goto exitf; }
3199
0
            for (m = 0; m < iev->n_sterel; m++)
3200
0
            {
3201
0
                int *lst = NULL;
3202
0
                int *mol_lst = iev->lists_sterel[m];
3203
0
                nn = mol_lst[1] + 2;
3204
0
                lst = pv->lists_sterel[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3205
0
                if (NULL == lst)
3206
0
                {
3207
0
                    err = 9001;
3208
0
                    goto exitf;
3209
0
                }
3210
0
                for (k = 0; k < nn; k++)
3211
0
                {
3212
0
                    lst[k] = mol_lst[k];
3213
0
                }
3214
0
            }
3215
0
        }
3216
0
    }
3217
3218
0
exitf:
3219
0
    if (err)
3220
0
    {
3221
0
        FreeExtOrigAtData( *ppPolymer, pv );
3222
0
    }
3223
3224
0
    return err;
3225
0
}
3226
3227
3228
/****************************************************************************/
3229
int SetInChIExtInputByExtOrigAtData( OAD_Polymer     *orp,
3230
                                     OAD_V3000     *orv,
3231
                                     inchi_Input_Polymer **iip,
3232
                                     inchi_Input_V3000     **iiv,
3233
                                     int nat )
3234
0
{
3235
0
    int    k, m, err = 0;
3236
3237
        /* Polymers */
3238
0
    if (orp && orp->n > 0)
3239
0
    {
3240
0
        *iip = (inchi_Input_Polymer *) inchi_calloc( 1, sizeof( inchi_Input_Polymer ) );
3241
0
        if (!*iip)
3242
0
        {
3243
0
            err = 9001;
3244
0
            goto exitf;
3245
0
        }
3246
0
        ( *iip )->n = orp->n;
3247
0
        ( *iip )->units = (inchi_Input_PolymerUnit**) inchi_calloc( orp->n, sizeof( ( *iip )->units[0] ) );
3248
0
        if (!( *iip )->units)
3249
0
        {
3250
0
            err = 9001; goto exitf;
3251
0
        }
3252
0
        memset( ( *iip )->units, 0, sizeof( *( *iip )->units ) );
3253
0
        for (k = 0; k < orp->n; k++)
3254
0
        {
3255
0
            int q = 0;
3256
0
            inchi_Input_PolymerUnit *unitk;
3257
0
            OAD_PolymerUnit    *groupk = orp->units[k];
3258
0
            ( *iip )->units[k] = (inchi_Input_PolymerUnit*) inchi_calloc( 1, sizeof( inchi_Input_PolymerUnit ) );
3259
0
            unitk = ( *iip )->units[k];
3260
0
            if (!unitk)
3261
0
            {
3262
0
                err = 9001; goto exitf;
3263
0
            }
3264
0
            memset( unitk, 0, sizeof( *unitk ) );
3265
0
            unitk->id = groupk->id;
3266
0
            unitk->type = groupk->type;
3267
0
            unitk->subtype = groupk->subtype;
3268
0
            unitk->conn = groupk->conn;
3269
0
            unitk->label = groupk->label;
3270
0
            for (q = 0; q < 4; q++)
3271
0
            {
3272
0
                unitk->xbr1[q] = groupk->xbr1[q];
3273
0
                unitk->xbr2[q] = groupk->xbr2[q];
3274
0
            }
3275
0
            strcpy( unitk->smt, groupk->smt );
3276
0
            unitk->na = groupk->na;
3277
0
            unitk->alist = (int *) inchi_calloc( unitk->na, sizeof( int ) );
3278
0
            if (!unitk->alist)
3279
0
            {
3280
0
                err = 9001; goto exitf;
3281
0
            }
3282
0
            for (m = 0; m < unitk->na; m++)
3283
0
            {
3284
0
                unitk->alist[m] = groupk->alist[m];
3285
0
            }
3286
0
            unitk->nb = groupk->nb;
3287
0
            if (unitk->nb > 0)
3288
0
            {
3289
0
                unitk->blist = (int *) inchi_calloc( 2 * unitk->nb, sizeof( int ) );
3290
0
                if (!unitk->blist)
3291
0
                {
3292
0
                    err = 9001; goto exitf;
3293
0
                }
3294
0
                for (m = 0; m < 2 * groupk->nb; m++)
3295
0
                {
3296
0
                    unitk->blist[m] = groupk->blist[m];
3297
0
                }
3298
0
            }
3299
0
            else
3300
0
            {
3301
0
                unitk->blist = NULL;
3302
0
            }
3303
0
        }
3304
0
    }
3305
3306
0
    if (orv)
3307
0
    {
3308
0
        int nn;
3309
0
        *iiv = (inchi_Input_V3000 *) inchi_calloc( 1, sizeof( OAD_V3000 ) );
3310
0
        if (!*iiv)
3311
0
        {
3312
0
            err = 9001; goto exitf;
3313
0
        }
3314
0
        memset( *iiv, 0, sizeof( **iiv ) );
3315
3316
0
        ( *iiv )->n_collections = orv->n_collections;
3317
0
        ( *iiv )->n_haptic_bonds = orv->n_haptic_bonds;
3318
0
        ( *iiv )->n_non_haptic_bonds = orv->n_non_haptic_bonds;
3319
0
        ( *iiv )->n_sgroups = orv->n_sgroups;
3320
0
        ( *iiv )->n_non_star_atoms = orv->n_non_star_atoms;
3321
0
        ( *iiv )->n_star_atoms = orv->n_star_atoms;
3322
0
        ( *iiv )->n_steabs = orv->n_steabs;
3323
0
        ( *iiv )->n_sterac = orv->n_sterac;
3324
0
        ( *iiv )->n_sterel = orv->n_sterel;
3325
0
        ( *iiv )->n_3d_constraints = orv->n_3d_constraints;
3326
3327
0
        if (orv->atom_index_orig)
3328
0
        {
3329
0
            ( *iiv )->atom_index_orig = (int *) inchi_calloc( nat, sizeof( int ) );
3330
0
            if (NULL == ( *iiv )->atom_index_orig)
3331
0
            {
3332
0
                err = 9001;
3333
0
                goto exitf;
3334
0
            }
3335
0
            memcpy( ( *iiv )->atom_index_orig, orv->atom_index_orig, nat );
3336
0
        }
3337
0
        if (orv->atom_index_fin)
3338
0
        {
3339
0
            ( *iiv )->atom_index_fin = (int *) inchi_calloc( nat, sizeof( int ) );
3340
0
            if (NULL == ( *iiv )->atom_index_fin)
3341
0
            {
3342
0
                err = 9001;
3343
0
                goto exitf;
3344
0
            }
3345
0
            memcpy( ( *iiv )->atom_index_fin, orv->atom_index_fin, nat );
3346
0
        }
3347
0
        if (orv->n_haptic_bonds && orv->lists_haptic_bonds)
3348
0
        {
3349
0
            ( *iiv )->lists_haptic_bonds = (int **) inchi_calloc( orv->n_haptic_bonds, sizeof( int* ) );
3350
0
            if (NULL == ( *iiv )->lists_haptic_bonds)
3351
0
            {
3352
0
                err = 9001;
3353
0
                goto exitf;
3354
0
            }
3355
0
            for (m = 0; m < orv->n_haptic_bonds; m++)
3356
0
            {
3357
0
                int *lst = NULL;
3358
0
                int *mol_lst = orv->lists_haptic_bonds[m];
3359
0
                nn = mol_lst[2] + 3;
3360
0
                lst = ( *iiv )->lists_haptic_bonds[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3361
0
                if (NULL == lst)
3362
0
                {
3363
0
                    err = 9001;
3364
0
                    goto exitf;
3365
0
                }
3366
0
                for (k = 0; k < nn; k++)
3367
0
                {
3368
0
                    lst[k] = mol_lst[k];
3369
0
                }
3370
0
            }
3371
0
        }
3372
0
        if (orv->n_steabs && orv->lists_steabs)
3373
0
        {
3374
0
            ( *iiv )->lists_steabs = (int **) inchi_calloc( orv->n_steabs, sizeof( int* ) );
3375
0
            if (NULL == ( *iiv )->lists_steabs) { err = 9001; goto exitf; }
3376
0
            for (m = 0; m < orv->n_steabs; m++)
3377
0
            {
3378
0
                int *lst = NULL;
3379
0
                int *mol_lst = orv->lists_steabs[m];
3380
0
                nn = mol_lst[1] + 2;
3381
0
                lst = ( *iiv )->lists_steabs[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3382
0
                if (NULL == lst)
3383
0
                {
3384
0
                    err = 9001;
3385
0
                    goto exitf;
3386
0
                }
3387
0
                for (k = 0; k < nn; k++)
3388
0
                {
3389
0
                    lst[k] = mol_lst[k];
3390
0
                }
3391
0
            }
3392
0
        }
3393
0
        if (orv->n_sterac && orv->lists_sterac)
3394
0
        {
3395
0
            ( *iiv )->lists_sterac = (int **) inchi_calloc( orv->n_sterac, sizeof( int* ) );
3396
0
            if (NULL == ( *iiv )->lists_sterac) { err = 9001; goto exitf; }
3397
0
            for (m = 0; m < orv->n_sterac; m++)
3398
0
            {
3399
0
                int *lst = NULL;
3400
0
                int *mol_lst = orv->lists_sterac[m];
3401
0
                nn = mol_lst[1] + 2;
3402
0
                lst = ( *iiv )->lists_sterac[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3403
0
                if (NULL == lst)
3404
0
                {
3405
0
                    err = 9001;
3406
0
                    goto exitf;
3407
0
                }
3408
0
                for (k = 0; k < nn; k++)
3409
0
                {
3410
0
                    lst[k] = mol_lst[k];
3411
0
                }
3412
0
            }
3413
0
        }
3414
0
        if (orv->n_sterel && orv->lists_sterel)
3415
0
        {
3416
0
            ( *iiv )->lists_sterel = (int **) inchi_calloc( orv->n_sterel, sizeof( int* ) );
3417
0
            if (NULL == ( *iiv )->lists_sterel) { err = 9001; goto exitf; }
3418
0
            for (m = 0; m < orv->n_sterel; m++)
3419
0
            {
3420
0
                int *lst = NULL;
3421
0
                int *mol_lst = orv->lists_sterel[m];
3422
0
                nn = mol_lst[1] + 2;
3423
0
                lst = ( *iiv )->lists_sterel[m] = (int *) inchi_calloc( nn, sizeof( int ) );
3424
0
                if (NULL == lst)
3425
0
                {
3426
0
                    err = 9001;
3427
0
                    goto exitf;
3428
0
                }
3429
0
                for (k = 0; k < nn; k++)
3430
0
                {
3431
0
                    lst[k] = mol_lst[k];
3432
0
                }
3433
0
            }
3434
0
        }
3435
0
    }
3436
3437
0
exitf:
3438
0
    if (err)
3439
0
    {
3440
0
        FreeInChIExtInput( *iip, *iiv );
3441
0
    }
3442
3443
0
    return err;
3444
0
}
3445
3446
3447
#if( defined( _WIN32 ) && defined( _MSC_VER ) && _MSC_VER >= 800 && defined(_USRDLL) && defined(BUILD_LINK_AS_DLL) )
3448
/* Win32 & MS VC ++, compile and link as a DLL */
3449
3450
/*********************************************************/
3451
/*   C calling conventions export from Win32 dll         */
3452
/*********************************************************/
3453
3454
/* prototypes */
3455
#ifndef COMPILE_ALL_CPP
3456
#ifdef __cplusplus
3457
extern "C" {
3458
#endif
3459
#endif
3460
3461
    int cdecl_GetINCHI( inchi_Input *inp, inchi_Output *out );
3462
    int cdecl_GetStdINCHI( inchi_Input *inp, inchi_Output *out );
3463
    void cdecl_FreeINCHI( inchi_Output *out );
3464
    void cdecl_FreeStdINCHI( inchi_Output *out );
3465
    int  cdecl_GetStringLength( char *p );
3466
    int  cdecl_Get_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3467
                                            int bDoNotAddH,
3468
                                            int bDiffUnkUndfStereo,
3469
                                            InchiInpData *pInchiInp );
3470
    int  cdecl_Get_std_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3471
                                                int bDoNotAddH,
3472
                                                InchiInpData *pInchiInp );
3473
    /*void cdecl_Free_inchi_Input( inchi_Input *pInp );*/
3474
    void cdecl_Free_std_inchi_Input( inchi_Input *pInp );
3475
    int cdecl_GetStructFromINCHI( inchi_InputINCHI *inpInChI,
3476
                                  inchi_OutputStruct *outStruct );
3477
    int cdecl_GetStructFromStdINCHI( inchi_InputINCHI *inpInChI,
3478
                                     inchi_OutputStruct *outStruct );
3479
    int cdecl_GetINCHIfromINCHI( inchi_InputINCHI *inpInChI,
3480
                                 inchi_Output *out );
3481
    void cdecl_FreeStructFromINCHI( inchi_OutputStruct *outStruct );
3482
    void cdecl_FreeStructFromStdINCHI( inchi_OutputStruct *outStruct );
3483
    int cdecl_CheckINCHI( const char *szINCHI, const int strict );
3484
3485
#ifndef COMPILE_ALL_CPP
3486
#ifdef __cplusplus
3487
}
3488
#endif
3489
#endif
3490
3491
/* implementation */
3492
/* libinchi.def provides export without cdecl_ prefixes */
3493
3494
3495
/****************************************************************************/
3496
int cdecl_GetINCHI( inchi_Input *inp, inchi_Output *out )
3497
{
3498
    return GetINCHI( inp, out );
3499
}
3500
3501
3502
/****************************************************************************/
3503
int cdecl_GetStdINCHI( inchi_Input *inp, inchi_Output *out )
3504
{
3505
    return GetStdINCHI( inp, out );
3506
}
3507
3508
3509
/****************************************************************************/
3510
void cdecl_FreeINCHI( inchi_Output *out )
3511
{
3512
    FreeINCHI( out );
3513
}
3514
3515
3516
/****************************************************************************/
3517
void cdecl_FreeStdINCHI( inchi_Output *out )
3518
{
3519
    FreeStdINCHI( out );
3520
}
3521
3522
3523
/****************************************************************************/
3524
int cdecl_GetStringLength( char *p )
3525
{
3526
    return GetStringLength( p );
3527
}
3528
3529
3530
/****************************************************************************/
3531
int cdecl_Get_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3532
                                      int bDoNotAddH,
3533
                                      int bDiffUnkUndfStereo,
3534
                                      InchiInpData *pInchiInp )
3535
{
3536
    return Get_inchi_Input_FromAuxInfo( szInchiAuxInfo,
3537
                                        bDoNotAddH,
3538
                                        bDiffUnkUndfStereo,
3539
                                        pInchiInp );
3540
}
3541
3542
3543
/****************************************************************************/
3544
int cdecl_Get_std_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3545
                                          int bDoNotAddH,
3546
                                          InchiInpData *pInchiInp )
3547
{
3548
    return Get_std_inchi_Input_FromAuxInfo( szInchiAuxInfo,
3549
                                            bDoNotAddH,
3550
                                            pInchiInp );
3551
}
3552
3553
3554
/****************************************************************************/
3555
void cdecl_Free_std_inchi_Input( inchi_Input *pInp )
3556
{
3557
    Free_std_inchi_Input( pInp );
3558
}
3559
3560
3561
/****************************************************************************/
3562
void cdecl_Free_inchi_Input( inchi_Input *pInp )
3563
{
3564
    Free_inchi_Input( pInp );
3565
}
3566
3567
3568
/****************************************************************************/
3569
int cdecl_GetStructFromINCHI( inchi_InputINCHI *inpInChI,
3570
                              inchi_OutputStruct *outStruct )
3571
{
3572
    return GetStructFromINCHI( inpInChI, outStruct );
3573
}
3574
3575
3576
/****************************************************************************/
3577
int cdecl_GetStructFromStdINCHI( inchi_InputINCHI *inpInChI,
3578
                                 inchi_OutputStruct *outStruct )
3579
{
3580
    return GetStructFromStdINCHI( inpInChI, outStruct );
3581
}
3582
3583
/********************************************************/
3584
void cdecl_FreeStructFromINCHI( inchi_OutputStruct *outStruct )
3585
{
3586
    FreeStructFromINCHI( outStruct );
3587
}
3588
3589
3590
/****************************************************************************/
3591
int cdecl_GetINCHIfromINCHI( inchi_InputINCHI *inpInChI,
3592
                             inchi_Output *out )
3593
{
3594
    return GetINCHIfromINCHI( inpInChI, out );
3595
}
3596
3597
3598
/****************************************************************************/
3599
void cdecl_FreeStructFromStdINCHI( inchi_OutputStruct *outStruct )
3600
{
3601
    FreeStructFromStdINCHI( outStruct );
3602
}
3603
3604
3605
/****************************************************************************/
3606
int cdecl_CheckINCHI( const char *szINCHI, const int strict )
3607
{
3608
    return CheckINCHI( szINCHI, strict );
3609
}
3610
#endif
3611
3612
#if( defined(__GNUC__) && __GNUC__ >= 3 && defined(__MINGW32__) && defined(_WIN32) )
3613
#include <windows.h>
3614
/*********************************************************/
3615
/*   Pacal calling conventions export from Win32 dll     */
3616
/*********************************************************/
3617
#ifndef COMPILE_ALL_CPP
3618
#ifdef __cplusplus
3619
extern "C" {
3620
#endif
3621
#endif
3622
/* prototypes */
3623
3624
    int  PASCAL pasc_GetINCHI( inchi_Input *inp, inchi_Output *out );
3625
    int  PASCAL pasc_GetStdINCHI( inchi_Input *inp, inchi_Output *out );
3626
    void PASCAL pasc_FreeINCHI( inchi_Output *out );
3627
    void PASCAL pasc_FreeStdINCHI( inchi_Output *out );
3628
    int  PASCAL pasc_GetStringLength( char *p );
3629
    int  PASCAL pasc_Get_std_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3630
                                                      int bDoNotAddH,
3631
                                                      InchiInpData *pInchiInp );
3632
    int  PASCAL pasc_Get_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3633
                                                      int bDoNotAddH,
3634
                                                      int bDiffUnkUndfStereo,
3635
                                                      InchiInpData *pInchiInp );
3636
    void PASCAL pasc_Free_inchi_Input( inchi_Input *pInp );
3637
    void PASCAL pasc_Free_std_inchi_Input( inchi_Input *pInp );
3638
    void PASCAL pasc_FreeStructFromINCHI( inchi_OutputStruct *out );
3639
    void PASCAL pasc_FreeStructFromStdINCHI( inchi_OutputStruct *out );
3640
    int PASCAL pasc_GetStructFromINCHI( inchi_InputINCHI *inp, inchi_OutputStruct *out );
3641
    int PASCAL pasc_GetStructFromStdINCHI( inchi_InputINCHI *inp, inchi_OutputStruct *out );
3642
    int PASCAL pasc_CheckINCHI( const char *szINCHI, const int strict );
3643
3644
#ifndef COMPILE_ALL_CPP
3645
#ifdef __cplusplus
3646
}
3647
#endif
3648
#endif
3649
3650
/* implementation */
3651
/* libinchi.def provides export without PASCAL pasc_ prefixes */
3652
3653
3654
/****************************************************************************/
3655
int PASCAL pasc_GetINCHI( inchi_Input *inp, inchi_Output *out )
3656
{
3657
    return GetINCHI( inp, out );
3658
}
3659
3660
3661
/****************************************************************************/
3662
int PASCAL pasc_GetStdINCHI( inchi_Input *inp, inchi_Output *out )
3663
{
3664
    return GetStdINCHI( inp, out );
3665
}
3666
3667
3668
/****************************************************************************/
3669
void PASCAL pasc_FreeINCHI( inchi_Output *out )
3670
{
3671
    FreeINCHI( out );
3672
}
3673
3674
3675
/****************************************************************************/
3676
void PASCAL pasc_FreeStdINCHI( inchi_Output *out )
3677
{
3678
    FreeStdINCHI( out );
3679
}
3680
3681
3682
/****************************************************************************/
3683
int PASCAL pasc_GetStringLength( char *p )
3684
{
3685
    return GetStringLength( p );
3686
}
3687
3688
3689
/****************************************************************************/
3690
int PASCAL pasc_Get_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3691
                                                int bDoNotAddH,
3692
                                                int bDiffUnkUndfStereo,
3693
                                                InchiInpData *pInchiInp )
3694
{
3695
    return Get_inchi_Input_FromAuxInfo( szInchiAuxInfo, bDoNotAddH,
3696
                                            bDiffUnkUndfStereo, pInchiInp );
3697
}
3698
3699
3700
/****************************************************************************/
3701
int PASCAL pasc_Get_std_inchi_Input_FromAuxInfo( char *szInchiAuxInfo,
3702
                                                int bDoNotAddH,
3703
                                                InchiInpData *pInchiInp )
3704
{
3705
    return Get_std_inchi_Input_FromAuxInfo( szInchiAuxInfo, bDoNotAddH, pInchiInp );
3706
}
3707
3708
3709
/****************************************************************************/
3710
void PASCAL pasc_Free_inchi_Input( inchi_Input *pInp )
3711
{
3712
    Free_inchi_Input( pInp );
3713
}
3714
3715
3716
/****************************************************************************/
3717
void PASCAL pasc_Free_std_inchi_Input( inchi_Input *pInp )
3718
{
3719
    Free_std_inchi_Input( pInp );
3720
}
3721
3722
3723
/****************************************************************************/
3724
void PASCAL pasc_FreeStructFromINCHI( inchi_OutputStruct *out )
3725
{
3726
    FreeStructFromINCHI( out );
3727
}
3728
3729
3730
/****************************************************************************/
3731
void PASCAL pasc_FreeStructFromStdINCHI( inchi_OutputStruct *out )
3732
{
3733
    FreeStructFromStdINCHI( out );
3734
}
3735
3736
3737
/****************************************************************************/
3738
int PASCAL pasc_GetStructFromINCHI( inchi_InputINCHI *inp, inchi_OutputStruct *out )
3739
{
3740
    return GetStructFromINCHI( inp, out );
3741
}
3742
3743
3744
/****************************************************************************/
3745
int PASCAL pasc_GetStructFromStdINCHI( inchi_InputINCHI *inp, inchi_OutputStruct *out )
3746
{
3747
    return GetStructFromStdINCHI( inp, out );
3748
}
3749
3750
3751
/****************************************************************************/
3752
int PASCAL pasc_CheckINCHI( const char *szINCHI, const int strict )
3753
{
3754
    return CheckINCHI( szINCHI, strict );
3755
}
3756
3757
#endif