Coverage Report

Created: 2023-11-27 06:31

/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
273
{
146
273
    if (!out)
147
0
    {
148
0
        return;
149
0
    }
150
151
273
    if (out->szInChI)
152
73
    {
153
73
        inchi_free( out->szInChI );
154
73
    }
155
273
    if (out->szLog)
156
219
    {
157
219
        inchi_free( out->szLog );
158
219
    }
159
273
    if (out->szMessage)
160
219
    {
161
219
        inchi_free( out->szMessage );
162
219
    }
163
164
273
    memset( out, 0, sizeof( *out ) );
165
273
}
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
273
{
201
273
    if (!out)
202
0
    {
203
0
        return;
204
0
    }
205
206
273
    if (out->atom)
207
16
    {
208
16
        inchi_free( out->atom );
209
16
    }
210
273
    if (out->stereo0D)
211
0
    {
212
0
        inchi_free( out->stereo0D );
213
0
    }
214
273
    if (out->szLog)
215
219
    {
216
219
        inchi_free( out->szLog );
217
219
    }
218
273
    if (out->szMessage)
219
219
    {
220
219
        inchi_free( out->szMessage );
221
219
    }
222
223
273
    memset( out, 0, sizeof( *out ) );
224
273
}
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
546
{
822
546
    int ret = INCHI_VALID_NON_STANDARD;
823
546
    int ret_i2i;
824
546
    inchi_InputINCHI    inchi_inp;
825
546
    inchi_Output        inchi_out;
826
546
    size_t slen, pos_slash1 = 0;
827
546
    char *str = NULL;
828
546
    size_t i;
829
546
    size_t slen0;
830
546
    char pp;
831
832
    /* .. non-empty */
833
546
    if (szINCHI == NULL)
834
0
    {
835
0
        return INCHI_INVALID_PREFIX;
836
0
    }
837
838
546
    slen = strlen( szINCHI );
839
840
841
    /* .. has valid prefix */
842
546
    if (slen < LEN_INCHI_STRING_PREFIX + 3)
843
4
    {
844
4
        return INCHI_INVALID_PREFIX;
845
4
    }
846
542
    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
536
    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
536
    pos_slash1 = LEN_INCHI_STRING_PREFIX + 1;
860
536
    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
536
    else if (szINCHI[pos_slash1] == 'B')
867
2
    {
868
        /* Beta version InChI ==> non-standard */
869
2
        ret = INCHI_VALID_BETA;
870
2
        pos_slash1++;
871
2
    }
872
873
    /* .. has trailing slash in the right place */
874
536
    if (szINCHI[pos_slash1] != '/')
875
2
    {
876
2
        return INCHI_INVALID_LAYOUT;
877
2
    }
878
879
    /* .. the rest of source string contains valid literals */
880
881
882
    /* adjust line len so we not check trailing whitespaces */
883
534
    i = slen - 1;
884
534
    while (isspace(UCINT szINCHI[i--])) slen--;
885
886
    /* Treat possible SaveOpt letters  */
887
534
    slen0 = slen;
888
534
    if (( szINCHI[slen - 3] == '\\' ) &&
889
534
        ( szINCHI[slen - 2] >= 'A' ) && ( szINCHI[slen - 2] <= 'Z' ) &&
890
534
        ( szINCHI[slen - 1] >= 'A' ) && ( szINCHI[slen - 1] <= 'Z' )
891
534
        )
892
0
    {
893
0
        slen0 = slen - 3;
894
0
    }
895
896
534
    int prev_is_slash = 1;
897
2.75M
    for (i = pos_slash1 + 1; i < slen0; i++)
898
2.75M
    {
899
2.75M
        pp = szINCHI[i];
900
2.75M
#if ( FIX_GAF_2020_GENERIC==1 )
901
2.75M
        if (prev_is_slash)
902
20.7k
        {
903
            /* After slash: */
904
20.7k
            if (pp == '0')
905
0
            {
906
                /* '0' is never allowed */
907
0
                return INCHI_INVALID_LAYOUT;
908
0
            }
909
20.7k
            if (i > pos_slash1 + 1)
910
20.1k
            {
911
                /* Not in main formula layer... */ 
912
20.1k
                if (!islower(pp))
913
8
                {
914
                    /* only lowercase letters are allowed */
915
8
                    return INCHI_INVALID_LAYOUT;
916
8
                }
917
20.1k
            }
918
20.7k
        }
919
2.75M
        prev_is_slash = (pp != '/') ? 0 : 1;
920
2.75M
#endif
921
2.75M
        if (pp >= 'A' && pp <= 'Z')   continue;
922
2.53M
        if (pp >= 'a' && pp <= 'z')   continue;
923
1.69M
        if (pp >= '0' && pp <= '9')  continue;
924
510k
        switch (pp)
925
510k
        {
926
138k
            case '(': case ')':
927
151k
            case '*': case '+':
928
442k
            case ',': case '-':
929
467k
            case '.': case '/':
930
467k
#if ( FIX_GAF_2020_GENERIC==1 )
931
510k
            case ';': case '?':     continue;
932
#else
933
            case ';': case '=':
934
            case '?': case '@':     continue;
935
#endif
936
88
            default:            return INCHI_INVALID_LAYOUT;
937
510k
        }
938
510k
    }
939
940
438
    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
438
fin:if (strict)
970
0
{
971
0
    if (NULL != str)
972
0
        inchi_free( str );
973
0
}
974
975
438
    return ret;
976
438
}
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
546
{
1025
546
    char    *p;
1026
546
    char    *pArgCurChar;
1027
546
    int      bInsideQuotes;
1028
546
    int      bCopyCharToArg;
1029
546
    int      nNumBackSlashes;
1030
546
    int      i;
1031
1032
546
    i = 0;
1033
546
    argv[i++] = ""; /* zeroth argument is not used */
1034
546
    p = cmd;
1035
546
    bInsideQuotes = 0;
1036
1037
    /* arguments, one by one */
1038
1.09k
    while (i < maxargs - 1)
1039
1.09k
    {
1040
        /* bypass spaces */
1041
1.63k
        while (*p == ' ' || *p == '\t')
1042
546
        {
1043
546
            p++;
1044
546
        }
1045
1.09k
        if (!*p)
1046
546
        {
1047
546
            break;
1048
546
        }
1049
1050
        /* scan an argument */
1051
546
        argv[i++] = pArgCurChar = p;     /* store preliminary ptr to arg */
1052
1053
7.37k
        while (1)
1054
7.37k
        {
1055
7.37k
            bCopyCharToArg = 1;
1056
7.37k
            nNumBackSlashes = 0;
1057
7.37k
            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
7.37k
            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
7.37k
            while (nNumBackSlashes--)
1089
0
            {
1090
0
                *pArgCurChar++ = '\\';
1091
0
            }
1092
7.37k
            if (!*p)
1093
546
            {
1094
546
                break;
1095
546
            }
1096
6.82k
            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.82k
            if (bCopyCharToArg)
1104
6.82k
            {
1105
6.82k
                *pArgCurChar++ = *p;
1106
6.82k
            }
1107
6.82k
            ++p;
1108
6.82k
        }
1109
546
        *pArgCurChar++ = '\0';  /* argument zero termination */
1110
546
    }
1111
1112
    /* The last argument is NULL */
1113
546
    argv[i] = NULL;
1114
1115
546
    return i;
1116
546
}
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
16
{
1656
16
    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
16
    num_stereo_centers = num_stereo_bonds = ret = 0;
1660
1661
16
    *atom = NULL;
1662
16
    *num_atoms = 0;
1663
16
    *stereo0D = NULL;
1664
16
    *num_stereo0D = 0;
1665
1666
34.0k
    for (i = 0; i < num_inp_atoms; i++)
1667
34.0k
    {
1668
34.0k
        if (at[i].p_parity)
1669
0
        {
1670
            /* stereocenter */
1671
0
            num_stereo_centers++;
1672
0
        }
1673
34.0k
        else
1674
34.0k
        {
1675
34.0k
            for (m = 0; m < MAX_NUM_STEREO_BONDS && at[i].sb_parity[m]; m++)
1676
0
            {
1677
0
                ;
1678
0
            }
1679
34.0k
            num_stereo_bonds += m;
1680
34.0k
        }
1681
34.0k
    }
1682
1683
16
    num_stereo_bonds /= 2;
1684
16
    num_inp_stereo0D = num_stereo_bonds + num_stereo_centers;
1685
1686
16
    if (num_inp_atoms > 0)
1687
16
    {
1688
16
        *atom = (inchi_Atom *) inchi_calloc( num_inp_atoms, sizeof( ( *atom )[0] ) );
1689
16
    }
1690
1691
16
    *num_atoms = num_inp_atoms;
1692
1693
16
    if (num_inp_stereo0D > 0)
1694
0
    {
1695
0
        *stereo0D = (inchi_Stereo0D *) inchi_calloc( num_inp_stereo0D, sizeof( ( *stereo0D )[0] ) );
1696
0
    }
1697
1698
16
    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
34.0k
    for (i = 0; i < num_inp_atoms; i++)
1707
34.0k
    {
1708
34.0k
        ( *atom )[i].num_bonds = at[i].valence;
1709
34.0k
        for (m = 0; m < at[i].valence; m++)
1710
0
        {
1711
0
            ( *atom )[i].bond_type[m] = at[i].bond_type[m];
1712
0
            ( *atom )[i].neighbor[m] = at[i].neighbor[m];
1713
0
        }
1714
34.0k
        ( *atom )[i].charge = at[i].charge;
1715
34.0k
        memcpy( ( *atom )[i].elname, at[i].elname, ATOM_EL_LEN );
1716
34.0k
        if (at[i].iso_atw_diff)
1717
12
        {
1718
12
            ( *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
12
        }
1720
34.0k
        ( *atom )[i].num_iso_H[0] = at[i].num_H;
1721
136k
        for (m = 0; m < NUM_H_ISOTOPES; m++)
1722
102k
        {
1723
102k
            ( *atom )[i].num_iso_H[m + 1] = at[i].num_iso_H[m];
1724
102k
        }
1725
34.0k
        ( *atom )[i].radical = at[i].radical;
1726
34.0k
    }
1727
1728
    /* stereo */
1729
34.0k
    for (i = n = 0; i < num_inp_atoms; i++)
1730
34.0k
    {
1731
34.0k
        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
34.0k
        else
1751
34.0k
        {
1752
34.0k
            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
34.0k
        }
1812
34.0k
    }
1813
1814
16
    *num_stereo0D = n;
1815
1816
16
exit_function:
1817
16
    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
16
    return ret;
1834
16
}
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
876
#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
273
{
2092
273
    STRUCT_DATA struct_data;
2093
273
    STRUCT_DATA *sd = &struct_data;
2094
2095
273
    static char szMainOption[] = " ?InChI2InChI";
2096
2097
273
    INCHI_CLOCK ic;
2098
273
    CANON_GLOBALS CG;
2099
2100
273
    int i;
2101
273
    char      szSdfDataValue[MAX_SDF_VALUE + 1];
2102
273
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
2103
2104
273
    INPUT_PARMS inp_parms;
2105
273
    INPUT_PARMS *ip = &inp_parms;
2106
2107
273
    int             bReleaseVersion = bRELEASE_VERSION;
2108
273
    int   nRet = 0, nRet1;
2109
2110
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2111
    int  num_repeat = REPEAT_ALL;
2112
#endif
2113
2114
273
    const char *argv[INCHI_MAX_NUM_ARG + 1];
2115
273
    int   argc;
2116
273
    char *szOptions = NULL;
2117
2118
273
    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
273
    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
273
    inchi_ios_init( input_file, INCHI_IOS_TYPE_STRING, NULL );
2162
273
    inchi_ios_init( out_file, INCHI_IOS_TYPE_STRING, NULL );
2163
273
    inchi_ios_init( log_file, INCHI_IOS_TYPE_STRING, NULL );
2164
2165
273
    sd->bUserQuit = 0;
2166
2167
    /* clear original input structure */
2168
    /* memset( inchi_file, 0, sizeof(inchi_file) ); */
2169
273
    memset( sd, 0, sizeof( *sd ) );
2170
273
    memset( ip, 0, sizeof( *ip ) );
2171
273
    memset( szSdfDataValue, 0, sizeof( szSdfDataValue ) );
2172
2173
273
    memset( &ic, 0, sizeof( ic ) );
2174
273
    memset( &CG, 0, sizeof( CG ) );
2175
2176
273
    szMainOption[1] = INCHI_OPTION_PREFX;
2177
2178
273
    if (!inpInChI)
2179
0
    {
2180
0
        nRet = _IS_ERROR;
2181
0
        goto exit_function;
2182
0
    }
2183
2184
    /* options */
2185
273
    if (inpInChI)
2186
273
    {
2187
273
        int opt_len = (int) ( ( inpInChI->szOptions ? strlen( inpInChI->szOptions ) : 0 ) + sizeof( szMainOption ) + 1 );
2188
273
        szOptions = (char*) inchi_calloc( opt_len + 1, sizeof( szOptions[0] ) );
2189
273
        if (szOptions)
2190
273
        {
2191
273
            if (inpInChI->szOptions)
2192
0
            {
2193
0
                strcpy( szOptions, inpInChI->szOptions );
2194
0
            }
2195
273
            strcat( szOptions, szMainOption );
2196
273
            argc = parse_options_string( szOptions, argv, INCHI_MAX_NUM_ARG );
2197
273
        }
2198
0
        else
2199
0
        {
2200
0
            nRet = _IS_FATAL;
2201
0
            goto translate_RetVal; /* emergency exit */
2202
0
        }
2203
273
    }
2204
0
    else
2205
0
    {
2206
0
        argc = 1;
2207
0
        argv[0] = "";
2208
0
        argv[1] = NULL;
2209
0
    }
2210
2211
273
    if (argc == 1
2212
273
#ifdef TARGET_API_LIB
2213
273
        && ( !inpInChI || !inpInChI->szInChI )
2214
273
#endif
2215
2216
273
        || argc == 2 && ( argv[1][0] == INCHI_OPTION_PREFX ) &&
2217
273
        ( !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
273
    nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue,
2227
273
                                &ulDisplTime, bReleaseVersion, log_file );
2228
2229
273
    if (szOptions)
2230
273
    {
2231
        /* argv pointed to strings in szOptions */
2232
273
        inchi_free( szOptions );
2233
273
        szOptions = NULL;
2234
273
    }
2235
    /* INChI DLL specific */
2236
273
    ip->bNoStructLabels = 1;
2237
2238
273
    if (0 > nRet1)
2239
0
    {
2240
0
        goto exit_function;
2241
0
    }
2242
2243
273
    if (ip->bNoStructLabels)
2244
273
    {
2245
273
        ip->pSdfLabel = NULL;
2246
273
        ip->pSdfValue = NULL;
2247
273
    }
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
273
    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
273
    if (!inpInChI->szInChI)
2271
0
    {
2272
0
        nRet = _IS_ERROR;
2273
0
        goto exit_function;
2274
0
    }
2275
273
    else
2276
273
    {
2277
273
        const int strict = 0;
2278
273
        nRet = CheckINCHI( inpInChI->szInChI, strict );
2279
273
        if (nRet != INCHI_VALID_STANDARD     &&
2280
273
            nRet != INCHI_VALID_NON_STANDARD &&
2281
273
            nRet != INCHI_VALID_BETA)
2282
54
        {
2283
54
            nRet = _IS_ERROR;
2284
54
            goto exit_function;
2285
54
        }
2286
273
    }
2287
2288
2289
219
    PrintInputParms( log_file, ip );
2290
2291
    /********************************/
2292
    /* InChI -> InChI               */
2293
    /********************************/
2294
2295
    /* input_file simulation */
2296
219
    input_file->s.pStr = inpInChI->szInChI;
2297
219
    input_file->s.nUsedLength = (int) strlen( input_file->s.pStr ) + 1;
2298
219
    input_file->s.nAllocatedLength = input_file->s.nUsedLength;
2299
219
    input_file->s.nPtr = 0;
2300
2301
    /* buffer for the message */
2302
219
    out->szMessage = (char *) inchi_calloc( MAX_MSG_LEN, sizeof( out->szMessage[0] ) );
2303
219
    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
219
    else
2309
219
    {
2310
219
        nRet = ReadWriteInChI( &ic, &CG, input_file, out_file, log_file,
2311
219
                                ip, sd,
2312
219
                                NULL, 0, NULL,
2313
219
                                NULL, NULL,
2314
219
                                out->szMessage, MAX_MSG_LEN,
2315
219
                                NULL /*out->WarningFlags*/ );
2316
219
    }
2317
2318
219
    if (nRet >= 0 && out_file->s.pStr)
2319
73
    {
2320
        /* success */
2321
73
        char *p;
2322
73
        out->szInChI = out_file->s.pStr;
2323
73
        out->szAuxInfo = NULL;
2324
2325
73
        for (p = strchr( out->szInChI, '\n' ); p; p = strchr( p + 1, '\n' ))
2326
73
        {
2327
73
            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
73
            else if (out->szAuxInfo || !p[1])
2333
73
            {
2334
                /* remove LF after aux info or from the last char */
2335
73
                *p = '\0';
2336
73
                break;
2337
73
            }
2338
73
        }
2339
73
        out_file->s.pStr = NULL;
2340
73
    }
2341
2342
    /*
2343
    out->szLog = log_file->pStr;
2344
    log_file->pStr   = NULL;
2345
    */
2346
2347
273
exit_function:;
2348
2349
1.36k
    for (i = 0; i < MAX_NUM_PATHS; i++)
2350
1.09k
    {
2351
1.09k
        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.09k
    }
2357
2358
273
    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
273
#ifdef TARGET_API_LIB
2368
    /* output */
2369
2370
273
        if (log_file->s.pStr && log_file->s.nUsedLength > 0)
2371
219
        {
2372
584
            while (log_file->s.nUsedLength && '\n' == log_file->s.pStr[log_file->s.nUsedLength - 1])
2373
365
            {
2374
365
                log_file->s.pStr[--log_file->s.nUsedLength] = '\0'; /* remove last LF */
2375
365
            }
2376
219
            if (out)
2377
219
            {
2378
219
                out->szLog = log_file->s.pStr;
2379
219
                log_file->s.pStr = NULL;
2380
219
            }
2381
219
        }
2382
2383
273
#endif
2384
2385
273
translate_RetVal:
2386
2387
    /* close internal output streams */
2388
273
    inchi_ios_close( out_file );
2389
273
    inchi_ios_close( log_file );
2390
273
    inchi_ios_reset( input_file );  /* do not close input_file - its string buffer may point to inpInChI->szInChI */
2391
2392
273
    switch (nRet)
2393
273
    {
2394
3
        case -3: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2395
128
        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
142
        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
142
            break;
2419
273
    }
2420
2421
273
    return nRet;
2422
273
}
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
273
{
2458
273
    INCHI_CLOCK ic;
2459
273
    CANON_GLOBALS CG;
2460
273
    STRUCT_DATA struct_data;
2461
273
    STRUCT_DATA *sd = &struct_data;
2462
273
    INPUT_PARMS inp_parms;
2463
273
    INPUT_PARMS *ip = &inp_parms;
2464
273
    INCHI_IOSTREAM inchi_file[3];
2465
273
    INCHI_IOSTREAM *out_file = inchi_file, *log_file = inchi_file + 1, *input_file = inchi_file + 2;
2466
273
    int    i, nRet = 0, nRet1;
2467
273
    int bStdFormat = 0;
2468
273
    int bReleaseVersion = bRELEASE_VERSION;
2469
273
    unsigned long  ulDisplTime = 0;    /*  infinite, milliseconds */
2470
#if ( defined(REPEAT_ALL) && REPEAT_ALL > 0 )
2471
    int  num_repeat = REPEAT_ALL;
2472
#endif
2473
273
    static char szMainOption[] = " ?InChI2Struct";
2474
273
    char szSdfDataValue[MAX_SDF_VALUE + 1];
2475
273
    const char *argv[INCHI_MAX_NUM_ARG + 1];
2476
273
    int   argc;
2477
273
    char *szOptions = NULL;
2478
    /* conversion result */
2479
273
    inp_ATOM *at = NULL;
2480
273
    int num_at = 0;
2481
273
    OAD_Polymer *polymer = NULL;
2482
273
    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
273
    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
273
    sd->bUserQuit = 0;
2526
2527
    /* Initialize internal for this function I/O streams as string buffers */
2528
273
    inchi_ios_init( input_file, INCHI_IOS_TYPE_STRING, NULL );
2529
273
    inchi_ios_init( out_file, INCHI_IOS_TYPE_STRING, NULL );
2530
273
    inchi_ios_init( log_file, INCHI_IOS_TYPE_STRING, NULL );
2531
2532
    /* clear original input structure */
2533
273
    memset( sd, 0, sizeof( *sd ) );
2534
273
    memset( ip, 0, sizeof( *ip ) );
2535
273
    memset( szSdfDataValue, 0, sizeof( szSdfDataValue ) );
2536
2537
273
    memset( &ic, 0, sizeof( ic ) );
2538
273
    memset( &CG, 0, sizeof( CG ) );
2539
2540
273
    szMainOption[1] = INCHI_OPTION_PREFX;
2541
2542
273
    if (!inpInChI)
2543
0
    {
2544
0
        nRet = _IS_ERROR;
2545
0
        goto exit_function;
2546
0
    }
2547
2548
    /* options */
2549
273
    if (inpInChI /*&& inpInChI->szOptions*/)
2550
273
    {
2551
        /* fix bug discovered by Burt Leland 2008-12-23 */
2552
273
        int opt_len = ( inpInChI->szOptions ? strlen( inpInChI->szOptions ) : 0 ) + sizeof( szMainOption ) + 1;
2553
273
        szOptions = (char*) inchi_calloc( opt_len + 1, sizeof( szOptions[0] ) );
2554
273
        if (szOptions)
2555
273
        {
2556
273
            if (inpInChI->szOptions)
2557
                /* fix bug discovered by Burt Leland 2008-12-23 */
2558
0
                strcpy( szOptions, inpInChI->szOptions );
2559
273
            strcat( szOptions, szMainOption );
2560
273
            argc = parse_options_string( szOptions, argv, INCHI_MAX_NUM_ARG );
2561
273
        }
2562
0
        else
2563
0
        {
2564
0
            nRet = _IS_FATAL;
2565
0
            goto translate_RetVal; /* emergency exit */
2566
0
        }
2567
273
    }
2568
0
    else
2569
0
    {
2570
0
        argc = 1;
2571
0
            argv[0] = "";
2572
0
        argv[1] = NULL;
2573
0
    }
2574
2575
273
    if (argc == 1
2576
273
#ifdef TARGET_API_LIB
2577
273
        && ( !inpInChI || !inpInChI->szInChI )
2578
273
#endif
2579
273
        || argc == 2 && ( argv[1][0] == INCHI_OPTION_PREFX ) &&
2580
273
        ( !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
273
    nRet1 = ReadCommandLineParms( argc, argv, ip, szSdfDataValue,
2589
273
                                  &ulDisplTime, bReleaseVersion,
2590
273
                                  log_file );
2591
2592
273
    if (szOptions)
2593
273
    {
2594
        /* argv pointed to strings in szOptions */
2595
273
        inchi_free( szOptions );
2596
273
        szOptions = NULL;
2597
273
    }
2598
2599
    /* INChI DLL specific */
2600
273
    ip->bNoStructLabels = 1;
2601
2602
273
    if (0 > nRet1)
2603
0
    {
2604
0
        goto exit_function;
2605
0
    }
2606
2607
273
    if (ip->bNoStructLabels)
2608
273
    {
2609
273
        ip->pSdfLabel = NULL;
2610
273
        ip->pSdfValue = NULL;
2611
273
    }
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
273
    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
273
    if (!inpInChI->szInChI)
2631
0
    {
2632
0
        nRet = _IS_ERROR;
2633
0
        goto exit_function;
2634
0
    }
2635
273
    else
2636
273
    {
2637
273
        const int strict = 0;                     /* do not use strict mode, it may be too alarmous */
2638
273
        nRet = CheckINCHI( inpInChI->szInChI, strict );
2639
273
        if (nRet == INCHI_VALID_STANDARD)
2640
0
        {
2641
0
            bStdFormat = 1;
2642
0
        }
2643
273
        else if (nRet == INCHI_VALID_NON_STANDARD || nRet == INCHI_VALID_BETA)
2644
219
        {
2645
219
            ;
2646
219
        }
2647
54
        else
2648
54
        {
2649
54
            nRet = _IS_ERROR;
2650
54
            goto exit_function;
2651
54
        }
2652
273
    }
2653
2654
219
    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
219
    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
219
    outStruct->szMessage = (char *) inchi_calloc( MAX_MSG_LEN, sizeof( char ) );
2675
219
    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
219
    else
2681
219
    {
2682
219
        int num_bonds;
2683
219
        nRet = ReadWriteInChI( &ic, &CG , input_file, out_file, log_file,
2684
219
                                ip, sd, &at, &num_at, &num_bonds,
2685
219
                                &polymer, &v3000,
2686
219
                                outStruct->szMessage,
2687
219
                                MAX_MSG_LEN, outStruct->WarningFlags );
2688
2689
219
        if (nRet >= 0 && polymer)
2690
1
        {
2691
1
            OAD_Polymer_SmartReopenCyclizedUnits( polymer, at,
2692
1
                                                 num_at, &num_bonds );
2693
1
        }
2694
219
    }
2695
2696
219
    if (nRet >= 0 && at && num_at)
2697
16
    {
2698
        /* success */
2699
16
        nRet = InpAtom0DToInchiAtom( at, num_at,
2700
16
                                    &outStruct->num_atoms,
2701
16
                                    &outStruct->atom,
2702
16
                                    &outStruct->num_stereo0D,
2703
16
                                    &outStruct->stereo0D );
2704
2705
16
        if (at)
2706
16
        {
2707
16
            inchi_free( at );
2708
16
            at = NULL;
2709
16
        }
2710
2711
16
        if (nRet >= 0 && polymer)
2712
1
        {
2713
            /* Check for and then replace ZZ for star atoms if Polymer extension is supplied */
2714
2
            for (i = 0; i < outStruct->num_atoms; i++)
2715
1
            {
2716
1
                if (!strcmp( outStruct->atom[i].elname, "Zz" ))
2717
0
                {
2718
0
                    strcpy( outStruct->atom[i].elname, "*" );
2719
0
                }
2720
1
            }
2721
1
        }
2722
2723
16
        if (nRet >= 0)
2724
16
        {
2725
16
            if (polymer || v3000)
2726
1
            {
2727
1
                nRet = SetInChIExtInputByExtOrigAtData( polymer, v3000,
2728
1
                                                        &outStruct->polymer,
2729
1
                                                        &outStruct->v3000,
2730
1
                                                        outStruct->num_atoms ); /* pair to SetExtOrigAtDataByInChIExtInput */
2731
1
                FreeExtOrigAtData( polymer, v3000 );
2732
1
                polymer = NULL;
2733
1
                v3000 = NULL;
2734
1
            }
2735
16
        }
2736
16
        if (nRet < 0)
2737
0
        {
2738
0
            inchi_ios_eprint( log_file, "Final structure conversion failed\n" );
2739
0
        }
2740
16
    }
2741
219
    outStruct->szLog = log_file->s.pStr;
2742
2743
273
exit_function:;
2744
2745
1.36k
    for (i = 0; i < MAX_NUM_PATHS; i++)
2746
1.09k
    {
2747
1.09k
        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.09k
    }
2753
2754
273
    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
273
#ifdef TARGET_API_LIB
2764
    /* output */
2765
273
    if (log_file->s.pStr && log_file->s.nUsedLength > 0)
2766
219
    {
2767
440
        while (log_file->s.nUsedLength &&
2768
440
                '\n' == log_file->s.pStr[log_file->s.nUsedLength - 1])
2769
221
        {
2770
221
            log_file->s.pStr[--log_file->s.nUsedLength] = '\0'; /* remove last LF */
2771
221
        }
2772
219
        if (outStruct)
2773
219
        {
2774
219
            outStruct->szLog = log_file->s.pStr;
2775
219
            log_file->s.pStr = NULL;
2776
219
        }
2777
219
    }
2778
273
#endif
2779
2780
273
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
273
    inchi_ios_close( input_file );
2786
273
    inchi_ios_close( out_file );
2787
273
    inchi_ios_close( log_file );
2788
2789
273
    switch (nRet)
2790
273
    {
2791
61
        case -3: nRet = inchi_Ret_ERROR; break; /* Error: no Structure has been created */
2792
128
        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
84
        default:
2795
84
            if (!outStruct->atom || !outStruct->num_atoms)
2796
68
            {
2797
68
                nRet = inchi_Ret_EOF;
2798
68
            }
2799
16
            else
2800
16
            {
2801
16
                int m, n, t = 0;
2802
48
                for (m = 0; m < 2; m++)
2803
32
                {
2804
96
                    for (n = 0; n < 2; n++)
2805
64
                    {
2806
64
                        if (outStruct->WarningFlags[m][n])
2807
15
                        {
2808
15
                            t++;
2809
15
                        }
2810
64
                    }
2811
32
                }
2812
16
                nRet = t ? inchi_Ret_WARNING : inchi_Ret_OKAY;
2813
16
            }
2814
84
            break;
2815
273
    }
2816
2817
273
    return nRet;
2818
273
}
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
273
{
2830
273
    int ret = 0;
2831
2832
273
    inchi_OutputStructEx outex;
2833
273
    memset( out, 0, sizeof( *out ) );
2834
2835
273
    ret = GetStructFromINCHIEx( inpInChI, &outex );
2836
2837
273
    out->szLog = outex.szLog;
2838
273
    out->szMessage = outex.szMessage;
2839
273
    out->WarningFlags[0][0] = outex.WarningFlags[0][0];
2840
273
    out->WarningFlags[0][1] = outex.WarningFlags[0][1];
2841
273
    out->WarningFlags[1][0] = outex.WarningFlags[1][0];
2842
273
    out->WarningFlags[1][1] = outex.WarningFlags[1][1];
2843
2844
273
    if (ret == inchi_Ret_OKAY || ret == inchi_Ret_WARNING)
2845
16
    {
2846
16
        out->num_atoms = outex.num_atoms;
2847
16
        out->atom = outex.atom;
2848
16
        out->num_stereo0D = outex.num_stereo0D;
2849
16
        out->stereo0D = outex.stereo0D;
2850
16
    }
2851
2852
273
    return ret;
2853
273
}
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
1
{
3235
1
    int    k, m, err = 0;
3236
3237
        /* Polymers */
3238
1
    if (orp && orp->n > 0)
3239
1
    {
3240
1
        *iip = (inchi_Input_Polymer *) inchi_calloc( 1, sizeof( inchi_Input_Polymer ) );
3241
1
        if (!*iip)
3242
0
        {
3243
0
            err = 9001;
3244
0
            goto exitf;
3245
0
        }
3246
1
        ( *iip )->n = orp->n;
3247
1
        ( *iip )->units = (inchi_Input_PolymerUnit**) inchi_calloc( orp->n, sizeof( ( *iip )->units[0] ) );
3248
1
        if (!( *iip )->units)
3249
0
        {
3250
0
            err = 9001; goto exitf;
3251
0
        }
3252
1
        memset( ( *iip )->units, 0, sizeof( *( *iip )->units ) );
3253
146
        for (k = 0; k < orp->n; k++)
3254
145
        {
3255
145
            int q = 0;
3256
145
            inchi_Input_PolymerUnit *unitk;
3257
145
            OAD_PolymerUnit    *groupk = orp->units[k];
3258
145
            ( *iip )->units[k] = (inchi_Input_PolymerUnit*) inchi_calloc( 1, sizeof( inchi_Input_PolymerUnit ) );
3259
145
            unitk = ( *iip )->units[k];
3260
145
            if (!unitk)
3261
0
            {
3262
0
                err = 9001; goto exitf;
3263
0
            }
3264
145
            memset( unitk, 0, sizeof( *unitk ) );
3265
145
            unitk->id = groupk->id;
3266
145
            unitk->type = groupk->type;
3267
145
            unitk->subtype = groupk->subtype;
3268
145
            unitk->conn = groupk->conn;
3269
145
            unitk->label = groupk->label;
3270
725
            for (q = 0; q < 4; q++)
3271
580
            {
3272
580
                unitk->xbr1[q] = groupk->xbr1[q];
3273
580
                unitk->xbr2[q] = groupk->xbr2[q];
3274
580
            }
3275
145
            strcpy( unitk->smt, groupk->smt );
3276
145
            unitk->na = groupk->na;
3277
145
            unitk->alist = (int *) inchi_calloc( unitk->na, sizeof( int ) );
3278
145
            if (!unitk->alist)
3279
0
            {
3280
0
                err = 9001; goto exitf;
3281
0
            }
3282
290
            for (m = 0; m < unitk->na; m++)
3283
145
            {
3284
145
                unitk->alist[m] = groupk->alist[m];
3285
145
            }
3286
145
            unitk->nb = groupk->nb;
3287
145
            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
145
            else
3300
145
            {
3301
145
                unitk->blist = NULL;
3302
145
            }
3303
145
        }
3304
1
    }
3305
3306
1
    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
1
exitf:
3438
1
    if (err)
3439
0
    {
3440
0
        FreeInChIExtInput( *iip, *iiv );
3441
0
    }
3442
3443
1
    return err;
3444
1
}
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