Coverage Report

Created: 2024-02-25 06:07

/src/inchi/INCHI-1-SRC/INCHI_BASE/src/runichi.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
* International Chemical Identifier (InChI)
3
* Version 1
4
* Software version 1.07
5
* 20/11/2023
6
*
7
* The InChI library and programs are free software developed under the
8
* auspices of the International Union of Pure and Applied Chemistry (IUPAC).
9
* Originally developed at NIST.
10
* Modifications and additions by IUPAC and the InChI Trust.
11
* Some portions of code were developed/changed by external contributors
12
* (either contractor or volunteer) which are listed in the file
13
* 'External-contributors' included in this distribution.
14
*
15
* IUPAC/InChI-Trust Licence No.1.0 for the
16
* International Chemical Identifier (InChI)
17
* Copyright (C) IUPAC and InChI Trust
18
*
19
* This library is free software; you can redistribute it and/or modify it
20
* under the terms of the IUPAC/InChI Trust InChI Licence No.1.0,
21
* or any later version.
22
*
23
* Please note that this library is distributed WITHOUT ANY WARRANTIES
24
* whatsoever, whether expressed or implied.
25
* See the IUPAC/InChI-Trust InChI Licence No.1.0 for more details.
26
*
27
* You should have received a copy of the IUPAC/InChI Trust InChI
28
* Licence No. 1.0 with this library; if not, please e-mail:
29
*
30
* info@inchi-trust.org
31
*
32
*/
33
34
35
/*
36
    General processing procedures
37
38
*/
39
40
#include <stdlib.h>
41
#include <string.h>
42
#include <stdarg.h>
43
#include <errno.h>
44
#include <limits.h>
45
#include <math.h>
46
#include <ctype.h>
47
48
#include "mode.h"
49
#include "ichitime.h"
50
#ifndef COMPILE_ANSI_ONLY
51
#include <conio.h>
52
#endif
53
54
#include "ichimain.h"
55
#include "ichi_io.h"
56
#include "mol_fmt.h"
57
#include "inchi_api.h"
58
#include "readinch.h"
59
#include "ichicant.h"
60
#ifdef TARGET_LIB_FOR_WINCHI
61
#include "../../../IChI_lib/src/ichi_lib.h"
62
#include "inchi_api.h"
63
#endif
64
#include "inchi_gui.h"
65
#include "readinch.h"
66
#include "ichirvrs.h"
67
68
#include "bcf_s.h"
69
70
extern int DisplayTheWholeStructure( struct tagCANON_GLOBALS *pCG,
71
                                     struct tagINCHI_CLOCK   *ic,
72
                                     struct tagStructData    *sd,
73
                                     INPUT_PARMS             *ip,
74
                                     char                    *szTitle,
75
                                     INCHI_IOSTREAM          *inp_file,
76
                                     INCHI_IOSTREAM          *log_file,
77
                                     ORIG_ATOM_DATA          *orig_inp_data,
78
                                     long                    num_inp,
79
                                     int                     iINChI,
80
                                     int                     bShowStruct,
81
                                     int                     bINCHI_LIB_Flag );
82
83
extern int DisplayStructure( struct tagCANON_GLOBALS *pCG,
84
                             inp_ATOM   *at,
85
                             int        num_at,
86
                             OAD_Polymer *polymer,
87
                             int        num_removed_H,
88
                             int        bAdd_DT_to_num_H,
89
                             int        nNumRemovedProtons,
90
                             NUM_H      *nNumRemovedProtonsIsotopic,
91
                             int        bIsotopic,
92
                             int        j /*bTautomeric*/,
93
                             INChI      **cur_INChI,
94
                             INChI_Aux  **cur_INChI_Aux,
95
                             int        bAbcNumbers,
96
                             DRAW_PARMS *dp,
97
                             INCHI_MODE nMode,
98
                             char       *szTitle );
99
100
extern int ReadInChICoord( INCHI_IOSTREAM   *pInp,
101
                           SEGM_LINE        *pLine,
102
                           int              *pState,
103
                           INChI            *pInpInChI[INCHI_NUM][TAUT_NUM],
104
                           int              nNumComponents[INCHI_NUM][TAUT_NUM] );
105
106
107
/* Local functions */
108
static int DoOneStructureEarlyPreprocessing( INCHI_CLOCK *ic,
109
                                             CANON_GLOBALS *pCG,
110
                                             long num_inp,
111
                                             STRUCT_DATA *sd,
112
                                             INPUT_PARMS *ip,
113
                                             INCHI_IOSTREAM *inp_file,
114
                                             INCHI_IOSTREAM *log_file,
115
                                             INCHI_IOSTREAM *out_file,
116
                                             INCHI_IOSTREAM *prb_file,
117
                                             ORIG_ATOM_DATA *orig_inp_data,
118
                                             ORIG_ATOM_DATA *prep_inp_data );
119
120
/* Actual worker sitting under ProcessOneStructureEx */
121
int ProcessOneStructureExCore( struct tagINCHI_CLOCK    *ic,
122
                               struct tagCANON_GLOBALS  *CG,
123
                               STRUCT_DATA              *sd,
124
                               INPUT_PARMS              *ip,
125
                               char                     *szTitle,
126
                               PINChI2                  *pINChI2[INCHI_NUM],
127
                               PINChI_Aux2              *pINChI_Aux2[INCHI_NUM],
128
                               INCHI_IOSTREAM           *inp_file,
129
                               INCHI_IOSTREAM           *log_file,
130
                               INCHI_IOSTREAM           *out_file,
131
                               INCHI_IOSTREAM           *prb_file,
132
                               ORIG_ATOM_DATA           *orig_inp_data,
133
                               ORIG_ATOM_DATA           *prep_inp_data,
134
                               long                     num_inp,
135
                               INCHI_IOS_STRING         *strbuf,
136
                               unsigned char            save_opt_bits );
137
138
139
140
static ORIG_STRUCT*
141
OrigAtData_StoreNativeInput( CANON_GLOBALS  *pCG,
142
                             int            *nRet,
143
                             STRUCT_DATA    *sd,
144
                             INPUT_PARMS    *ip,
145
                             ORIG_ATOM_DATA *orig_inp_data,
146
                             ORIG_STRUCT    *pOrigStruct );
147
static void PrepareSaveOptBits( unsigned char *save_opt_bits,
148
                                INPUT_PARMS   *ip );
149
150
static void DisplayOrigAndResultStructuresAndComponents( int nRet,
151
                                                         INCHI_CLOCK    *ic,
152
                                                         CANON_GLOBALS  *pCG,
153
                                                         STRUCT_DATA    *sd,
154
                                                         INPUT_PARMS    *ip,
155
                                                         char           *szTitle,
156
                                                         PINChI2        *pINChI[INCHI_NUM],
157
                                                         PINChI_Aux2    *pINChI_Aux[INCHI_NUM],
158
                                                         INCHI_IOSTREAM *inp_file, INCHI_IOSTREAM *log_file,
159
                                                         INCHI_IOSTREAM *out_file,
160
                                                         ORIG_ATOM_DATA *orig_inp_data,
161
                                                         ORIG_ATOM_DATA *prep_inp_data,
162
                                                         long           num_inp,
163
                                                         int            maxINChI,
164
                                                         COMP_ATOM_DATA composite_norm_data[INCHI_NUM][TAUT_NUM + 1] );
165
static void SaveOkProcessedMolfile( int             nRet,
166
                                    STRUCT_DATA     *sd,
167
                                    INPUT_PARMS     *ip,
168
                                    INCHI_IOSTREAM  *prb_file,
169
                                    INCHI_IOSTREAM  *inp_file );
170
171
static int mark_atoms_to_delete_or_renumber( ORIG_ATOM_DATA *orig_at_data,
172
                                             OAD_StructureEdits *ed,
173
                                             int *at_renum);
174
static int set_renumbered_or_delete( int *number,
175
                                     int *buf,
176
                                     int nelems,
177
                                     int *renum,
178
                                     int base );
179
180
static void swap_atoms_xyz( ORIG_ATOM_DATA *orig_at_data, int ia1, int ia2 );
181
182
/* Callbacks */
183
184
/*  Console user issued CTRL+C etc. */
185
int( *ConsoleQuit )( void ) = NULL;
186
int( *UserAction ) ( void ) = NULL;
187
188
#if (BUILD_WITH_ENG_OPTIONS==1)
189
#if ALLOW_SUBSTRUCTURE_FILTERING==1
190
static int OrigAtData_CheckForSubstructure(ORIG_ATOM_DATA *orig_inp_data);
191
#endif
192
#endif
193
194
195
/**********************************************
196
 * output " L=V" or " L missing" or ""
197
 * The fprintf format string must contain %s%s%s%s
198
 */
199
const char gsMissing[] = "is missing";
200
const char gsEmpty[] = "";
201
const char gsSpace[] = " ";
202
const char gsEqual[] = "=";
203
204
205
206
/****************************************************************************
207
 Process a portion of input data (molecule, InChI string, ...)
208
 in a relevant way (generate InChI, restore molecule by InChI )
209
****************************************************************************/
210
int ProcessOneStructure( INCHI_CLOCK            *ic,
211
                         CANON_GLOBALS          *pCG,
212
                         STRUCT_DATA            *sd,
213
                         INPUT_PARMS            *ip,
214
                         char                   *szTitle,
215
                         PINChI2                *pINChI[INCHI_NUM],
216
                         PINChI_Aux2            *pINChI_Aux[INCHI_NUM],
217
                         INCHI_IOSTREAM         *inp_file,
218
                         INCHI_IOSTREAM         *log_file,
219
                         INCHI_IOSTREAM         *out_file,
220
                         INCHI_IOSTREAM         *prb_file,
221
                         ORIG_ATOM_DATA         *orig_inp_data,
222
                         ORIG_ATOM_DATA         *prep_inp_data,
223
                         long                   num_inp,
224
                         INCHI_IOS_STRING       *strbuf,
225
                         unsigned char          save_opt_bits )
226
41.6k
{
227
41.6k
    int nRet = 0,
228
41.6k
        nRet1, i, k,
229
41.6k
        maxINChI = 0,
230
41.6k
        bSortPrintINChIFlags = 0;
231
41.6k
    COMP_ATOM_DATA
232
41.6k
        composite_norm_data[INCHI_NUM][TAUT_NUM + 1];    /*    [0]:non-taut,
233
                                                        [1]:taut,
234
                                                        [2]:intermediate taut struct */
235
41.6k
    NORM_CANON_FLAGS ncFlags;
236
41.6k
    NORM_CANON_FLAGS *pncFlags = &ncFlags;
237
41.6k
    ORIG_STRUCT OrigStruct;
238
41.6k
    ORIG_STRUCT *pOrigStruct = NULL;
239
41.6k
    int err, ret1 = 0;
240
241
    /* djb-rwth: removing redundant code */
242
243
    /*    1. Preliminary work */
244
245
41.6k
    int is_polymer = orig_inp_data
246
41.6k
                     && orig_inp_data->valid_polymer
247
41.6k
                     && orig_inp_data->polymer
248
41.6k
                     && orig_inp_data->polymer->n ;
249
250
41.6k
    int is_polymer2inchi = is_polymer && ( ip->nInputType == INPUT_MOLFILE || ip->nInputType == INPUT_SDFILE );
251
252
41.6k
    sd->bUserQuitComponent = 0;
253
41.6k
    sd->bUserQuitComponentDisplay = 0;
254
41.6k
    memset( composite_norm_data, 0, sizeof( composite_norm_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
255
41.6k
    memset( pncFlags, 0, sizeof( *pncFlags ) ); /* djb-rwth: memset_s C11/Annex K variant? */
256
257
        
258
    /* For experimental purposes only */
259
    /*ret1 = DoOneStructureEarlyPreprocessing( num_inp, sd, ip, inp_file,
260
                                             log_file, out_file, prb_file,
261
                                             orig_inp_data, prep_inp_data );
262
    */
263
41.6k
    ret1 = DoOneStructureEarlyPreprocessing( ic, pCG, num_inp, sd, ip,
264
41.6k
                                             inp_file, log_file, out_file, prb_file,
265
41.6k
                                             orig_inp_data, prep_inp_data );
266
41.6k
    switch (ret1)
267
41.6k
    {
268
0
        case _IS_SKIP:
269
0
        case _IS_ERROR:
270
0
        case _IS_FATAL:
271
0
            nRet = ret1;
272
41.6k
    }
273
274
41.6k
    if (ret1)
275
0
    {
276
0
        goto exit_function;
277
0
    }
278
279
280
41.6k
    if (is_polymer)
281
0
    {
282
        /* Polymer house-keeping related to possible CRU frame shift(s) */
283
284
0
        orig_inp_data->polymer->frame_shift_scheme = ip->bFrameShiftScheme;
285
0
        orig_inp_data->polymer->treat = ip->bPolymers;
286
287
0
        if (!is_polymer2inchi)
288
0
        {
289
            /* Polymer structure is being restored from InChI string            */
290
            /* If CRUs were pre-cyclized, re-open them in preferred forms here  */
291
0
            if (orig_inp_data->polymer->frame_shift_scheme == FSS_STARS_CYCLED)
292
0
            {
293
0
                OAD_Polymer_SmartReopenCyclizedUnits( orig_inp_data->polymer,
294
0
                                                      orig_inp_data->at,
295
0
                                                      orig_inp_data->num_inp_atoms,
296
0
                                                      &orig_inp_data->num_inp_bonds );
297
0
            }
298
0
        }
299
0
    }
300
301
302
41.6k
    ret1 = OrigAtData_SaveMolfile( orig_inp_data, sd, ip, num_inp, out_file );
303
41.6k
    if (ret1)
304
0
    {
305
0
        goto exit_function;
306
0
    }
307
308
309
41.6k
    pOrigStruct = &OrigStruct;
310
41.6k
    memset( pOrigStruct, 0, sizeof( *pOrigStruct ) ); /* djb-rwth: memset_s C11/Annex K variant? */
311
312
41.6k
    OrigAtData_StoreNativeInput( pCG, &nRet, sd,  ip,  orig_inp_data, pOrigStruct );
313
314
    /*    2. Create INChI for the whole disconnected or original structure */
315
316
41.6k
    if (nRet != _IS_FATAL && nRet != _IS_ERROR)
317
41.6k
    {
318
41.6k
        nRet1 = CreateOneStructureINChI( pCG, ic, sd, ip, szTitle,
319
41.6k
                                         pINChI, pINChI_Aux, INCHI_BAS,
320
41.6k
                                         inp_file, log_file, out_file, prb_file,
321
41.6k
                                         orig_inp_data, prep_inp_data,
322
41.6k
                                         composite_norm_data,
323
41.6k
                                         num_inp, strbuf, pncFlags );
324
41.6k
        nRet = inchi_max( nRet, nRet1 );
325
326
        /* If we create InChI from polymer-containing structure */
327
41.6k
        if (is_polymer2inchi)
328
0
        {
329
0
            int polymer_repr_type = OAD_Polymer_GetRepresentation( orig_inp_data->polymer );
330
331
0
#ifdef ALLOW_MIXED_SRU_AND_MON
332
0
            if (polymer_repr_type == POLYMER_REPRESENTATION_STRUCTURE_BASED ||
333
0
                 polymer_repr_type == POLYMER_REPRESENTATION_MIXED)
334
#else
335
            if (polymer_repr_type == POLYMER_REPRESENTATION_STRUCTURE_BASED)
336
#endif
337
0
            {
338
                /* Temporarily copy ptr to polymer data to prep_inp_data */
339
0
                OAD_Polymer *prep_polymer = prep_inp_data->polymer; /* may be NULL */
340
0
                prep_inp_data->polymer = orig_inp_data->polymer;
341
342
0
                OAD_Polymer_FindBackbones( prep_inp_data, /* NB: not orig_inp_data! */
343
0
                                           &( composite_norm_data[INCHI_BAS][TAUT_YES] ),
344
0
                                           &err, sd->pStrErrStruct );
345
0
                if (err)
346
0
                {
347
0
                    ret1 = _IS_ERROR;
348
0
                }
349
0
                nRet = inchi_max( nRet, ret1 );
350
0
                prep_inp_data->polymer = prep_polymer;    /* restore temp copied*/
351
0
            }
352
0
        }
353
41.6k
    }
354
355
41.6k
    if (nRet != _IS_FATAL && nRet != _IS_ERROR)
356
41.5k
    {
357
41.5k
        maxINChI = 1;
358
41.5k
    }
359
360
361
    /* 3. Create INChI for the whole metal-reconnected structure */
362
363
41.6k
    if (nRet != _IS_FATAL                                              &&
364
41.6k
         nRet != _IS_ERROR &&
365
41.6k
         ( sd->bTautFlagsDone[INCHI_BAS] & TG_FLAG_DISCONNECT_COORD_DONE ) &&
366
41.6k
         ( ip->bTautFlags & TG_FLAG_RECONNECT_COORD ))
367
233
    {
368
369
233
        nRet1 = CreateOneStructureINChI( pCG, ic, sd, ip, szTitle,
370
233
                                         pINChI, pINChI_Aux, INCHI_REC, inp_file,
371
233
                                         log_file, out_file, prb_file,
372
233
                                         orig_inp_data, prep_inp_data,
373
233
                                         composite_norm_data,
374
233
                                         num_inp, strbuf, pncFlags );
375
233
        nRet = inchi_max( nRet, nRet1 );
376
377
233
        if (is_polymer2inchi)
378
0
        {
379
0
            ret1 = 0;
380
            /* temporarily copy ptr to polymer data to prep_inp_data */
381
0
            prep_inp_data->polymer = orig_inp_data->polymer;
382
383
0
            OAD_Polymer_FindBackbones( prep_inp_data, /* NB: not orig_inp_data! */
384
0
                                       &( composite_norm_data[INCHI_REC][TAUT_YES] ),
385
0
                                       &err, sd->pStrErrStruct );
386
0
            if (err)
387
0
            {
388
0
                ret1 = _IS_ERROR;
389
0
            }
390
0
            nRet = inchi_max( nRet, ret1 );
391
0
            prep_inp_data->polymer = NULL;    /* remove temp copied */
392
0
        }
393
233
        if (nRet != _IS_FATAL && nRet != _IS_ERROR)
394
233
        {
395
233
            maxINChI = 2;
396
233
        }
397
233
    }
398
399
41.6k
    if (nRet != _IS_FATAL && nRet != _IS_ERROR)
400
41.5k
    {
401
41.5k
        if (( sd->bChiralFlag & FLAG_INP_AT_CHIRAL ) &&
402
41.5k
            ( ip->nMode & REQ_MODE_STEREO ) &&
403
41.5k
             !( ip->nMode & ( REQ_MODE_RELATIVE_STEREO | REQ_MODE_RACEMIC_STEREO ) ) &&
404
41.5k
             !bIsStructChiral( pINChI, sd->num_components ))
405
0
        {
406
0
            if (!ip->bNoWarnings)
407
0
            {
408
0
                WarningMessage( sd->pStrErrStruct, "Not chiral" );
409
0
            }
410
0
        }
411
41.5k
        if (!sd->bUserQuitComponent && !sd->bUserQuit)
412
41.5k
        {
413
41.5k
            nRet1 = TreatCreateINChIWarning( sd, ip, prep_inp_data, num_inp,
414
41.5k
                                             inp_file, log_file, out_file, prb_file );
415
41.5k
            nRet = inchi_max( nRet, nRet1 );
416
41.5k
        }
417
41.5k
    }
418
419
420
    /*    4. Sort and print INChI for the whole structure */
421
422
41.6k
    PrepareSaveOptBits( &save_opt_bits, ip );
423
41.6k
    if (nRet != _IS_FATAL && nRet != _IS_ERROR)
424
41.5k
    {
425
41.5k
        nRet1 = SortAndPrintINChI( pCG, out_file, strbuf, log_file, ip,
426
41.5k
                                   orig_inp_data, prep_inp_data,
427
41.5k
                                   composite_norm_data,
428
41.5k
                                   pOrigStruct, sd->num_components,
429
41.5k
                                   sd->num_non_taut, sd->num_taut,
430
41.5k
                                   sd->bTautFlags, sd->bTautFlagsDone,
431
41.5k
                                   pncFlags, num_inp,
432
41.5k
                                   pINChI, pINChI_Aux,
433
41.5k
                                   &bSortPrintINChIFlags, save_opt_bits ); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
434
41.5k
    }
435
436
437
    /*    5. Post-process */
438
439
41.6k
    DisplayOrigAndResultStructuresAndComponents( nRet, ic, pCG, sd, ip, szTitle,
440
41.6k
                                                 pINChI, pINChI_Aux,
441
41.6k
                                                 inp_file, log_file, out_file,
442
41.6k
                                                 orig_inp_data, prep_inp_data,
443
41.6k
                                                 num_inp, maxINChI,
444
41.6k
                                                 composite_norm_data );
445
446
447
41.6k
    SaveOkProcessedMolfile( nRet, sd, ip, prb_file, inp_file );
448
449
450
    /* Cleanup */
451
452
124k
    for (i = 0; i < INCHI_NUM; i++)
453
83.2k
    {
454
332k
        for (k = 0; k < TAUT_NUM + 1; k++)
455
249k
        {
456
249k
            FreeCompAtomData( &composite_norm_data[i][k] );
457
249k
        }
458
83.2k
    }
459
460
41.6k
    OrigStruct_Free( pOrigStruct );
461
462
41.6k
exit_function:
463
464
41.6k
    return nRet;
465
41.6k
}
466
467
468
469
/****************************************************************************
470
 Early preprocessing: used if defined
471
    REMOVE_ION_PAIRS_ORIG_STRU or UNDERIVATIZE or RING2CHAIN
472
****************************************************************************/
473
474
475
int DoOneStructureEarlyPreprocessing( INCHI_CLOCK *ic,
476
                                      CANON_GLOBALS *pCG,
477
                                      long num_inp,
478
                                      STRUCT_DATA *sd,
479
                                      INPUT_PARMS *ip,
480
                                      INCHI_IOSTREAM *inp_file,
481
                                      INCHI_IOSTREAM *log_file,
482
                                      INCHI_IOSTREAM *out_file,
483
                                      INCHI_IOSTREAM *prb_file,
484
                                      ORIG_ATOM_DATA *orig_inp_data,
485
                                      ORIG_ATOM_DATA *prep_inp_data )
486
41.6k
{
487
488
41.6k
#if ( RING2CHAIN == 1 || UNDERIVATIZE == 1 )
489
41.6k
    int ret1 = 0, ret2 = 0; /* djb-rwth: removing redundant variables */
490
41.6k
#endif
491
492
#if ( REMOVE_ION_PAIRS_ORIG_STRU == 1 )
493
    fix_odd_things( orig_inp_data->num_inp_atoms, orig_inp_data->at, 0, ip->bFixNonUniformDraw );
494
#endif
495
496
41.6k
#if ( UNDERIVATIZE == 1 )
497
41.6k
    if (ip->bUnderivatize)
498
0
    {
499
0
        if (0 > ( ret2 = OAD_Edit_Underivatize( ic, pCG, orig_inp_data, ( ip->bINChIOutputOptions & INCHI_OUT_SDFILE_ONLY ), ip->bUnderivatize & 2, ip->pSdfValue ) ))
500
0
        {
501
0
            long num_inp2 = num_inp;
502
0
            AddErrorMessage( sd->pStrErrStruct, "Underivatization error" );
503
0
            sd->nStructReadError = 99;
504
0
            sd->nErrorType = _IS_ERROR;
505
0
            TreatErrorsInReadTheStructure( sd, ip, LOG_MASK_ALL, inp_file, log_file, out_file, prb_file,
506
0
                                        prep_inp_data, &num_inp2 );
507
0
            return _IS_ERROR; /* output only if derivatives found */
508
0
        }
509
0
        else if (0 < ret2)
510
0
        {
511
0
            if (!ip->bNoWarnings)
512
0
            {
513
0
                WarningMessage( sd->pStrErrStruct, "Input structure underivatized" );
514
0
            }
515
0
        }
516
0
    }
517
41.6k
#endif /* UNDERIVATIZE == 1 */
518
519
41.6k
#if ( RING2CHAIN == 1 )
520
41.6k
    if (ip->bRing2Chain && 0 > ( ret1 = Ring2Chain( ic, pCG, orig_inp_data ) ))
521
0
    {
522
0
        long num_inp2 = num_inp;
523
0
        AddErrorMessage( sd->pStrErrStruct, "Ring to chain error" );
524
0
        sd->nStructReadError = 99;
525
0
        sd->nErrorType = _IS_ERROR;
526
        /* djb-rwth: removing redundant code */
527
0
        TreatErrorsInReadTheStructure( sd, ip, LOG_MASK_ALL,
528
0
                                       inp_file, log_file,
529
0
                                       out_file, prb_file,
530
0
                                       prep_inp_data, &num_inp2 );
531
0
        return _IS_ERROR; /* output only if derivatives found */
532
0
    }
533
41.6k
#endif /* RING2CHAIN == 1 */
534
41.6k
#if ( RING2CHAIN == 1 || UNDERIVATIZE == 1 )  /***** post v.1 feature *****/
535
41.6k
    if (ip->bIgnoreUnchanged && !ret1 && !ret2)
536
0
    {
537
0
        return _IS_SKIP; /* output only if derivatives or ring/chain found */
538
0
    }
539
41.6k
#endif /* RING2CHAIN == 1 || UNDERIVATIZE == 1 */
540
41.6k
    return 0;
541
41.6k
}
542
543
544
/* If requested, save input data to a Molfile instead of creating INChI                     */
545
/* Also used for output in case of combination of options 'InChI2Struct' and 'OutputSDF'    */
546
int OrigAtData_SaveMolfile( ORIG_ATOM_DATA  *orig_inp_data,
547
                            STRUCT_DATA     *sd,
548
                            INPUT_PARMS     *ip,
549
                            long            num_inp,
550
                            INCHI_IOSTREAM  *out_file )
551
41.6k
{
552
41.6k
    int ret = 0;
553
554
41.6k
    if (!( ip->bINChIOutputOptions & INCHI_OUT_SDFILE_ONLY ))
555
41.6k
    {
556
41.6k
        return _IS_OKAY;
557
41.6k
    }
558
0
    else
559
0
    {
560
0
        char szNumber[256];
561
0
        sprintf(szNumber, "Structure #%ld. %s%s%s%s", num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));
562
0
        ret = OrigAtData_WriteToSDfile( orig_inp_data, out_file, szNumber, NULL,
563
0
                                        ( sd->bChiralFlag&FLAG_INP_AT_CHIRAL ) ? 1 : 0,
564
0
                                        ( ip->bINChIOutputOptions&INCHI_OUT_SDFILE_ATOMS_DT ) ? 1 : 0,
565
0
                                        ip->pSdfLabel, ip->pSdfValue );
566
0
    }
567
568
0
    return ret;
569
41.6k
}
570
571
572
/****************************************************************************
573
 Optionally save native input data as 'OrigStruct' data package
574
****************************************************************************/
575
ORIG_STRUCT * OrigAtData_StoreNativeInput( CANON_GLOBALS    *pCG,
576
                                           int              *nRet,
577
                                           STRUCT_DATA      *sd,
578
                                           INPUT_PARMS      *ip,
579
                                           ORIG_ATOM_DATA   *orig_inp_data,
580
                                           ORIG_STRUCT      *pOrigStruct )
581
41.6k
{
582
583
    /*    v. 1.05 always create and fill OrigStruc as it may be used to store e.g. polymer info    */
584
    /*    If normal AuxInfo is requested, create full reversibility information from native inp data
585
    if ( ip->bINChIOutputOptions & (INCHI_OUT_NO_AUX_INFO | INCHI_OUT_SHORT_AUX_INFO))
586
        return NULL; */
587
588
41.6k
    if (OrigStruct_FillOut( pCG, orig_inp_data, pOrigStruct, sd ))
589
0
    {
590
0
        AddErrorMessage( sd->pStrErrStruct, "Cannot interpret reversibility information" );
591
0
        sd->nStructReadError = 99;
592
0
        sd->nErrorType = _IS_ERROR;
593
0
        *nRet = _IS_ERROR;
594
0
    }
595
596
41.6k
    return pOrigStruct;
597
41.6k
}
598
599
600
/****************************************************************************
601
 Prepare SaveOpt bits
602
****************************************************************************/
603
void PrepareSaveOptBits( unsigned char *save_opt_bits, INPUT_PARMS *ip )
604
41.6k
{
605
41.6k
    if (ip->nInputType != INPUT_INCHI)
606
0
    {
607
0
        *save_opt_bits = 0;
608
0
        if (ip->bINChIOutputOptions & INCHI_OUT_SAVEOPT)
609
0
        {
610
0
            if (0 != ( ip->bTautFlags & TG_FLAG_RECONNECT_COORD ))
611
0
            {
612
0
                ( *save_opt_bits ) |= SAVE_OPT_RECMET;
613
0
            }
614
0
            if (0 != ( ip->nMode & REQ_MODE_BASIC ))
615
0
            {
616
0
                ( *save_opt_bits ) |= SAVE_OPT_FIXEDH;
617
0
            }
618
0
            if (0 != ( ip->nMode & REQ_MODE_DIFF_UU_STEREO ))
619
0
            {
620
0
                ( *save_opt_bits ) |= SAVE_OPT_SLUUD;
621
0
            }
622
0
            if (0 == ( ip->nMode & ( REQ_MODE_SB_IGN_ALL_UU | REQ_MODE_SC_IGN_ALL_UU ) ))
623
0
            {
624
0
                ( *save_opt_bits ) |= SAVE_OPT_SUU;
625
0
            }
626
0
            if (0 != ( ip->bTautFlags & TG_FLAG_KETO_ENOL_TAUT ))
627
0
            {
628
0
                ( *save_opt_bits ) |= SAVE_OPT_KET;
629
0
            }
630
0
            if (0 != ( ip->bTautFlags & TG_FLAG_1_5_TAUT ))
631
0
            {
632
0
                ( *save_opt_bits ) |= SAVE_OPT_15T;
633
0
            }
634
0
            if (0 != (ip->bTautFlags & TG_FLAG_PT_22_00))
635
0
                (*save_opt_bits) |= SAVE_OPT_PT_22_00;
636
0
            if (0 != (ip->bTautFlags & TG_FLAG_PT_16_00))
637
0
                (*save_opt_bits) |= SAVE_OPT_PT_16_00;
638
0
            if (0 != (ip->bTautFlags & TG_FLAG_PT_06_00))
639
0
                (*save_opt_bits) |= SAVE_OPT_PT_06_00;
640
0
            if (0 != (ip->bTautFlags & TG_FLAG_PT_39_00))
641
0
                (*save_opt_bits) |= SAVE_OPT_PT_39_00;
642
0
            if (0 != (ip->bTautFlags & TG_FLAG_PT_13_00))
643
0
                (*save_opt_bits) |= SAVE_OPT_PT_13_00;
644
0
            if (0 != (ip->bTautFlags & TG_FLAG_PT_18_00))
645
0
                (*save_opt_bits) |= SAVE_OPT_PT_18_00;
646
            /* Check if /SNon requested and turn OFF stereo bits if so */
647
0
            if (!( ip->nMode & REQ_MODE_STEREO ))
648
0
            {
649
0
                ( *save_opt_bits ) &= ~SAVE_OPT_SUU;
650
0
                ( *save_opt_bits ) &= ~SAVE_OPT_SLUUD;
651
0
            }
652
0
        }
653
0
    }
654
41.6k
}
655
656
657
/****************************************************************************
658
 Display structures/components on screen
659
****************************************************************************/
660
void DisplayOrigAndResultStructuresAndComponents( int               nRet,
661
                                                  INCHI_CLOCK       *ic,
662
                                                  CANON_GLOBALS     *pCG,
663
                                                  STRUCT_DATA       *sd,
664
                                                  INPUT_PARMS       *ip,
665
                                                  char              *szTitle,
666
                                                  PINChI2           *pINChI[INCHI_NUM],
667
                                                  PINChI_Aux2       *pINChI_Aux[INCHI_NUM],
668
                                                  INCHI_IOSTREAM    *inp_file,
669
                                                  INCHI_IOSTREAM    *log_file,
670
                                                  INCHI_IOSTREAM    *out_file,
671
                                                  ORIG_ATOM_DATA    *orig_inp_data,
672
                                                  ORIG_ATOM_DATA    *prep_inp_data,
673
                                                  long              num_inp,
674
                                                  int               maxINChI,
675
                                                  COMP_ATOM_DATA    composite_norm_data[INCHI_NUM][TAUT_NUM + 1] )
676
41.6k
{
677
678
679
41.6k
    if (ip->bDisplay)    ip->bDisplayCompositeResults = 1;    /* v. 1.05 */
680
681
#ifndef COMPILE_ANSI_ONLY /* { */
682
683
    /* Display equivalent components on original or preprocessed structure(s) */
684
#ifndef TARGET_LIB_FOR_WINCHI
685
    if (nRet != _IS_FATAL && nRet != _IS_ERROR && /*ip->bDisplay &&*/
686
        ( ip->bCompareComponents & CMP_COMPONENTS ) && !sd->bUserQuit && !sd->bUserQuitComponent)
687
    {
688
        int j, ret, ord;
689
        int bDisplaySaved = ip->bDisplay;
690
        ORIG_ATOM_DATA *inp_data;
691
        AT_NUMB         nEquSet;
692
        for (ord = -1; ord < INCHI_NUM; ord++)
693
        {
694
            switch (ord)
695
            {
696
                case -1:
697
                    j = INCHI_BAS;  /* preprocessed non-tautomeric */
698
                    break;
699
                case 0:
700
                    j = INCHI_REC;  /* preprocessed tautomeric */
701
                    break;
702
                case 1:
703
                    j = -1;        /* original input */
704
                    break;
705
                default:
706
                    continue;
707
            }
708
            inp_data = j < 0 ? orig_inp_data : prep_inp_data + j;
709
            if (inp_data && inp_data->num_inp_atoms && inp_data->at &&
710
                 inp_data->nEquLabels &&
711
                 inp_data->nNumEquSets)
712
            {
713
                for (nEquSet = 1; nEquSet <= inp_data->nNumEquSets; nEquSet++)
714
                {
715
                    ip->dp.nEquLabels = inp_data->nEquLabels;
716
                    ip->dp.nCurEquLabel = nEquSet;
717
                    ip->dp.nNumEquSets = inp_data->nNumEquSets;
718
                    ip->bDisplay = 1; /* force display if it was not requested */
719
                    ret = DisplayTheWholeStructure( pCG, ic, sd, ip, szTitle,
720
                                                    inp_file, log_file, inp_data,
721
                                                    num_inp, j, 1 /*bShowStructure*/, 0 );
722
                    ip->dp.nEquLabels = NULL;
723
                    ip->dp.nCurEquLabel = 0;
724
                    ip->dp.nNumEquSets = 0;
725
                    ip->bDisplay = bDisplaySaved; /* restore display option */
726
                    if (ret)
727
                    {
728
            /* user pressed Esc */
729
                        goto exit_loop;
730
                    }
731
                }
732
            }
733
        }
734
    exit_loop:;
735
    }
736
#endif
737
738
    /* Display composite results and equivalent components on composite results */
739
    if (nRet != _IS_FATAL && nRet != _IS_ERROR && /*ip->bDisplay &&*/ ip->bDisplayCompositeResults)
740
    {
741
        int iINChI;
742
        for (iINChI = 0; iINChI < maxINChI && !sd->bUserQuitComponentDisplay; iINChI++)
743
        {
744
            DisplayTheWholeCompositeStructure( pCG, ic, ip, sd, num_inp,
745
                                               iINChI, pINChI[iINChI], pINChI_Aux[iINChI],
746
                                               orig_inp_data, prep_inp_data, composite_norm_data[iINChI] );
747
        }
748
#ifndef TARGET_LIB_FOR_WINCHI
749
        if (!ip->bDisplay && sd->bUserQuitComponentDisplay)
750
        {
751
            sd->bUserQuit = 1;
752
        }
753
#endif
754
    }
755
756
#endif /* } COMPILE_ANSI_ONLY */
757
758
41.6k
    return;
759
41.6k
}
760
761
762
/****************************************************************************
763
 Special mode (option /PGO) : extract all good MOLfiles into the problem file;
764
 do not extract any MOLfile that could not be processed.
765
****************************************************************************/
766
void SaveOkProcessedMolfile( int            nRet,
767
                             STRUCT_DATA    *sd,
768
                             INPUT_PARMS    *ip,
769
                             INCHI_IOSTREAM *prb_file,
770
                             INCHI_IOSTREAM *inp_file )
771
41.6k
{
772
41.6k
    if (ip->bSaveAllGoodStructsAsProblem &&
773
41.6k
         nRet != _IS_FATAL                &&
774
41.6k
         nRet != _IS_ERROR                &&
775
41.6k
         prb_file                         &&
776
41.6k
         prb_file->f &&
777
41.6k
         0L <= sd->fPtrStart              &&
778
41.6k
         sd->fPtrStart < sd->fPtrEnd)
779
0
    {
780
0
        MolfileSaveCopy( inp_file, sd->fPtrStart, sd->fPtrEnd, prb_file->f, 0 );
781
0
    }
782
783
41.6k
    return;
784
41.6k
}
785
786
787
/****************************************************************************
788
 Generate InChI for the whole (multi-component) structure
789
****************************************************************************/
790
int CreateOneStructureINChI( CANON_GLOBALS          *pCG,
791
                             INCHI_CLOCK            *ic,
792
                             STRUCT_DATA            *sd,
793
                             INPUT_PARMS            *ip,
794
                             char                   *szTitle,
795
                             PINChI2                *pINChI2[INCHI_NUM],
796
                             PINChI_Aux2            *pINChI_Aux2[INCHI_NUM],
797
                             int                    iINChI,
798
                             INCHI_IOSTREAM         *inp_file,
799
                             INCHI_IOSTREAM         *log_file,
800
                             INCHI_IOSTREAM         *out_file,
801
                             INCHI_IOSTREAM         *prb_file,
802
                             ORIG_ATOM_DATA         *orig_inp_data,
803
                             ORIG_ATOM_DATA         *prep_inp_data,
804
                             COMP_ATOM_DATA         composite_norm_data2[][TAUT_NUM + 1],
805
                             long                   num_inp,
806
                             INCHI_IOS_STRING   *strbuf,
807
                             NORM_CANON_FLAGS       *pncFlags )
808
41.8k
{
809
41.8k
    int i, j, k, nRet = 0, n = 0l;
810
#if defined (TARGET_EXE_STANDALONE) && defined(_WIN32)
811
    int err_display;
812
#endif
813
814
41.8k
    PINChI2     *pINChI = NULL;
815
41.8k
    PINChI_Aux2 *pINChI_Aux = NULL;
816
817
41.8k
    INP_ATOM_DATA InpCurAtData;
818
41.8k
    INP_ATOM_DATA *inp_cur_data;
819
820
41.8k
    INP_ATOM_DATA InpNormAtData, InpNormTautData;
821
41.8k
    INP_ATOM_DATA *inp_norm_data[TAUT_NUM]; /*  = { &InpNormAtData, &InpNormTautData }; */
822
41.8k
    ORIG_ATOM_DATA *cur_prep_inp_data = prep_inp_data + iINChI;
823
41.8k
    inchiTime      ulTStart;
824
825
    /* Always create info data structures (but do not display them always )
826
    #ifndef COMPILE_ANSI_ONLY
827
    */
828
41.8k
    int            bShowStructure = 0;
829
41.8k
    int            bStructurePreprocessed = 0; /* All changes except disconnection */
830
41.8k
    int            bStructureDisconnected = 0;
831
41.8k
    int            bAlsoOutputReconnected = 0, bINCHI_LIB_Flag = 0;
832
41.8k
    COMP_ATOM_DATA *composite_norm_data = composite_norm_data2[iINChI];
833
41.8k
    INP_ATOM_DATA2 *all_inp_norm_data = NULL;
834
    /*#endif*/
835
836
    /*        Order of actions:
837
838
        if ( orig_inp_data is NOT empty AND
839
             prep_inp_data[0] IS empty ) then do
840
             in PreprocessOneStructure()        :
841
842
            1. copy orig_inp_data --> prep_inp_data[0]
843
            2. fix odd things in prep_inp_data[0]
844
            3. if( orig_inp_data->bDisconnectSalts ) then
845
                  -- disconnect salts in prep_inp_data[0]
846
            4. move protons to neutralize charges on heteroatoms
847
            5. if( orig_inp_data->bDisconnectCoord ) then
848
                  -- copy prep_inp_data[0] --> prep_inp_data[1]
849
                  -- disconnect metals in prep_inp_data[0]
850
851
        iINChI = 0
852
        =========
853
        (normal/disconnected layer)
854
855
            1. normalize prep_inp_data[0] in inp_norm_data[0,1]
856
            2. create INChI[ iINChI ] out of inp_norm_data[0,1]
857
858
859
        iINChI = 1 AND orig_inp_data->bDisconnectCoord > 0
860
        =================================================
861
        (reconnected layer)
862
863
            1. normalize prep_inp_data[1] in inp_norm_data[0,1]
864
            2. create INChI[ iINChI ] out of inp_norm_data[0,1]
865
866
    */
867
868
41.8k
    ip->msec_LeftTime = ip->msec_MaxTime; /* start timeout countdown for each component */
869
870
41.8k
    inp_cur_data = &InpCurAtData;
871
41.8k
    inp_norm_data[TAUT_NON] = &InpNormAtData;
872
41.8k
    inp_norm_data[TAUT_YES] = &InpNormTautData;
873
874
41.8k
    memset( inp_cur_data, 0, sizeof( *inp_cur_data ) ); /* djb-rwth: memset_s C11/Annex K variant? */
875
41.8k
    memset( inp_norm_data[TAUT_NON], 0, sizeof( *inp_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
876
41.8k
    memset( inp_norm_data[TAUT_YES], 0, sizeof( *inp_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
877
878
41.8k
    {
879
        /*#ifndef COMPILE_ANSI_ONLY*/
880
41.8k
        memset( composite_norm_data + TAUT_NON, 0, sizeof( composite_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
881
41.8k
        memset( composite_norm_data + TAUT_YES, 0, sizeof( composite_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
882
41.8k
        memset( composite_norm_data + TAUT_INI, 0, sizeof( composite_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
883
41.8k
    }   /*#endif*/
884
885
41.8k
    if (ip->bAllowEmptyStructure && !orig_inp_data->at && !orig_inp_data->num_inp_atoms)
886
0
    {
887
0
        ;
888
0
    }
889
41.8k
    else if (!orig_inp_data->at || !orig_inp_data->num_inp_atoms)
890
0
    {
891
0
        return 0; /* nothing to do */
892
0
    }
893
41.8k
    if (iINChI == 1 && orig_inp_data->bDisconnectCoord <= 0)
894
0
    {
895
0
        return 0;
896
0
    }
897
898
    /* m = iINChI; */ /* orig_inp_data index */
899
41.8k
    if (iINChI != INCHI_BAS && iINChI != INCHI_REC)
900
0
    {
901
0
        AddErrorMessage( sd->pStrErrStruct, "Fatal undetermined program error" );
902
0
        sd->nStructReadError = 97;
903
0
        nRet = sd->nErrorType = _IS_FATAL;
904
0
        inchi_free(all_inp_norm_data); /* djb-rwth: avoiding memory leak */
905
0
        goto exit_function;
906
0
    }
907
908
    /*******************************************************************
909
     *                                                                 *
910
     *                                                                 *
911
     *  Whole structure preprocessing: 1st step of the normalization   *
912
     *                                                                 *
913
     *  Happen only on the first call to CreateOneStructureINChI()      *
914
     *                                                                 *
915
     *                                                                 *
916
     *******************************************************************/
917
918
41.8k
    if (( !prep_inp_data->at || !prep_inp_data->num_inp_atoms ) &&
919
41.8k
         orig_inp_data->num_inp_atoms > 0)
920
41.6k
    {
921
        /* The structure has not been preprocessed */
922
41.6k
        if (ip->msec_MaxTime)
923
0
        {
924
0
            InchiTimeGet( &ulTStart );
925
0
        }
926
927
41.6k
        PreprocessOneStructure( ic, sd, ip, orig_inp_data, prep_inp_data );
928
929
41.6k
        pncFlags->bTautFlags[iINChI][TAUT_YES] =
930
41.6k
                pncFlags->bTautFlags[iINChI][TAUT_NON] =
931
41.6k
                    sd->bTautFlags[INCHI_BAS] | ip->bTautFlags;
932
933
41.6k
        pncFlags->bTautFlagsDone[iINChI][TAUT_YES] =
934
41.6k
            pncFlags->bTautFlagsDone[iINChI][TAUT_NON] =
935
41.6k
            sd->bTautFlagsDone[INCHI_BAS] | ip->bTautFlagsDone;
936
937
41.6k
        {
938
            /*#ifndef COMPILE_ANSI_ONLY*/
939
            /* in this location the call happens once for each input structure, before preprocessing */
940
41.6k
            bStructurePreprocessed = ( 0 != ( sd->bTautFlagsDone[INCHI_BAS] & (
941
41.6k
                TG_FLAG_MOVE_HPLUS2NEUTR_DONE |
942
41.6k
                TG_FLAG_DISCONNECT_SALTS_DONE |
943
41.6k
                TG_FLAG_MOVE_POS_CHARGES_DONE |
944
41.6k
                TG_FLAG_FIX_ODD_THINGS_DONE ) ) );
945
946
41.6k
            bStructureDisconnected = ( 0 != ( sd->bTautFlagsDone[INCHI_BAS] & TG_FLAG_DISCONNECT_COORD_DONE ) );
947
948
41.6k
            bShowStructure = ( bStructurePreprocessed ||
949
41.6k
                               bStructureDisconnected ||
950
41.6k
                               prep_inp_data[0].num_components > 1 );
951
952
            /* sd->bTautFlags[] contains output flags
953
               ip->bTautFlags   contains input flags
954
            */
955
41.6k
            bAlsoOutputReconnected = ( sd->bTautFlagsDone[INCHI_BAS] & TG_FLAG_DISCONNECT_COORD_DONE ) &&
956
41.6k
                ( ip->bTautFlags               & TG_FLAG_RECONNECT_COORD );
957
41.6k
            bINCHI_LIB_Flag = 0;
958
959
            /*************** output structures to TARGET_LIB_FOR_WINCHI conditions *********************
960
             *
961
             *  Send to TARGET_LIB_FOR_WINCHI:
962
             *
963
             *  type                      component  conditions
964
             *
965
             *  COMPONENT_ORIGINAL              #0:  (num_components > 1)
966
             *  COMPONENT_ORIGINAL_PREPROCESSED #0:  (num_components > 1) && (preprocessed)
967
             *  COMPONENT_ORIGINAL              #1:  (num_components = 1) && (preprocessed)
968
             *
969
             *  Flags explanation:
970
             *        MAIN => iINChI=0,  RECN => iINChI=1 (Reconnected)
971
             *        ORIG => Original, PREP => Preprocessed
972
             *
973
             *  Possible flags:           k
974
             *
975
             *  COMP_ORIG_0_MAIN  0x0001  0  COMPONENT_ORIGINAL, bMain, component #0
976
             *  COMP_ORIG_0_RECN  0x0002  1  COMPONENT_ORIGINAL, bRecn, component #0
977
             *
978
             *  COMP_PREP_0_MAIN  0x0004  2  COMPONENT_ORIGINAL_PREPROCESSED, bMain, component #0
979
             *  COMP_PREP_0_RECN  0x0008  3  COMPONENT_ORIGINAL_PREPROCESSED, bRecn, component #0
980
             *
981
             *  COMP_ORIG_1_MAIN  0x0010  4  COMPONENT_ORIGINAL, bMain, component #1
982
             *  COMP_ORIG_1_RECN  0x0020  5  COMPONENT_ORIGINAL, bRecn, component #1
983
             *
984
             *  bReconnected  = k%2     (0 or 1)
985
             *  nComponent    = k/4     (0 or 1)
986
             *  bPreprocessed = (k/2)%2 (0 or 1)
987
             *
988
             ******************************************************************************/
989
990
            /* Original -> Main, component #0, Original */
991
41.6k
            if (prep_inp_data[INCHI_BAS].num_components > 1)
992
238
            {
993
238
                bINCHI_LIB_Flag |= COMP_ORIG_0_MAIN;
994
238
            }
995
41.3k
            else
996
41.3k
            {
997
                /* Original -> Main, component #1, Original */
998
41.3k
                if (prep_inp_data[INCHI_BAS].num_components == 1 && bStructurePreprocessed)
999
49
                {
1000
49
                    bINCHI_LIB_Flag |= COMP_ORIG_1_MAIN;
1001
                    /* preprocessed will be added when output canonicalization results */
1002
49
                }
1003
41.3k
            }
1004
1005
41.6k
            if (bAlsoOutputReconnected)
1006
234
            {
1007
                /* Original -> Reconnected, component #0, Original */
1008
234
                if (prep_inp_data[INCHI_REC].num_components > 1)
1009
0
                {
1010
0
                    bINCHI_LIB_Flag |= COMP_ORIG_0_RECN;
1011
0
                }
1012
234
                else if (prep_inp_data[INCHI_BAS].num_components == 1 && bStructurePreprocessed)
1013
0
                {
1014
                    /* Original -> Reconnected, component #1, Original */
1015
0
                    bINCHI_LIB_Flag |= COMP_ORIG_1_RECN;
1016
                    /* preprocessed will be added when output canonicalization results */
1017
0
                }
1018
234
            }
1019
41.6k
            if (ip->msec_MaxTime)
1020
0
            {
1021
0
                ip->msec_LeftTime -= InchiTimeElapsed( ic, &ulTStart );
1022
0
            }
1023
1024
            /* display the ORIGINAL, UN-PREPROCESSED structure */
1025
1026
41.6k
            if (ip->bDisplay)
1027
0
            {
1028
0
                if (DisplayTheWholeStructure( pCG, ic, sd, ip, szTitle,
1029
0
                    inp_file, log_file, orig_inp_data, num_inp,
1030
0
                    -1, bShowStructure, bINCHI_LIB_Flag ))
1031
0
                {
1032
0
                    inchi_free(all_inp_norm_data); /* djb-rwth: avoiding memory leak */
1033
0
                    goto exit_function;
1034
0
                }
1035
0
            }
1036
41.6k
        } /*#endif */
1037
1038
41.6k
        switch (sd->nErrorType)
1039
41.6k
        {
1040
0
            case _IS_ERROR:
1041
0
            case _IS_FATAL:
1042
                /* error message */
1043
0
                nRet = TreatErrorsInReadTheStructure( sd, ip,
1044
0
                                                      LOG_MASK_ALL,
1045
0
                                                      inp_file, log_file, out_file, prb_file,
1046
0
                                                      prep_inp_data, &num_inp );
1047
0
                goto exit_cycle;
1048
41.6k
        }
1049
41.6k
    }
1050
    /* tranfer flags from INChI_Aux to sd */
1051
1052
1053
41.8k
    {
1054
        /*#ifndef COMPILE_ANSI_ONLY */ /* { */
1055
1056
        /******************************************/
1057
        /*      Displaying the structures         */
1058
        /*          Only under WIN32              */
1059
        /******************************************/
1060
41.8k
        if ( /* ip->bDisplayCompositeResults && !sd->bUserQuitComponentDisplay && */
1061
41.8k
             prep_inp_data[iINChI].num_components > 1
1062
41.8k
           )
1063
238
        {
1064
238
            all_inp_norm_data = (INP_ATOM_DATA2 *) inchi_calloc( prep_inp_data[iINChI].num_components, sizeof( all_inp_norm_data[0] ) );
1065
238
        }
1066
1067
        /* Display the input structure AFTER PREPROCESSING */
1068
41.8k
        switch (iINChI)
1069
41.8k
        {
1070
41.6k
            case INCHI_BAS:
1071
                /*------------ Possibly disconnected structure -------------------*/
1072
41.6k
                bStructurePreprocessed = 0 != ( sd->bTautFlagsDone[iINChI] & (
1073
41.6k
                    TG_FLAG_MOVE_HPLUS2NEUTR_DONE |
1074
41.6k
                    TG_FLAG_DISCONNECT_SALTS_DONE |
1075
41.6k
                    TG_FLAG_MOVE_POS_CHARGES_DONE |
1076
41.6k
                    TG_FLAG_MOVE_CHARGE_COORD_DONE |
1077
41.6k
                    TG_FLAG_DISCONNECT_COORD_DONE |
1078
41.6k
                    TG_FLAG_FIX_ODD_THINGS_DONE ) );
1079
41.6k
                bINCHI_LIB_Flag = 0;
1080
                /* Preprocessed/Main -> Main, component #0, Preprocessed */
1081
41.6k
                if (prep_inp_data[iINChI].num_components > 1 &&
1082
41.6k
                     bStructurePreprocessed)
1083
234
                {
1084
234
                    bINCHI_LIB_Flag |= COMP_PREP_0_MAIN;
1085
234
                }
1086
41.6k
                bShowStructure = ( bStructurePreprocessed &&
1087
41.6k
                                   prep_inp_data[iINChI].num_components > 1 );
1088
41.6k
                break;
1089
1090
233
            case INCHI_REC:
1091
                /*------------ Reconnected structure ------------------------------*/
1092
233
                bAlsoOutputReconnected =
1093
233
                    ( sd->bTautFlagsDone[INCHI_BAS] & TG_FLAG_DISCONNECT_COORD_DONE ) &&
1094
233
                    ( ip->bTautFlags               & TG_FLAG_RECONNECT_COORD );
1095
1096
233
                if (!bAlsoOutputReconnected)
1097
0
                {
1098
0
                    break;
1099
0
                }
1100
1101
233
                bStructurePreprocessed = 0 != ( sd->bTautFlagsDone[iINChI] & (
1102
233
                    TG_FLAG_MOVE_HPLUS2NEUTR_DONE |
1103
233
                    TG_FLAG_DISCONNECT_SALTS_DONE |
1104
233
                    TG_FLAG_MOVE_POS_CHARGES_DONE |
1105
233
                    TG_FLAG_FIX_ODD_THINGS_DONE ) );
1106
233
                bINCHI_LIB_Flag = 0;
1107
                /* Preprocessed/Reconnected -> Reconnected, component #0, Preprocessed */
1108
233
                if (prep_inp_data[iINChI].num_components > 1 && bStructurePreprocessed)
1109
0
                {
1110
0
                    bINCHI_LIB_Flag |= COMP_PREP_0_RECN;
1111
0
                }
1112
233
                bShowStructure = ( bStructurePreprocessed &&
1113
233
                                   prep_inp_data[iINChI].num_components > 1 );
1114
233
                break;
1115
1116
0
            default:
1117
0
                bShowStructure = 0;
1118
41.8k
        }
1119
1120
1121
41.8k
        if (ip->bDisplay && prep_inp_data[iINChI].num_inp_atoms > 0)
1122
0
        {
1123
0
            if (DisplayTheWholeStructure( pCG, ic, sd, ip, szTitle,
1124
0
                inp_file, log_file,
1125
0
                prep_inp_data + iINChI,
1126
0
                num_inp,
1127
0
                iINChI,
1128
0
                bShowStructure,
1129
0
                bINCHI_LIB_Flag ))
1130
0
            {
1131
0
                inchi_free(all_inp_norm_data); /* djb-rwth: avoiding memory leak */
1132
0
                goto exit_function;
1133
0
            }
1134
0
        }
1135
41.8k
    } /* #endif */ /* } ifndef COMPILE_ANSI_ONLY */
1136
1137
1138
    /* allocate pINChI[iINChI] and pINChI_Aux2[iINChI] -- arrays of pointers to INChI and INChI_Aux */
1139
    /* assign values to sd->num_components[]                                                  */
1140
    
1141
    /* djb-rwth: MYREALLOC2 has been replaced and the whole block rewritten to address memory leaks and reading from freed memory locations */
1142
41.8k
    do {
1143
41.8k
        if( (sd->num_components[iINChI]) <= ((long long)cur_prep_inp_data->num_components) ) {
1144
41.8k
            PINChI2* newPTR1 = (PINChI2*)inchi_calloc( ((long long)cur_prep_inp_data->num_components)+1, sizeof(PINChI2) );
1145
41.8k
            PINChI_Aux2* newPTR2 = (PINChI_Aux2*)inchi_calloc( ((long long)cur_prep_inp_data->num_components)+1, sizeof(PINChI_Aux2) );
1146
41.8k
            if ( newPTR1 && newPTR2 ) {
1147
41.8k
                if ( (pINChI2[iINChI]) && (sd->num_components[iINChI]) > 0 )
1148
0
                    memcpy(newPTR1, pINChI2[iINChI], (sd->num_components[iINChI]) * sizeof(PINChI2));
1149
41.8k
                if ((pINChI_Aux2[iINChI]) && (sd->num_components[iINChI]) > 0)
1150
0
                    memcpy(newPTR2, pINChI_Aux2[iINChI], (sd->num_components[iINChI]) * sizeof(PINChI_Aux2));
1151
41.8k
                if (pINChI2[iINChI])
1152
0
                    inchi_free(pINChI2[iINChI]);
1153
41.8k
                if (pINChI_Aux2[iINChI])
1154
0
                    inchi_free(pINChI_Aux2[iINChI]);
1155
41.8k
                pINChI2[iINChI] = newPTR1;
1156
41.8k
                pINChI_Aux2[iINChI] = newPTR2;
1157
41.8k
                sd->num_components[iINChI] = cur_prep_inp_data->num_components;
1158
41.8k
                k = 0;
1159
41.8k
            }
1160
0
            else {
1161
0
                inchi_free(newPTR1);
1162
0
                inchi_free(newPTR2);
1163
0
                k = 1;
1164
0
            }
1165
41.8k
        }
1166
0
        else { k = 0; }
1167
41.8k
    } while (0);
1168
1169
41.8k
    if (k)
1170
0
    {
1171
0
        AddErrorMessage( sd->pStrErrStruct, "Cannot allocate output data. Terminating" );
1172
0
        sd->nStructReadError = 99;
1173
0
        sd->nErrorType = _IS_FATAL;
1174
0
        inchi_free(all_inp_norm_data); /* djb-rwth: avoiding memory leak */
1175
0
        goto exit_function;
1176
0
    }
1177
1178
41.8k
    pINChI = pINChI2[iINChI];
1179
41.8k
    pINChI_Aux = pINChI_Aux2[iINChI];
1180
1181
    /**************************************************************************/
1182
    /*                                                                        */
1183
    /*                                                                        */
1184
    /*   M A I N   C Y C L E:   P R O C E S S    C O M P O N E N T S          */
1185
    /*                                                                        */
1186
    /*                                                                        */
1187
    /*                     O N E   B Y   O N E                                */
1188
    /*                                                                        */
1189
    /*                                                                        */
1190
    /**************************************************************************/
1191
1192
41.8k
    for (i = 0, nRet = 0;
1193
107k
            !sd->bUserQuitComponent && i < cur_prep_inp_data->num_components;
1194
65.8k
                i++)
1195
65.8k
    {
1196
65.8k
        if (ip->msec_MaxTime)
1197
0
        {
1198
0
            InchiTimeGet( &ulTStart );
1199
0
        }
1200
1201
65.8k
#ifndef TARGET_LIB_FOR_WINCHI  /* { */
1202
65.8k
#if ( bREUSE_INCHI == 1 )
1203
1204
65.8k
        if ((iINChI == INCHI_REC &&
1205
             /*( !ip->bDisplay &&
1206
               !ip->bDisplayCompositeResults && */
1207
65.8k
               !( ip->bCompareComponents & CMP_COMPONENTS )) ||
1208
65.8k
               sd->bUserQuitComponentDisplay) /* djb-rwth: addressing LLVM warning */
1209
233
        {
1210
            /* Reconnected structure (06-20-2005: added "&& !ip->bDisplayCompositeResults" to display composite structure) */
1211
233
            int m = iINChI - 1;
1212
1213
            /* Find whether we have already calculated this INChI in basic (disconnected) layer */
1214
782
            for (j = n = 0; j < prep_inp_data[m].num_components; j++)
1215
549
            {
1216
549
                if (i + 1 == prep_inp_data[m].nOldCompNumber[j] &&
1217
549
                    ( pINChI2[m][j][TAUT_NON] || pINChI2[m][j][TAUT_YES] ))
1218
0
                {
1219
                    /* Yes, we have already done this */
1220
0
                    if (!n++)
1221
0
                    {
1222
0
                        memcpy(pINChI + i, pINChI2[m] + j, sizeof(pINChI[0]));
1223
0
                        memcpy(pINChI_Aux + i, pINChI_Aux2[m] + j, sizeof(pINChI_Aux[0]));
1224
0
                        for (k = 0; k < TAUT_NUM; k++)
1225
0
                        {
1226
0
                            if (pINChI[i][k])
1227
0
                            {
1228
0
                                pINChI[i][k]->nRefCount++;
1229
0
                                if (pINChI[i][k]->nNumberOfAtoms > 0)
1230
0
                                {
1231
0
                                    switch (k)
1232
0
                                    {
1233
0
                                        case TAUT_NON:
1234
0
                                            sd->num_non_taut[iINChI] ++;
1235
0
                                            break;
1236
0
                                        case TAUT_YES:
1237
0
                                            if (pINChI[i][k]->lenTautomer > 0)
1238
0
                                            {
1239
0
                                                sd->num_taut[iINChI] ++;
1240
0
                                            }
1241
0
                                            else
1242
0
                                                if (!pINChI[i][TAUT_NON] ||
1243
0
                                                     !pINChI[i][TAUT_NON]->nNumberOfAtoms)
1244
0
                                                {
1245
0
                                                    sd->num_non_taut[iINChI] ++;
1246
0
                                                }
1247
0
                                            break;
1248
0
                                    }
1249
0
                                }
1250
0
                            }
1251
0
                            if (pINChI_Aux[i][k])
1252
0
                            {
1253
0
                                pINChI_Aux[i][k]->nRefCount++;
1254
0
                            }
1255
0
                        }
1256
0
                    }
1257
0
                }
1258
549
            }
1259
1260
233
            if (n == 1)
1261
0
            {
1262
0
                continue;
1263
0
            }
1264
233
            if (n > 1)
1265
0
            {
1266
                /* ith component is equivalent to more than one another component */
1267
0
                AddErrorMessage( sd->pStrErrStruct, "Cannot distinguish components" );
1268
0
                sd->nStructReadError = 99;
1269
0
                sd->nErrorType = _IS_ERROR;
1270
0
                inchi_free(all_inp_norm_data); /* djb-rwth: avoiding memory leak */
1271
0
                goto exit_function;
1272
0
            }
1273
233
        }
1274
1275
65.8k
#endif
1276
65.8k
#endif /* } TARGET_LIB_FOR_WINCHI */
1277
1278
        /*****************************************************/
1279
        /*  a) Allocate memory and extract current component */
1280
        /*****************************************************/
1281
1282
65.8k
        nRet = GetOneComponent( ic, sd, ip,
1283
65.8k
                                log_file, out_file,
1284
65.8k
                                inp_cur_data, cur_prep_inp_data,
1285
65.8k
                                i, num_inp );
1286
1287
65.8k
        if (ip->msec_MaxTime)
1288
0
        {
1289
0
            ip->msec_LeftTime -= InchiTimeElapsed( ic, &ulTStart );
1290
0
        }
1291
1292
65.8k
        switch (nRet)
1293
65.8k
        {
1294
0
            case _IS_ERROR:
1295
0
            case _IS_FATAL:
1296
0
                goto exit_cycle;
1297
65.8k
        }
1298
1299
#if !defined(TARGET_API_LIB) && !defined(COMPILE_ANSI_ONLY)
1300
        /*  console request: Display the component? */
1301
        if (ip->bDisplay && inp_file->f != stdin)
1302
        {
1303
            if (user_quit( ic, "Enter=Display Component, Esc=Stop ?", ip->ulDisplTime ))
1304
            {
1305
                sd->bUserQuitComponent = 1;
1306
                break;
1307
            }
1308
        }
1309
#endif
1310
1311
        /*#ifndef COMPILE_ANSI_ONLY  
1312
        { */
1313
1314
        /*  b) Display the extracted original component structure */
1315
65.8k
        if (ip->bDisplay && inp_cur_data->at && !sd->bUserQuitComponentDisplay)
1316
0
        {
1317
0
            if (cur_prep_inp_data->num_components == 1)
1318
0
            {
1319
0
                sprintf(szTitle, "%sInput Structure #%ld.%s%s%s%s%s",
1320
0
                    bStructurePreprocessed ? "Preprocessed " : "",
1321
0
                    num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), iINChI ? " (Reconnected)" : "");
1322
0
            }
1323
0
            else
1324
0
            {
1325
0
                sprintf(szTitle, "Component #%d of %d, Input Structure #%ld.%s%s%s%s%s",
1326
0
                    i + 1, cur_prep_inp_data->num_components,
1327
0
                    num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), iINChI ? " (Reconnected)" : "");
1328
0
            }
1329
1330
#if defined (TARGET_EXE_STANDALONE) && defined(_WIN32)
1331
            err_display = DisplayStructure( pCG,
1332
                                    inp_cur_data->at,
1333
                                    inp_cur_data->num_at,
1334
                                    NULL, /* OAD_Polymer *polymer, */
1335
                                    0,
1336
                                    1,
1337
                                    0,
1338
                                    NULL,
1339
                                    1           /*isotopic*/,
1340
                                    0           /*taut*/,
1341
                                    NULL,
1342
                                    NULL,
1343
                                    ip->bAbcNumbers,
1344
                                    &ip->dp,
1345
                                    ip->nMode,
1346
                                    szTitle );
1347
1348
            sd->bUserQuitComponentDisplay = (err_display == ESC_KEY );
1349
1350
            if (!err_display)
1351
            {
1352
                inchi_fprintf( stderr, "Cannot display the structure\n" );
1353
            }
1354
#endif
1355
#ifdef TARGET_LIB_FOR_WINCHI
1356
            if (DRAWDATA && DRAWDATA_EXISTS)
1357
            {
1358
                struct DrawData vDrawData;
1359
                int    nType = COMPONENT_ORIGINAL;
1360
                vDrawData.pWindowData = CreateWinData_( pCG,
1361
                                                        inp_cur_data->at,
1362
                                                        inp_cur_data->num_at,
1363
                                                        0,
1364
                                                        1 /* bAdd_DT_to_num_H */,
1365
                                                        0,
1366
                                                        NULL,
1367
                                                        1 /* display isotopic if present */,
1368
                                                        0,
1369
                                                        NULL,
1370
                                                        NULL,
1371
                                                        ip->bAbcNumbers,
1372
                                                        &ip->dp,
1373
                                                        ip->nMode );
1374
                if (vDrawData.pWindowData != NULL)
1375
                {
1376
                    if (DRAWDATA_EXISTS( i + 1, nType, iINChI ))
1377
                    {
1378
                        /* i = component number */
1379
                        nType = COMPONENT_ORIGINAL_PREPROCESSED;
1380
                    }
1381
                    vDrawData.nComponent = i + 1;
1382
                    vDrawData.nType = nType;
1383
                    vDrawData.bReconnected = iINChI; /* 0=>main; 1=>reconnected */
1384
                    vDrawData.szTitle = inchi__strdup( szTitle );
1385
                    vDrawData.pWindowData->szTitle = inchi__strdup( szTitle );
1386
                    DRAWDATA( &vDrawData );
1387
                }
1388
            }
1389
#endif
1390
0
        }
1391
        /*#endif */  /* } COMPILE_ANSI_ONLY */
1392
1393
1394
        /*******************************************************************************/
1395
        /*                                                                             */
1396
        /*  N O R M A L I Z A T I O N    a n d     C A N O N I C A L I Z A T I O N     */
1397
        /*                                                                             */
1398
        /*         (both tautomeric and non-tautomeric if requested)                   */
1399
        /*                                                                             */
1400
        /*******************************************************************************/
1401
        /*  c) Create the component's INChI ( copies ip->bTautFlags into sd->bTautFlags)*/
1402
        /*******************************************************************************/
1403
1404
65.8k
        nRet = CreateOneComponentINChI( pCG, ic, sd, ip,
1405
65.8k
                                        inp_cur_data, orig_inp_data,
1406
65.8k
                                        pINChI/*2[iINChI]*/,
1407
65.8k
                                        pINChI_Aux/*2[iINChI]*/,
1408
65.8k
                                        iINChI, i, num_inp,
1409
65.8k
                                        inp_norm_data, pncFlags, log_file );
1410
1411
1412
1413
        /*  d) Display one component structure and/or INChI results only if there was no error */
1414
1415
        /* #ifndef COMPILE_ANSI_ONLY */ /* { */
1416
65.8k
        if (!nRet)
1417
65.8k
        {
1418
            /*  output one component INChI to the stdout if requested */
1419
            /*
1420
            if ( ip->bDisplayEachComponentINChI ) {
1421
                int cur_num_non_taut = (pINChI[i][TAUT_NON] && pINChI[i][TAUT_NON]->nNumberOfAtoms>0);
1422
                int cur_num_taut     = (pINChI[i][TAUT_YES] && pINChI[i][TAUT_YES]->nNumberOfAtoms>0);
1423
                if ( ip->bDisplayEachComponentINChI && cur_num_non_taut + cur_num_taut ) {
1424
                    SortAndPrintINChI( pCG, stdout, pStr, nStrLen, NULL,
1425
                                       ip, 1, cur_num_non_taut, cur_num_taut,
1426
                                       num_inp, pINChI+i, pINChI_Aux+i,
1427
                                       save_opt_bits);
1428
                }
1429
            }
1430
            */
1431
            /**************************************************************************
1432
             * display from one up to 4 structure pictures-results for each component *
1433
             * Enable buttons:                                                        *
1434
             * BN (non-tautomeric non-isotopic): inp_norm_data[0]->bExists            *
1435
             * TN (tautomeric non-isotopic):     inp_norm_data[1]->bExists            *
1436
             * BI (non-tautomeric isotopic):     inp_norm_data[0]->bExists &&         *
1437
             *                                   inp_norm_data[0]->bHasIsotopicLayer  *
1438
             * TI (tautomeric isotopic):         inp_norm_data[1]->bExists &&         *
1439
             *                                   inp_norm_data[1]->bHasIsotopicLayer  *
1440
             **************************************************************************/
1441
1442
65.8k
            int bIsotopic, bTautomeric, bDisplayTaut, bHasIsotopicLayer, bFixedBondsTaut, m_max, m, nNumDisplayedFixedBondTaut = 0; /* djb-rwth: ignoring LLVM warning: variable used */
1443
1444
65.8k
            for ( j = 0;
1445
65.8k
                  ip->bDisplay && !sd->bUserQuitComponentDisplay && j < TAUT_NUM;
1446
65.8k
                  j++)
1447
0
            {
1448
0
                if (inp_norm_data[j]->bExists && !inp_norm_data[j]->bDeleted)
1449
0
                {
1450
0
                    bTautomeric = ( pINChI[i][j]->lenTautomer > 0 );
1451
                     /* same as (inp_norm_data[j]->bTautomeric > 0) */
1452
1453
                    /* If requested tautomeric and no tautmerism found then do not say mobile or fixed H. 2004-10-27 */
1454
0
                    bDisplayTaut = ( !( ip->nMode & REQ_MODE_BASIC ) && !bTautomeric ) ? -1 : bTautomeric;
1455
0
                    bHasIsotopicLayer = ( inp_norm_data[j]->bHasIsotopicLayer > 0 );
1456
1457
0
                    for (k = 0; k <= bHasIsotopicLayer; k++)
1458
0
                    {
1459
0
                        bIsotopic = ( k > 0 );
1460
0
                        m_max = inp_norm_data[j]->at_fixed_bonds && inp_norm_data[j]->bTautPreprocessed ? 1 : 0;
1461
0
                        for (m = m_max; 0 <= m; m--)
1462
0
                        {
1463
0
                            bFixedBondsTaut = ( m > 0 );
1464
0
                            nNumDisplayedFixedBondTaut += bFixedBondsTaut;
1465
                                /* display only one time */
1466
1467
                            /*  Added number of components, added another format for a single component case - DCh */
1468
0
                            if (cur_prep_inp_data->num_components > 1)
1469
0
                            {
1470
0
                                sprintf(szTitle, "%s Component #%d of %d, Structure #%ld%s%s.%s%s%s%s%s",
1471
0
                                    bFixedBondsTaut ? "Preprocessed" : "Result for",
1472
0
                                    i + 1, cur_prep_inp_data->num_components, num_inp,
1473
0
                                    bDisplayTaut == 1 ? ", mobile H" : bDisplayTaut == 0 ? ", fixed H" : "",
1474
0
                                    bIsotopic ? ", isotopic" : "",
1475
0
                                    SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), iINChI ? " (Reconnected)" : "");
1476
0
                            }
1477
0
                            else
1478
0
                            {
1479
0
                                sprintf(szTitle, "%s Structure #%ld%s%s.%s%s%s%s%s",
1480
0
                                    bFixedBondsTaut ? "Preprocessed" : "Result for",
1481
0
                                    num_inp,
1482
0
                                    bDisplayTaut == 1 ? ", mobile H" : bDisplayTaut == 0 ? ", fixed H" : "",
1483
0
                                    bIsotopic ? ", isotopic" : "",
1484
0
                                    SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), iINChI ? " (Reconnected)" : "");
1485
0
                            }
1486
1487
#if defined (TARGET_EXE_STANDALONE) && defined(_WIN32)
1488
                            if (bFixedBondsTaut && nNumDisplayedFixedBondTaut != 1)
1489
                            {
1490
                                continue;
1491
                            }
1492
                            if (ip->bDisplay)
1493
                            {
1494
                                if (bFixedBondsTaut)
1495
                                {
1496
                                    err_display = DisplayStructure( pCG,
1497
                                                            inp_norm_data[j]->at_fixed_bonds,
1498
                                                            inp_norm_data[j]->num_at,
1499
                                                            NULL, /* OAD_Polymer *polymer, */
1500
                                                            inp_norm_data[j]->num_removed_H,
1501
                                                            0 /*bAdd_DT_to_num_H*/,
1502
                                                            inp_norm_data[j]->nNumRemovedProtons,
1503
                                                            inp_norm_data[j]->nNumRemovedProtonsIsotopic,
1504
                                                            bHasIsotopicLayer,
1505
                                                            j,
1506
                                                            NULL,
1507
                                                            NULL,
1508
                                                            ip->bAbcNumbers,
1509
                                                            &ip->dp,
1510
                                                            ip->nMode,
1511
                                                            szTitle );
1512
                                }
1513
                                else
1514
                                {
1515
                                    err_display = DisplayStructure( pCG,
1516
                                                            inp_norm_data[j]->at,
1517
                                                            inp_norm_data[j]->num_at,
1518
                                                            NULL, /* OAD_Polymer *polymer, */
1519
                                                            0,
1520
                                                            0 /*bAdd_DT_to_num_H*/,
1521
                                                            0,
1522
                                                            NULL,
1523
                                                            k,
1524
                                                            j,
1525
                                                            pINChI[i],
1526
                                                            pINChI_Aux[i],
1527
                                                            ip->bAbcNumbers,
1528
                                                            &ip->dp,
1529
                                                            ip->nMode, szTitle );
1530
                                }
1531
                                if ((sd->bUserQuitComponentDisplay = (err_display == ESC_KEY ))) /* djb-rwth: addressing LLVM warning */
1532
                                {
1533
                                    break;
1534
                                }
1535
                            }
1536
#endif
1537
#ifdef TARGET_LIB_FOR_WINCHI
1538
1539
                            if (DRAWDATA && !bFixedBondsTaut)
1540
                            {
1541
                                struct DrawData vDrawData;
1542
                                vDrawData.pWindowData =
1543
                                    CreateWinData_( pCG,
1544
                                                    inp_norm_data[j]->at,
1545
                                                    inp_norm_data[j]->num_at,
1546
                                                    0,
1547
                                                    0 /* bAdd_DT_to_num_H */,
1548
                                                    0,
1549
                                                    NULL,
1550
                                                    k,
1551
                                                    j,
1552
                                                    pINChI[i],
1553
                                                    pINChI_Aux[i],
1554
                                                    ip->bAbcNumbers,
1555
                                                    &ip->dp,
1556
                                                    ip->nMode );
1557
1558
                                if (vDrawData.pWindowData != NULL)
1559
                                {
1560
                                    int nType;
1561
                                    vDrawData.nComponent = i + 1;
1562
                                    if (bTautomeric == 0)
1563
                                        nType = ( bIsotopic == 0 ) ? COMPONENT_BN
1564
                                        : COMPONENT_BI;
1565
                                    else
1566
                                        nType = ( bIsotopic == 0 ) ? COMPONENT_TN
1567
                                        : COMPONENT_TI;
1568
                                    vDrawData.nType = nType;
1569
1570
                                    vDrawData.bReconnected = iINChI; /* 0=>main; 1=>reconnected */
1571
                                    vDrawData.szTitle = inchi__strdup( szTitle );
1572
                                    vDrawData.pWindowData->szTitle = inchi__strdup( szTitle );
1573
                                    DRAWDATA( &vDrawData );
1574
                                }
1575
                            }
1576
                            else if (DRAWDATA && bFixedBondsTaut)
1577
                            {
1578
                                struct DrawData vDrawData;
1579
                                if (( ip->bCompareComponents & CMP_COMPONENTS ) &&
1580
                                     !( ip->bCompareComponents & CMP_COMPONENTS_NONTAUT ) &&
1581
                                     !bIsotopic == !inp_norm_data[j]->bHasIsotopicLayer)
1582
                                {
1583
1584
                                    vDrawData.pWindowData =
1585
                                        CreateWinData_( pCG,
1586
                                                        inp_norm_data[j]->at_fixed_bonds,
1587
                                                        inp_norm_data[j]->num_at,
1588
                                                        inp_norm_data[j]->num_removed_H,
1589
                                                        0 /* bAdd_DT_to_num_H */,
1590
                                                        inp_norm_data[j]->nNumRemovedProtons,
1591
                                                        inp_norm_data[j]->nNumRemovedProtonsIsotopic,
1592
                                                        k,
1593
                                                        j,
1594
                                                        NULL,
1595
                                                        NULL,
1596
                                                        ip->bAbcNumbers,
1597
                                                        &ip->dp,
1598
                                                        ip->nMode );
1599
                                }
1600
                                else
1601
                                {
1602
                                    continue;
1603
                                }
1604
                                if (vDrawData.pWindowData != NULL)
1605
                                {
1606
                                    vDrawData.nComponent = i + 1;
1607
                                    vDrawData.nType = COMPONENT_ORIGINAL_PREPROCESSED;
1608
                                    vDrawData.bReconnected = iINChI; /* 0=>main; 1=>reconnected */
1609
                                    vDrawData.szTitle = inchi__strdup( szTitle );
1610
                                    vDrawData.pWindowData->szTitle = inchi__strdup( szTitle );
1611
                                    DRAWDATA( &vDrawData );
1612
                                }
1613
                            }
1614
#endif
1615
0
                        }
1616
0
                    }
1617
0
                }
1618
0
            }
1619
1620
            /* Save normalized components for composite display */
1621
65.8k
            if ( /*ip->bDisplayCompositeResults && */
1622
65.8k
                 all_inp_norm_data
1623
65.8k
                )
1624
24.2k
            {
1625
72.6k
                for (j = 0; j < TAUT_NUM; j++)
1626
48.4k
                {
1627
48.4k
                    if (inp_norm_data[j]->bExists)
1628
47.9k
                    {
1629
47.9k
                        all_inp_norm_data[i][j] = *inp_norm_data[j];
1630
47.9k
                        memset( inp_norm_data[j], 0, sizeof( *inp_norm_data[0] ) ); /* djb-rwth: memset_s C11/Annex K variant? */
1631
47.9k
                    }
1632
48.4k
                }
1633
24.2k
            }
1634
65.8k
        }
1635
1636
        /* #endif */ /* } COMPILE_ANSI_ONLY */
1637
1638
1639
65.8k
        if (nRet)
1640
1
        {
1641
1
            nRet = TreatErrorsInCreateOneComponentINChI( sd, ip,
1642
1
                                                         cur_prep_inp_data,
1643
1
                                                         i, num_inp, inp_file,
1644
1
                                                         log_file, out_file, prb_file );
1645
1
            break;
1646
1
        }
1647
65.8k
    }
1648
    /**************************************************************************/
1649
    /*                                                                        */
1650
    /*                                                                        */
1651
    /*   E N D   O F   T H E    M A I N   C Y C L E   P R O C E S S I N G     */
1652
    /*                                                                        */
1653
    /*          C O M P O N E N T S    O N E   B Y   O N E                    */
1654
    /*                                                                        */
1655
    /*                                                                        */
1656
    /**************************************************************************/
1657
1658
41.8k
exit_cycle:
1659
41.8k
    switch (nRet)
1660
41.8k
    {
1661
0
        case _IS_FATAL:
1662
1
        case _IS_ERROR:
1663
1
            break;
1664
41.8k
        default:
1665
1666
        /* #ifndef COMPILE_ANSI_ONLY *//* { */
1667
            /* composite results picture(s) */
1668
41.8k
            if (all_inp_norm_data)
1669
237
            {
1670
237
                CreateCompositeNormAtom( composite_norm_data,
1671
237
                                         all_inp_norm_data,
1672
237
                                         prep_inp_data[iINChI].num_components );
1673
                /*
1674
                for ( i = 0; i < prep_inp_data[iINChI].num_components; i ++ ) {
1675
                    for ( k = 0; k < TAUT_NUM; k ++ ) {
1676
                       FreeInpAtomData( &all_inp_norm_data[i][k] );
1677
                    }
1678
                }
1679
                inchi_free( all_inp_norm_data );
1680
                all_inp_norm_data = NULL;
1681
                */
1682
237
            }
1683
            /* #endif */ /* } COMPILE_ANSI_ONLY */
1684
1685
41.8k
            break;
1686
41.8k
    }
1687
1688
    /*#ifndef COMPILE_ANSI_ONLY*/ /* { */
1689
1690
        /* avoid memory leaks in case of error */
1691
41.8k
    if (all_inp_norm_data)
1692
238
    {
1693
24.4k
        for (i = 0; i < prep_inp_data[iINChI].num_components; i++)
1694
24.2k
        {
1695
72.6k
            for (k = 0; k < TAUT_NUM; k++)
1696
48.4k
            {
1697
48.4k
                FreeInpAtomData( &all_inp_norm_data[i][k] );
1698
48.4k
            }
1699
24.2k
        }
1700
238
        inchi_free( all_inp_norm_data );
1701
238
        all_inp_norm_data = NULL;
1702
238
    }
1703
/*#endif */ /* } COMPILE_ANSI_ONLY */
1704
1705
41.8k
    FreeInpAtomData( inp_cur_data );
1706
125k
    for (i = 0; i < TAUT_NUM; i++)
1707
83.6k
    {
1708
83.6k
        FreeInpAtomData( inp_norm_data[i] );
1709
83.6k
    }
1710
1711
1712
41.8k
exit_function:
1713
1714
41.8k
    return nRet;
1715
41.8k
}
1716
1717
1718
/****************************************************************************
1719
 Generate InChI for one connected component
1720
 (of possibly multi-component structure)
1721
****************************************************************************/
1722
int CreateOneComponentINChI( CANON_GLOBALS      *pCG,
1723
                             INCHI_CLOCK        *ic,
1724
                             STRUCT_DATA        *sd,
1725
                             INPUT_PARMS        *ip,
1726
                             INP_ATOM_DATA      *inp_cur_data,
1727
                             ORIG_ATOM_DATA     *orig_inp_data,
1728
                             PINChI2            *pINChI,
1729
                             PINChI_Aux2        *pINChI_Aux,
1730
                             int                iINChI,
1731
                             int                i,
1732
                             long               num_inp,
1733
                             INP_ATOM_DATA      **inp_norm_data,
1734
                             NORM_CANON_FLAGS   *pncFlags,
1735
                             INCHI_IOSTREAM     *log_file )
1736
65.8k
{
1737
65.8k
    inchiTime     ulTStart, ulTEnd, *pulTEnd = NULL;
1738
65.8k
    int           k, num_at, ret = 0;
1739
65.8k
    int           bOrigCoord;
1740
65.8k
    INCHI_MODE     bTautFlags = ip->bTautFlags;
1741
65.8k
    INCHI_MODE     bTautFlagsDone = ( ip->bTautFlagsDone | sd->bTautFlagsDone[INCHI_BAS] );
1742
65.8k
    INChI       *cur_INChI[TAUT_NUM];
1743
65.8k
    INChI_Aux   *cur_INChI_Aux[TAUT_NUM];
1744
65.8k
    long          lElapsedTime;
1745
1746
65.8k
    InchiTimeGet( &ulTStart );
1747
65.8k
    bOrigCoord =
1748
65.8k
        !( ip->bINChIOutputOptions & ( INCHI_OUT_NO_AUX_INFO | INCHI_OUT_SHORT_AUX_INFO ) );
1749
1750
197k
    for (k = 0; k < TAUT_NUM; k++)
1751
131k
    {
1752
131k
        cur_INChI[k] = NULL;
1753
131k
        cur_INChI_Aux[k] = NULL;
1754
131k
    }
1755
1756
    /*  Allocate memory for non-tautomeric (k=0) and tautomeric (k=1) results */
1757
197k
    for (k = 0; k < TAUT_NUM; k++)
1758
131k
    {
1759
        /* djb-rwth: introducing variables for correct nAllocMode expression */
1760
131k
        int nAM1 = 0, nAM2 = 0;
1761
1762
131k
        if (k == TAUT_YES)
1763
65.8k
            nAM1 = REQ_MODE_TAUT;
1764
1765
131k
        if (bTautFlagsDone & (TG_FLAG_FOUND_ISOTOPIC_H_DONE | TG_FLAG_FOUND_ISOTOPIC_ATOM_DONE))
1766
120
            nAM2 = ip->nMode & REQ_MODE_ISO;
1767
1768
131k
        int nAllocMode = nAM1 | nAM2; /* djb-rwth: original sequence of bit-wise operations had to be rewritten */
1769
1770
1771
131k
        if ((k == TAUT_NON && ( ip->nMode & REQ_MODE_BASIC )) ||
1772
131k
             (k == TAUT_YES && ( ip->nMode & REQ_MODE_TAUT ))) /* djb-rwth: addressing LLVM warning */
1773
89.9k
        {
1774
            /*  alloc INChI and INChI_Aux */
1775
89.9k
            cur_INChI[k] = Alloc_INChI( inp_cur_data->at,
1776
89.9k
                                            inp_cur_data->num_at,
1777
89.9k
                                            &inp_cur_data->num_bonds,
1778
89.9k
                                            &inp_cur_data->num_isotopic,
1779
89.9k
                                            nAllocMode );
1780
1781
89.9k
            cur_INChI_Aux[k] = Alloc_INChI_Aux( inp_cur_data->num_at,
1782
89.9k
                                                inp_cur_data->num_isotopic,
1783
89.9k
                                                nAllocMode,
1784
89.9k
                                                bOrigCoord );
1785
89.9k
            if (cur_INChI_Aux[k])
1786
89.9k
            {
1787
89.9k
                cur_INChI_Aux[k]->bIsIsotopic = inp_cur_data->num_isotopic;
1788
89.9k
            }
1789
            /*  alloc memory for the output structure: non-tautomeric and tautomeric (for displaying) */
1790
1791
89.9k
            CreateInpAtomData( inp_norm_data[k], inp_cur_data->num_at, k );
1792
89.9k
        }
1793
41.7k
        else
1794
41.7k
        {
1795
41.7k
            FreeInpAtomData( inp_norm_data[k] );
1796
41.7k
        }
1797
131k
    }
1798
1799
65.8k
    lElapsedTime = InchiTimeElapsed( ic, &ulTStart );
1800
65.8k
    if (ip->msec_MaxTime)
1801
0
    {
1802
0
        ip->msec_LeftTime -= lElapsedTime;
1803
0
    }
1804
65.8k
    sd->ulStructTime += lElapsedTime;
1805
1806
    /*^^^#if ( !defined( TARGET_LIB_FOR_WINCHI ) && !defined( TARGET_API_LIB ) ) */
1807
    #if ( !defined( TARGET_LIB_FOR_WINCHI ) && !defined( TARGET_API_LIB ) && !defined(TARGET_EXE_STANDALONE) )
1808
    #endif
1809
1810
    /******************************************************
1811
     *
1812
     *  Get one component canonical numberings, etc.
1813
     *
1814
     ******************************************************/
1815
1816
    /* Create_INChI() return value:
1817
     * num_at <= 0: error code
1818
     * num_at >  0: number of atoms (excluding terminal hydrogen atoms)
1819
     * inp_norm_data[0] => non-tautomeric, inp_norm_data[1] => tautomeric */
1820
1821
65.8k
    InchiTimeGet( &ulTStart );
1822
1823
65.8k
    if (ip->msec_MaxTime)
1824
0
    {
1825
0
        ulTEnd = ulTStart;
1826
0
        pulTEnd = &ulTEnd;
1827
0
        if (ip->msec_LeftTime > 0)
1828
0
        {
1829
0
            InchiTimeAddMsec( ic, pulTEnd, ip->msec_LeftTime );
1830
0
        }
1831
0
    }
1832
1833
65.8k
    num_at = Create_INChI( pCG, ic, ip,
1834
65.8k
                           cur_INChI, cur_INChI_Aux,
1835
65.8k
                           orig_inp_data/* not used */,
1836
65.8k
                           inp_cur_data->at, inp_norm_data, inp_cur_data->num_at,
1837
65.8k
                           ip->nMode,
1838
65.8k
                           &bTautFlags, &bTautFlagsDone,
1839
65.8k
                           pulTEnd, NULL, sd->pStrErrStruct );
1840
1841
65.8k
    SetConnectedComponentNumber( inp_cur_data->at, inp_cur_data->num_at, i + 1 );
1842
                        /*  NB: normalization alters structure component number */
1843
1844
197k
    for (k = 0; k < TAUT_NUM; k++)
1845
131k
    {
1846
131k
        if (cur_INChI_Aux[k] && cur_INChI_Aux[k]->nNumberOfAtoms > 0)
1847
89.6k
        {
1848
89.6k
            pncFlags->bNormalizationFlags[iINChI][k] |=
1849
89.6k
                cur_INChI_Aux[k]->bNormalizationFlags;
1850
89.6k
            pncFlags->bTautFlags[iINChI][k] |=
1851
89.6k
                cur_INChI_Aux[k]->bTautFlags;
1852
89.6k
            pncFlags->bTautFlagsDone[iINChI][k] |=
1853
89.6k
                cur_INChI_Aux[k]->bTautFlagsDone;
1854
89.6k
            pncFlags->nCanonFlags[iINChI][k] |=
1855
89.6k
                cur_INChI_Aux[k]->nCanonFlags;
1856
89.6k
        }
1857
131k
    }
1858
1859
    /*  Detect errors */
1860
65.8k
    if (num_at < 0)
1861
1
    {
1862
1
        sd->nErrorCode = num_at;
1863
1
    }
1864
65.8k
    else if (num_at == 0)
1865
0
    {
1866
0
        sd->nErrorCode = -1;
1867
0
    }
1868
65.8k
    else if (cur_INChI[TAUT_NON] && cur_INChI[TAUT_NON]->nErrorCode)
1869
0
    {   /*  non-tautomeric error */
1870
0
        sd->nErrorCode = cur_INChI[TAUT_NON]->nErrorCode;
1871
0
    }
1872
65.8k
    else if (cur_INChI[TAUT_YES] && cur_INChI[TAUT_YES]->nErrorCode)
1873
0
    {   /*  tautomeric error */
1874
0
        sd->nErrorCode = cur_INChI[TAUT_YES]->nErrorCode;
1875
0
    }
1876
1877
1878
#if ( bRELEASE_VERSION == 0 )
1879
    if (cur_INChI[TAUT_NON]) sd->bExtract |= cur_INChI[TAUT_NON]->bExtract;
1880
    if (cur_INChI[TAUT_YES]) sd->bExtract |= cur_INChI[TAUT_YES]->bExtract;
1881
    if (( TG_FLAG_TEST_TAUT3_SALTS_DONE & bTautFlagsDone ))
1882
    {
1883
        sd->bExtract |= EXTR_TEST_TAUT3_SALTS_DONE;
1884
    }
1885
#endif
1886
1887
    /*  Detect and store stereo warnings */
1888
65.8k
    if (!sd->nErrorCode)
1889
65.8k
        GetProcessingWarningsOneComponentInChI( cur_INChI, inp_norm_data, sd, ip->bNoWarnings );
1890
1891
65.8k
    lElapsedTime = InchiTimeElapsed( ic, &ulTStart );
1892
65.8k
    if (ip->msec_MaxTime)
1893
0
    {
1894
0
        ip->msec_LeftTime -= lElapsedTime;
1895
0
    }
1896
65.8k
    sd->ulStructTime += lElapsedTime;
1897
1898
#if !defined(TARGET_API_LIB) && !defined(COMPILE_ANSI_ONLY)
1899
    /*  Display the results */
1900
    if (ip->bDisplay)
1901
    {
1902
        eat_keyboard_input( );
1903
    }
1904
#endif
1905
1906
    /*  a) No matter what happened save the allocated INChI pointers */
1907
    /*  save the INChI of the current component */
1908
1909
65.8k
    InchiTimeGet( &ulTStart );
1910
197k
    for (k = 0; k < TAUT_NUM; k++)
1911
131k
    {
1912
131k
        pINChI[i][k] = cur_INChI[k];
1913
131k
        pINChI_Aux[i][k] = cur_INChI_Aux[k];
1914
131k
        cur_INChI[k] = NULL;
1915
131k
        cur_INChI_Aux[k] = NULL;
1916
131k
    }
1917
1918
    /*  b) Count one component structure and/or INChI results only
1919
           if there was no error
1920
           Set inp_norm_data[j]->num_removed_H = number of removed explicit H
1921
    */
1922
1923
65.8k
    if (!sd->nErrorCode)
1924
65.8k
    {
1925
        /*  find where the current processed structure is located */
1926
65.8k
        int cur_is_in_non_taut = ( pINChI[i][TAUT_NON] &&
1927
65.8k
                                   pINChI[i][TAUT_NON]->nNumberOfAtoms > 0 );
1928
65.8k
        int cur_is_in_taut = ( pINChI[i][TAUT_YES] &&
1929
65.8k
                                   pINChI[i][TAUT_YES]->nNumberOfAtoms > 0 );
1930
1931
65.8k
        int cur_is_non_taut = (cur_is_in_non_taut && 0 == pINChI[i][TAUT_NON]->lenTautomer) ||
1932
65.8k
            (cur_is_in_taut && 0 == pINChI[i][TAUT_YES]->lenTautomer); /* djb-rwth: addressing LLVM warnings */
1933
65.8k
        int cur_is_taut = cur_is_in_taut && 0 < pINChI[i][TAUT_YES]->lenTautomer;
1934
1935
        /*
1936
        sd->bTautFlags[iINChI]     |= bTautFlags;
1937
        sd->bTautFlagsDone[iINChI] |= bTautFlagsDone;
1938
        */
1939
1940
65.8k
        if (cur_is_non_taut + cur_is_taut)
1941
65.8k
        {
1942
            /*  count tautomeric and non-tautomeric components of the structures */
1943
65.8k
            int j1 = cur_is_in_non_taut ? TAUT_NON : TAUT_YES;
1944
65.8k
            int j2 = cur_is_in_taut ? TAUT_YES : TAUT_NON;
1945
65.8k
            int j;
1946
65.8k
            sd->num_non_taut[iINChI] += cur_is_non_taut;
1947
65.8k
            sd->num_taut[iINChI] += cur_is_taut;
1948
155k
            for (j = j1; j <= j2; j++)
1949
89.6k
            {
1950
89.6k
                int bIsotopic = ( pINChI[i][j]->nNumberOfIsotopicAtoms ||
1951
89.6k
                                  pINChI[i][j]->nNumberOfIsotopicTGroups ||
1952
89.6k
                                  (pINChI[i][j]->nPossibleLocationsOfIsotopicH && pINChI[i][j]->nPossibleLocationsOfIsotopicH[0] > 1) ); /* djb-rwth: addressing LLVM warning */
1953
89.6k
                if (pINChI_Aux[i][j] && (j == TAUT_YES)) /* djb-rwth: fixing a NULL pointer dereference */
1954
65.8k
                {
1955
65.8k
                    bIsotopic |= ( 0 < pINChI_Aux[i][j]->nNumRemovedIsotopicH[0] +
1956
65.8k
                                      pINChI_Aux[i][j]->nNumRemovedIsotopicH[1] +
1957
65.8k
                                      pINChI_Aux[i][j]->nNumRemovedIsotopicH[2] );
1958
65.8k
                }
1959
1960
89.6k
                inp_norm_data[j]->bExists = 1; /*  j=0: non-taut exists, j=1: taut exists */
1961
89.6k
                inp_norm_data[j]->bHasIsotopicLayer = bIsotopic;
1962
                /*inp_norm_data[j]->num_removed_H = inp_norm_data[j]->num_at - num_at;*/
1963
89.6k
            }
1964
65.8k
        }
1965
65.8k
    }
1966
1967
    /* return (sd->nErrorCode==CT_OUT_OF_RAM || sd->nErrorCode==CT_USER_QUIT_ERR)? _IS_FATAL :
1968
            sd->nErrorCode? _IS_ERROR : 0; */
1969
1970
65.8k
    if (sd->nErrorCode == CT_OUT_OF_RAM || sd->nErrorCode == CT_USER_QUIT_ERR)
1971
0
    {
1972
0
        ret = _IS_FATAL;
1973
0
    }
1974
65.8k
    else if (sd->nErrorCode)
1975
1
    {
1976
1
        ret = _IS_ERROR;
1977
1
    }
1978
1979
65.8k
    lElapsedTime = InchiTimeElapsed( ic, &ulTStart );
1980
65.8k
    if (ip->msec_MaxTime)
1981
0
    {
1982
0
        ip->msec_LeftTime -= lElapsedTime;
1983
0
    }
1984
65.8k
    sd->ulStructTime += lElapsedTime;
1985
1986
65.8k
    return ret;
1987
65.8k
}
1988
1989
1990
/****************************************************************************
1991
 Extended-functionality version of ProcessOneStructure
1992
1993
 able to handle both polymer related and unrelated pseudoelement atoms
1994
 and to perform advanced polymer treatment (v. 1.06+)
1995
 ****************************************************************************/
1996
int ProcessOneStructureEx( struct tagINCHI_CLOCK    *ic,
1997
                           struct tagCANON_GLOBALS  *CG,
1998
                           STRUCT_DATA              *sd,
1999
                           INPUT_PARMS              *ip,
2000
                           char                     *szTitle,
2001
                           PINChI2                  *pINChI2[INCHI_NUM],
2002
                           PINChI_Aux2              *pINChI_Aux2[INCHI_NUM],
2003
                           INCHI_IOSTREAM           *inp_file,
2004
                           INCHI_IOSTREAM           *log_file,
2005
                           INCHI_IOSTREAM           *out_file,
2006
                           INCHI_IOSTREAM           *prb_file,
2007
                           ORIG_ATOM_DATA           *orig_inp_data,
2008
                           ORIG_ATOM_DATA           *prep_inp_data,
2009
                           long                     num_inp,
2010
                           INCHI_IOS_STRING         *strbuf,
2011
                           unsigned char            save_opt_bits )
2012
0
{
2013
0
    int ret = _IS_OKAY;
2014
0
    char *sinchi_noedits=NULL, *saux_noedits=NULL;
2015
    
2016
2017
    /* PREPROCESS */
2018
2019
#if (BUILD_WITH_ENG_OPTIONS==1)
2020
#if ALLOW_SUBSTRUCTURE_FILTERING==1
2021
    if (ip->bFilterSS)
2022
    {
2023
        int present, ok = 0;
2024
        
2025
        present = OrigAtData_CheckForSubstructure(orig_inp_data);
2026
2027
        if (ip->bFilterSS == 1 && present)      ok = 1;
2028
        else if (ip->bFilterSS == -1 && !present) ok = 1;
2029
2030
        if (!ok)
2031
        {
2032
            inchi_ios_eprint(log_file, "Warning (Skip record which does not pass substructure presence/absence filter) structure #%ld.%s%s%s%s\n",
2033
                             num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));
2034
            return _IS_SKIP;
2035
        }
2036
    }
2037
#endif
2038
#endif
2039
2040
    /*  Preprocess Polymer CRUs (collect frame shift info and edit the original input accordingly) */
2041
0
    ret = PreprocessPolymerCRUData( ic, CG, sd, ip, szTitle,
2042
0
                                    pINChI2, pINChI_Aux2,
2043
0
                                    inp_file, log_file, out_file, prb_file,
2044
0
                                    orig_inp_data, prep_inp_data,
2045
0
                                    num_inp, strbuf, save_opt_bits,
2046
0
                                    &sinchi_noedits, &saux_noedits); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
2047
2048
    /* CALCULATE INCHI */
2049
    
2050
    /* Perform calculation as usual either for untouched (modes POLYMERS_LEGACY and POLYMERS_LEGACY_PLUS) 
2051
       or just edited, probably (mode POLYMERS_MODERN) structure as passed in orig_inp_data
2052
    */
2053
0
    ret = ProcessOneStructureExCore( ic, CG, sd, ip,  szTitle, 
2054
0
                                     pINChI2, pINChI_Aux2,
2055
0
                                     inp_file, log_file, out_file, prb_file,
2056
0
                                     orig_inp_data, prep_inp_data,
2057
0
                                     num_inp, strbuf, save_opt_bits );
2058
2059
0
    if (ip->bINChIOutputOptions2 & INCHI_OUT_INCHI_GEN_ERROR)
2060
0
    {
2061
0
        if (ret == _IS_FATAL || ret == _IS_ERROR)
2062
0
        {
2063
0
            if (ip->bINChIOutputOptions & INCHI_OUT_STDINCHI)
2064
0
            {
2065
0
                inchi_ios_eprint(out_file, "InChI=1S//\n");
2066
0
            }
2067
0
            else
2068
0
            {
2069
0
                inchi_ios_eprint(out_file, "InChI=1//\n");
2070
0
            }
2071
0
        }
2072
0
    }
2073
2074
    /* Post-process: add AuxInfo for a very unedited original structure */
2075
0
    if (ret != _IS_FATAL && ret != _IS_ERROR)
2076
0
    {
2077
0
        if (!(ip->bINChIOutputOptions & INCHI_OUT_NO_AUX_INFO) &&
2078
0
            out_file->s.pStr && strstr(out_file->s.pStr, "AuxInfo=" ) &&
2079
0
            saux_noedits && strstr(saux_noedits, "AuxInfo=") )
2080
0
        {
2081
0
            char *pp = out_file->s.pStr;
2082
0
            if (saux_noedits[8])
2083
0
            {
2084
0
                remove_one_lf(pp);
2085
0
                out_file->s.nUsedLength = strlen(out_file->s.pStr);
2086
0
                inchi_ios_eprint(out_file, "/U/%-s\n", saux_noedits +8);
2087
0
            }
2088
0
        }
2089
0
    }
2090
2091
0
    inchi_free(sinchi_noedits);
2092
0
    inchi_free(saux_noedits);
2093
2094
    
2095
#ifdef TARGET_LIB_FOR_WINCHI
2096
2097
    push_to_winchi_text_window(out_file);
2098
2099
    if (sd->pStrErrStruct && FWPUSH)
2100
    {
2101
        FWPUSH(sd->pStrErrStruct);
2102
    }
2103
    inchi_ios_flush(out_file);
2104
#endif
2105
2106
0
    return ret;
2107
0
}
2108
2109
2110
/****************************************************************************
2111
 Special treatment for polymers: perform CRU frame shift analysis 
2112
 and make related edits in orig_inp_data whenever applicable
2113
****************************************************************************/
2114
int PreprocessPolymerCRUData( struct tagINCHI_CLOCK    *ic,
2115
                                struct tagCANON_GLOBALS  *CG,
2116
                                STRUCT_DATA              *sd,
2117
                                INPUT_PARMS              *ip,
2118
                                char                     *szTitle,
2119
                                PINChI2                  *pINChI2[INCHI_NUM],
2120
                                PINChI_Aux2              *pINChI_Aux2[INCHI_NUM],
2121
                                INCHI_IOSTREAM           *inp_file,
2122
                                INCHI_IOSTREAM           *log_file,
2123
                                INCHI_IOSTREAM           *out_file,
2124
                                INCHI_IOSTREAM           *prb_file,
2125
                                ORIG_ATOM_DATA           *orig_inp_data,
2126
                                ORIG_ATOM_DATA           *prep_inp_data,
2127
                                long                     num_inp,
2128
                                INCHI_IOS_STRING         *strbuf,
2129
                                unsigned char            save_opt_bits,
2130
                                char           **sinchi_noedits,
2131
                                char           **saux_noedits)
2132
0
{
2133
0
    int ret = _IS_OKAY;
2134
0
    char *sinchi_105p = NULL, *saux_105p = NULL;
2135
0
    OAD_StructureEdits edits_unit_frame_shift, *ed_fs = &edits_unit_frame_shift;
2136
0
    OAD_StructureEdits edits_unit_folding, *ed_fold = &edits_unit_folding;
2137
    
2138
0
    OAD_StructureEdits_Init(ed_fold);
2139
0
    OAD_StructureEdits_Init(ed_fs);
2140
2141
0
    if (orig_inp_data)
2142
0
    {
2143
0
        orig_inp_data->valid_polymer = 0;
2144
0
        if (orig_inp_data->polymer)
2145
0
        {
2146
0
            orig_inp_data->polymer->treat = ip->bPolymers;
2147
0
            if (orig_inp_data->polymer->treat != POLYMERS_NO)
2148
0
            {
2149
0
                orig_inp_data->valid_polymer = 1;
2150
2151
0
                if (orig_inp_data->polymer->treat == POLYMERS_MODERN)
2152
0
                {
2153
0
                    int n_done, n_todo = 0, n_poly_zz = 0; /* djb-rwth: ignoring LLVM warning: variable used */
2154
2155
                    /*  First, get InChI and AuxInfo for the unedited original input
2156
                    (actually, we are interested in AuxInfo for original structure;
2157
                    we then append it to the final result AuxInfo, in order to
2158
                    preserve total reversibility (restoring the original structure ) */
2159
0
                    ret = OAD_ProcessOneStructureNoEdits(ic, CG, sd, ip, szTitle,
2160
0
                                                            pINChI2, pINChI_Aux2,
2161
0
                                                            inp_file, log_file, out_file, prb_file,
2162
0
                                                            orig_inp_data, prep_inp_data,
2163
0
                                                            num_inp, strbuf, save_opt_bits,
2164
0
                                                            &n_poly_zz,
2165
0
                                                            sinchi_noedits, saux_noedits);
2166
0
                    if (ret == _IS_FATAL || ret == _IS_ERROR)
2167
0
                    {
2168
0
                        ret = _IS_WARNING; 
2169
0
                        if (!ip->bNoWarnings)
2170
0
                        {
2171
0
                            AddErrorMessage(sd->pStrErrStruct, "CRU folding and frame shift analysis failed");
2172
0
                        }
2173
0
                        goto exit_function;
2174
0
                    }
2175
0
                    if (n_poly_zz < 2)
2176
0
                    {
2177
                        /* For now, CRU folding and frame shift analysis are only applicable to */
2178
                        /* CRU having both caps of indefinite nature, Zz                        */
2179
0
                        goto exit_function;
2180
0
                    }
2181
                    
2182
2183
                    /* Prepare and perform CRU folding related edits */
2184
0
                    if (ip->bFoldPolymerSRU != 0) 
2185
0
                    {
2186
                        /*  Get interim 105+ flavour of InChI and AuxInfo and prepare */
2187
0
                        int old_bFrameShiftScheme = ip->bFrameShiftScheme;
2188
0
                        ip->bFrameShiftScheme = FSS_STARS_CYCLED;
2189
0
                        ret = OAD_ProcessOneStructure105Plus(ic, CG, sd, ip, szTitle,
2190
0
                            pINChI2, pINChI_Aux2,
2191
0
                            inp_file, log_file, out_file, prb_file,
2192
0
                            orig_inp_data, prep_inp_data,
2193
0
                            num_inp, strbuf, save_opt_bits,
2194
0
                            &sinchi_105p, &saux_105p);
2195
0
                        ip->bFrameShiftScheme = old_bFrameShiftScheme;
2196
0
                        if (ret == _IS_FATAL || ret == _IS_ERROR)
2197
0
                        {
2198
0
                            ret = _IS_WARNING;
2199
0
                            if (!ip->bNoWarnings)
2200
0
                            {
2201
                                /* AddErrorMessage(sd->pStrErrStruct, "CRU fold analysis failed");*/
2202
0
                                ;
2203
0
                            }
2204
0
                            goto frame_shift; 
2205
0
                        }
2206
2207
0
                        ret = OAD_Polymer_PrepareFoldCRUEdits( orig_inp_data, *sinchi_noedits, *saux_noedits, sinchi_105p, saux_105p, ed_fold);
2208
0
                        if (ret == _IS_FATAL || ret == _IS_ERROR)
2209
0
                        {
2210
0
                            if (!ip->bNoWarnings)
2211
0
                            {
2212
                                /*AddErrorMessage(sd->pStrErrStruct, "CRU fold analysis failed");*/
2213
0
                                ;
2214
0
                            }
2215
0
                            goto frame_shift;
2216
0
                        }
2217
0
                        if (ret == _IS_WARNING)
2218
0
                        {
2219
                           /* inchi_ios_eprint(log_file, "Warning (CRU fold analysis failed) structure #%ld.%s%s%s%s\n",
2220
                                num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/                            
2221
0
                            ;
2222
0
                        }
2223
                        /* else */
2224
0
                        {
2225
                            /* Proceed with CRU fold */
2226
0
                            n_done = 0; /* djb-rwth: ignoring LLVM warning: variable used */
2227
0
                            n_todo = ed_fold->del_atom->used + ed_fold->del_bond->used + ed_fold->new_bond->used + ed_fold->mod_bond->used;
2228
0
                            ed_fold->del_side_chains = 1;
2229
0
                            OAD_StructureEdits_DebugPrint(ed_fold);
2230
0
                            if (n_todo)
2231
0
                            {
2232
                                /* Edit the original input data */
2233
0
                                ed_fold->del_side_chains = 1;
2234
0
                                n_done = OAD_StructureEdits_Apply(sd, ip, orig_inp_data, ed_fold, &ret); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
2235
0
                                if (ret == _IS_FATAL || ret == _IS_ERROR)
2236
0
                                {
2237
0
                                    ret = _IS_WARNING;
2238
                                    /*inchi_ios_eprint(log_file, "Warning (CRU fold failed) structure #%ld.%s%s%s%s\n",
2239
                                        num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));
2240
                                    */
2241
0
                                    if (!ip->bNoWarnings)
2242
0
                                    {
2243
0
                                        AddErrorMessage(sd->pStrErrStruct, "CRU folding failed");
2244
0
                                    }
2245
0
                                }
2246
0
                                else
2247
0
                                {
2248
0
                                    if (!ip->bNoWarnings)
2249
0
                                    {
2250
0
                                        WarningMessage(sd->pStrErrStruct, "Atom(s) removed due to CRU folding");
2251
0
                                    }
2252
0
                                }
2253
0
                            }
2254
0
                        }
2255
0
                    }
2256
2257
0
frame_shift:        ;
2258
                    /* Prepare and perform frame shift related edits */
2259
0
                    if (ip->bFrameShiftScheme != FSS_NONE) 
2260
0
                    {
2261
                        /* Clear buffers */
2262
0
                        if (sinchi_105p)
2263
0
                        {
2264
0
                            inchi_free(sinchi_105p);
2265
0
                        }
2266
0
                        if (saux_105p)
2267
0
                        {
2268
0
                            inchi_free(saux_105p);
2269
0
                        }
2270
                        /*  Get interim 105+ flavour of InChI and AuxInfo (possibly 2nd time) */
2271
0
                        ret = OAD_ProcessOneStructure105Plus(ic, CG, sd, ip, szTitle,
2272
0
                                                                pINChI2, pINChI_Aux2,
2273
0
                                                                inp_file, log_file, out_file, prb_file,
2274
0
                                                                orig_inp_data, prep_inp_data,
2275
0
                                                                num_inp, strbuf, save_opt_bits,
2276
0
                                                                &sinchi_105p, &saux_105p);
2277
0
                        if (ret == _IS_FATAL || ret == _IS_ERROR)
2278
0
                        {
2279
0
                            ret = _IS_WARNING;
2280
                            /*inchi_ios_eprint(log_file, "Warning (Frame shift analysis failed) structure #%ld.%s%s%s%s\n",
2281
                                num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/
2282
0
                            if (!ip->bNoWarnings)
2283
0
                            {
2284
0
                                AddErrorMessage(sd->pStrErrStruct, "Frame shift analysis failed");
2285
0
                            }
2286
0
                            goto exit_function;
2287
0
                        }
2288
2289
0
                        ret = OAD_Polymer_PrepareFrameShiftEdits( orig_inp_data, sinchi_105p, saux_105p, ed_fs);
2290
                     
2291
0
                        if (ret == _IS_FATAL || ret == _IS_ERROR) /* djb-rwth: logical operator corrected */
2292
0
                        {
2293
0
                            ret = _IS_WARNING;
2294
                            /*inchi_ios_eprint(log_file, "Warning (Frame shift analysis failed) structure #%ld.%s%s%s%s\n",
2295
                                             num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/
2296
0
                            if (!ip->bNoWarnings)
2297
0
                            {
2298
0
                                AddErrorMessage(sd->pStrErrStruct, "Frame shift analysis failed");
2299
0
                            }
2300
0
                            goto exit_function;
2301
0
                        }
2302
0
                        else
2303
0
                        {
2304
                            /* OK, proceed with frame shift */
2305
0
                            n_done = 0; /* djb-rwth: ignoring LLVM warning: variable used */
2306
0
                            n_todo = ed_fs->del_atom->used +
2307
0
                                     ed_fs->del_bond->used + ed_fs->new_bond->used + ed_fs->mod_bond->used +
2308
0
                                     ed_fs->mod_coord->used;
2309
0
                            OAD_StructureEdits_DebugPrint(ed_fs);
2310
0
                            if (n_todo)
2311
0
                            {
2312
                                /* Edit the original input data according to frame shift info */
2313
0
                                n_done = OAD_StructureEdits_Apply(sd, ip, orig_inp_data, ed_fs, &ret); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
2314
0
                                if (ret == _IS_FATAL || ret == _IS_ERROR)
2315
0
                                {
2316
0
                                    ret = _IS_WARNING;
2317
                                    /*inchi_ios_eprint(log_file, "Warning (Frame shift failed) structure #%ld.%s%s%s%s\n",
2318
                                                     num_inp, SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));*/
2319
0
                                    if (!ip->bNoWarnings)
2320
0
                                    {
2321
0
                                        AddErrorMessage(sd->pStrErrStruct, "Frame shift failed");
2322
0
                                    }
2323
0
                                }
2324
0
                                else
2325
0
                                {
2326
0
                                    if (!ip->bNoWarnings)
2327
0
                                    {
2328
0
                                        WarningMessage(sd->pStrErrStruct, "Bond(s) rearranged due to CRU frame shift");
2329
0
                                    }
2330
0
                                }
2331
0
                            }
2332
0
                        }
2333
0
                    } /* if (ip->bFrameShiftScheme != FSS_NONE)  */
2334
2335
2336
0
                } /* if (orig_inp_data->polymer->treat == POLYMERS_MODERN) */
2337
0
            }
2338
2339
0
            else /* orig_inp_data->polymer->treat == POLYMERS_NO) */
2340
0
            {
2341
                /*inchi_ios_eprint(log_file, "Ignore polymer data");*/
2342
0
                if (!ip->bNoWarnings)
2343
0
                {
2344
0
                    AddErrorMessage(sd->pStrErrStruct, "Ignore polymer data");
2345
0
                }
2346
0
            }
2347
0
        }
2348
0
    }
2349
2350
0
exit_function:
2351
0
    if (sinchi_105p)
2352
0
    {
2353
0
        inchi_free(sinchi_105p);
2354
0
    }
2355
0
    if (saux_105p)
2356
0
    {
2357
0
        inchi_free(saux_105p);
2358
0
    }
2359
0
    OAD_StructureEdits_Clear(ed_fold);  /* Clear edits collection */
2360
0
    OAD_StructureEdits_Clear(ed_fs);    /* Clear edits collection */
2361
2362
    
2363
0
    return ret;
2364
0
}
2365
2366
2367
/****************************************************************************/
2368
void swap_atoms_xyz( ORIG_ATOM_DATA *orig_at_data, int ia1, int ia2 )
2369
0
{
2370
0
    double x, y, z;
2371
    
2372
0
    if (ia1 != ia2)
2373
0
    {
2374
0
        x = orig_at_data->at[ia1].x; 
2375
0
        y = orig_at_data->at[ia1].y; 
2376
0
        z = orig_at_data->at[ia1].z;
2377
2378
0
        orig_at_data->at[ia1].x = orig_at_data->at[ia2].x;
2379
0
        orig_at_data->at[ia1].y = orig_at_data->at[ia2].y;
2380
0
        orig_at_data->at[ia1].z = orig_at_data->at[ia2].z;
2381
        
2382
0
        orig_at_data->at[ia2].x = x;
2383
0
        orig_at_data->at[ia2].y = y;
2384
0
        orig_at_data->at[ia2].z = z;
2385
0
    }
2386
2387
0
    return;
2388
0
}
2389
2390
2391
/****************************************************************************
2392
 OAD_StructureEdits_Edit
2393
****************************************************************************/
2394
int OAD_StructureEdits_Apply( STRUCT_DATA *sd, 
2395
                              INPUT_PARMS *ip, 
2396
                              ORIG_ATOM_DATA *orig_at_data, 
2397
                              OAD_StructureEdits *ed, 
2398
                              int *ret)
2399
0
{
2400
0
    int ok = 0, fail;
2401
0
    int i, j, old_a1, old_a2, new_a1, new_a2, n_edits = 0;
2402
0
    int n_del_atom, n_del_bond, n_new_bond, n_mod_bond, n_mod_coord;
2403
0
    int a1, a2;
2404
0
    int bond_type = INCHI_BOND_TYPE_NONE, bond_stereo = INCHI_BOND_STEREO_NONE;
2405
0
    inp_ATOM *at = orig_at_data->at;
2406
0
    OAD_Polymer *p = orig_at_data->polymer;
2407
0
    int *at_renum = NULL;
2408
0
    int *ibuf = NULL;
2409
0
    int n_max_stored=-1;
2410
2411
0
    *ret = _IS_OKAY;
2412
2413
0
    n_del_atom = ed->del_atom->used;
2414
0
    n_del_bond = ed->del_bond->used/2;
2415
0
    n_new_bond = ed->new_bond->used/3;
2416
0
    n_mod_bond = ed->mod_bond->used/4;
2417
0
    n_mod_coord = ed->mod_coord->used/2;
2418
0
    if (n_del_atom + n_del_bond + n_new_bond + n_mod_bond + n_mod_coord < 1)
2419
0
    {
2420
0
        return 0;
2421
0
    }
2422
2423
0
    n_max_stored = inchi_max(2 * (orig_at_data->num_inp_atoms + 1), 2 * (orig_at_data->num_inp_bonds + 1)); /* set all-purpose buffer */
2424
2425
0
    ITRACE_("\n***************************\nOrig_at_data BEFORE EDITS:\n");
2426
0
    OrigAtData_DebugTrace(orig_at_data);
2427
0
    OAD_Polymer_DebugTrace(orig_at_data->polymer);
2428
2429
    /* Delete bonds */
2430
0
    if (n_del_bond)
2431
0
    {
2432
0
        for (i = 0; i < 2 * n_del_bond; i += 2)
2433
0
        {
2434
0
            a1 = ed->del_bond->item[i] - 1;
2435
0
            a2 = ed->del_bond->item[i + 1] - 1;
2436
0
            ok = OrigAtData_RemoveBond(a1, a2, at, &bond_type, &bond_stereo, &orig_at_data->num_inp_bonds);
2437
0
            if (!ok)
2438
0
            {
2439
0
                *ret = _IS_ERROR;
2440
0
                goto exit_function;
2441
0
            }
2442
0
            n_edits++;
2443
0
        }
2444
0
    }
2445
    
2446
    /* Add bonds */
2447
0
    if (n_new_bond)
2448
0
    {
2449
0
        for (i = 0; i < 2 * n_new_bond; i += 2)
2450
0
        {
2451
0
            a1 = ed->new_bond->item[i] - 1;
2452
0
            a2 = ed->new_bond->item[i + 1] - 1;
2453
            /* TODO: consider real bond_type, bond_stereo */
2454
            /* OrigAtData_AddSingleStereolessBond( a1, a2, at, &dummy ); */
2455
0
            ok = OrigAtData_AddBond(a1, a2, at, bond_type, bond_stereo, &orig_at_data->num_inp_bonds);
2456
0
            if (!ok)
2457
0
            {
2458
0
                *ret = _IS_ERROR;
2459
0
                goto exit_function;
2460
0
            }
2461
0
            n_edits++;
2462
0
        }
2463
0
    }
2464
    
2465
    /* Modify bonds */
2466
0
    if (n_mod_bond)
2467
0
    {
2468
0
        for (j = 0; j < 4 * n_mod_bond; j += 4)
2469
0
        {
2470
0
            old_a1 = ed->mod_bond->item[j];
2471
0
            old_a2 = ed->mod_bond->item[j + 1];
2472
0
            new_a1 = ed->mod_bond->item[j + 2];
2473
0
            new_a2 = ed->mod_bond->item[j + 3];
2474
0
            if ((old_a1 == new_a1&&old_a2 == new_a2) || (old_a2 == new_a1&&old_a1 == new_a2))
2475
0
            {
2476
0
                continue;
2477
0
            }
2478
0
            ok = OrigAtData_RemoveBond(old_a1 - 1, old_a2 - 1, at, &bond_type, &bond_stereo, &orig_at_data->num_inp_bonds);
2479
0
            if (!ok)
2480
0
            {
2481
0
                *ret = _IS_ERROR;
2482
0
                goto exit_function;
2483
0
            }
2484
0
            ok = OrigAtData_AddBond(new_a1 - 1, new_a2 - 1, at, bond_type, bond_stereo, &orig_at_data->num_inp_bonds);
2485
0
            if (!ok)
2486
0
            {
2487
0
                *ret = _IS_ERROR;
2488
0
                goto exit_function;
2489
0
            }
2490
            /* Correct CRU blist lists */
2491
0
            for (i = 0; i < p->n; i++)
2492
0
            {
2493
0
                OAD_PolymerUnit *u = p->units[i];
2494
0
                if (!u->blist)
2495
0
                {
2496
                    /* No crossing bonds in the unit */
2497
0
                    continue;
2498
0
                }
2499
0
                if ( bIsSameBond(u->blist[0], u->blist[1], old_a1, old_a2) )
2500
0
                {
2501
0
                    u->blist[0] = new_a1;
2502
0
                    u->blist[1] = new_a2;
2503
0
                }
2504
0
                else if ( bIsSameBond(u->blist[2], u->blist[3], old_a1, old_a2) )
2505
0
                {
2506
0
                    u->blist[2] = new_a1;
2507
0
                    u->blist[3] = new_a2;
2508
0
                }
2509
0
            }
2510
2511
0
            n_edits++;
2512
0
        }
2513
0
    }
2514
2515
    /* Modify coordinates */
2516
0
    if (n_mod_coord)
2517
0
    {
2518
0
        for (j = 0; j < 2 * n_mod_coord; j += 2)
2519
0
        {
2520
0
            old_a1 = ed->mod_coord->item[j];
2521
0
            new_a1 = ed->mod_bond->item[j + 1];
2522
0
            swap_atoms_xyz(orig_at_data, old_a1 - 1, new_a1 - 1);
2523
0
            n_edits++;
2524
0
        }
2525
0
    }
2526
2527
    
2528
    /* Delete atoms */
2529
0
    if (n_del_atom)
2530
0
    {
2531
0
        int nat0, nat, nacc;
2532
0
        inp_ATOM *new_at = NULL, *new_at0=NULL;
2533
2534
0
        at_renum = (int *)inchi_calloc(n_max_stored, sizeof(int));
2535
0
        if (!at_renum)
2536
0
        {
2537
0
            *ret = _IS_ERROR;
2538
0
            goto exit_function;
2539
0
        }
2540
        /* all-purpose buffer */
2541
0
        ibuf = (int *)inchi_calloc(n_max_stored, sizeof(int));
2542
0
        if (!ibuf)
2543
0
        {
2544
0
            *ret = _IS_ERROR;
2545
0
            goto exit_function;
2546
0
        }
2547
2548
0
        fail = mark_atoms_to_delete_or_renumber(orig_at_data, ed, at_renum); 
2549
0
        if (fail)
2550
0
        {
2551
0
            *ret = _IS_ERROR;
2552
0
            goto exit_function;
2553
0
        }
2554
        /* Now remove atom by atom */
2555
2556
0
        nat0 = orig_at_data->num_inp_atoms;
2557
0
        nat = nat0 - ed->del_atom->used;
2558
0
        new_at = (inp_ATOM  *)inchi_calloc(nat, sizeof(new_at[0]));
2559
0
        if (!new_at)
2560
0
        {
2561
0
            *ret = _IS_ERROR;
2562
0
            goto exit_function;
2563
0
        }
2564
2565
0
        for (i = 0, nacc = 0; i < nat0; i++)
2566
0
        {
2567
0
            AT_NUMB nbr0[MAXVAL];
2568
0
            U_CHAR btype0[MAXVAL];
2569
0
            int m, macc, valen;
2570
0
            int new_num = at_renum[i];        
2571
0
            if (new_num == -1)
2572
0
            {
2573
                /* Skip removed atom */
2574
0
                continue;
2575
0
            }
2576
2577
            /* Atom to keep; copy it */ 
2578
0
            new_at0 = new_at + nacc;
2579
0
            ++nacc;
2580
0
            memcpy(new_at0, orig_at_data->at + i, sizeof(new_at[0]));
2581
            /* Correct its own number(s) */
2582
0
            new_at0->orig_at_number = new_num + 1;
2583
            
2584
            /* Correct its nbr number(s) */
2585
0
            valen = new_at0->valence;
2586
0
            memcpy(nbr0, new_at0->neighbor, valen * sizeof(AT_NUMB));
2587
0
            memcpy(btype0, new_at0->bond_type, valen);
2588
0
            memset(new_at0->neighbor, 0, valen); /* djb-rwth: memset_s C11/Annex K variant? */
2589
0
            for (m = 0, macc=0; m < valen; m++)
2590
0
            {
2591
0
                int num2 = nbr0[m];
2592
0
                int renum2 = at_renum[num2];
2593
0
                if (renum2 == num2)
2594
0
                {
2595
                    /* keep old */
2596
0
                    new_at0->neighbor[macc++] = num2; 
2597
0
                }
2598
0
                else if (renum2 == -1)
2599
0
                {
2600
                    /* skip and decrement valences */
2601
0
                    new_at0->chem_bonds_valence -= btype0[m];
2602
0
                    new_at0->valence--;
2603
0
                }
2604
0
                else 
2605
0
                {
2606
                    /* set renumbered */
2607
0
                    new_at0->neighbor[macc++] = renum2;
2608
0
                }
2609
0
            }
2610
0
        }
2611
2612
0
        if (new_at)
2613
0
        {
2614
0
            inchi_free(orig_at_data->at);
2615
0
            orig_at_data->at = new_at;
2616
0
        }
2617
2618
0
        orig_at_data->num_inp_atoms = nacc;
2619
0
        orig_at_data->num_inp_bonds = 0;
2620
0
        for (i = 0; i < nacc; i++)
2621
0
        {
2622
0
            orig_at_data->num_inp_bonds += new_at[i].valence;
2623
0
        }
2624
0
        orig_at_data->num_inp_bonds /= 2;
2625
2626
        /* Correct other data */
2627
2628
        /* Correct polymer data */
2629
0
        if (p)
2630
0
        {
2631
0
            int iu;
2632
2633
0
            for (iu = 0; iu < p->n; iu++)
2634
0
            {
2635
0
                OAD_PolymerUnit* u = p->units[iu];
2636
0
                int new_na, new_nb, new_bb;
2637
0
                memset(ibuf, 0, n_max_stored * sizeof(ibuf[0])); /* djb-rwth: memset_s C11/Annex K variant? */
2638
0
                if (u)
2639
0
                {
2640
0
                    if (u->alist)
2641
0
                    {
2642
0
                        memcpy(ibuf, u->alist, u->na * sizeof(ibuf[0]));
2643
0
                        new_na = set_renumbered_or_delete(u->alist, ibuf, u->na, at_renum, 1);
2644
0
                        if (new_na == -1)
2645
0
                        {
2646
0
                            *ret = _IS_ERROR;
2647
0
                            goto exit_function;
2648
0
                        }
2649
0
                        u->na = new_na;
2650
0
                    }
2651
0
                    if (u->blist)
2652
0
                    {
2653
0
                        memcpy(ibuf, u->blist, 2 * (long long)u->nb * sizeof(int)); /* djb-rwth: cast operator added */
2654
0
                        new_nb = set_renumbered_or_delete(u->blist, ibuf, 2*u->nb, at_renum, 1);
2655
0
                        new_nb /= 2;
2656
0
                        if (new_nb == -1)
2657
0
                        {
2658
0
                            *ret = _IS_ERROR;
2659
0
                            goto exit_function;
2660
0
                        }
2661
0
                        u->nb = new_nb;
2662
0
                    }
2663
2664
2665
0
                    if (u->bkbonds)
2666
0
                    {
2667
0
                        int b, new_nbkbonds;
2668
0
                        for (b = 0, new_nbkbonds = 0; b < u->nbkbonds; b++)
2669
0
                        {
2670
0
                            int bnd[2];
2671
0
                            bnd[0] = u->bkbonds[b][0];
2672
0
                            bnd[1] = u->bkbonds[b][1];
2673
0
                            memcpy(ibuf, bnd, 2 * sizeof(ibuf[0]));
2674
0
                            memset(u->bkbonds[b], 0, 2 * sizeof(u->bkbonds[0][0])); /* djb-rwth: memset_s C11/Annex K variant? */
2675
0
                            new_bb = set_renumbered_or_delete(bnd, ibuf, 2, at_renum, 1);
2676
0
                            if (new_bb == -1)
2677
0
                            {
2678
0
                                *ret = _IS_ERROR;
2679
0
                                goto exit_function;
2680
0
                            }
2681
0
                            else if (new_bb == 2)
2682
0
                            {
2683
0
                                u->bkbonds[new_nbkbonds][0] = bnd[0];
2684
0
                                u->bkbonds[new_nbkbonds][1] = bnd[1];
2685
0
                                new_nbkbonds++;
2686
                                /* OK, settled new nums or kept old */
2687
0
                            }
2688
0
                            else
2689
0
                            {
2690
0
                                continue;
2691
0
                            }
2692
0
                        }
2693
0
                        u->nbkbonds = new_nbkbonds;
2694
0
                    }
2695
2696
0
                    if (u->blist) /* djb-rwth: fixing a NULL pointer dereference */
2697
0
                    {
2698
0
                        u->cap1 = u->blist[0];
2699
0
                        u->end_atom1 = u->blist[1];
2700
0
                        u->cap2 = u->blist[2];
2701
0
                        u->end_atom2 = u->blist[3];
2702
0
                    }
2703
0
                    if (u->cap1 < 1 || u->cap2 < 1 || u->end_atom1 < 1 || u->end_atom2 < 1)
2704
0
                    {
2705
0
                        *ret = _IS_ERROR;
2706
0
                        goto exit_function;
2707
0
                    }
2708
2709
2710
0
                }
2711
0
            }
2712
0
        } /* if (p) */
2713
2714
        /* Correct V300 data */
2715
0
        if (orig_at_data->v3000)
2716
0
        {
2717
0
            ;
2718
0
        }
2719
2720
2721
0
    } /* if (n_del_atom) */
2722
    
2723
2724
0
exit_function:
2725
0
    if (ibuf)
2726
0
    {
2727
0
        inchi_free(ibuf);
2728
0
    }
2729
0
    if (at_renum)
2730
0
    {
2731
0
        inchi_free(at_renum);
2732
0
    }
2733
0
    return n_edits;
2734
0
}
2735
                                
2736
2737
/****************************************************************************
2738
 Set each element of number to renum[element] or delete it if renum==(base -1)
2739
 base is either 0 (0-started numbers) or 1 (1-started)
2740
 Returns new number of elements or -1 at error
2741
****************************************************************************/
2742
int set_renumbered_or_delete( int *number,  /* numbers to correct */
2743
                              int *buf,   /* must be enough size to hold nelems elements */
2744
                              int nelems, /* initial size of numbers */
2745
                              int *renum, /* new numbers in order of old numbers; always 0-based */
2746
                              int base)
2747
0
{
2748
0
    int i, new_nelems;
2749
0
    memcpy(buf, number, nelems * sizeof(int));
2750
0
    memset(number, 0, nelems * sizeof(int)); /* djb-rwth: memset_s C11/Annex K variant? */
2751
0
    for (i = 0, new_nelems = 0; i < nelems; i++)
2752
0
    {
2753
0
        int new_num = renum[ buf[i]-base ] + base;
2754
0
        if (new_num == (base-1))
2755
0
        {
2756
0
            continue;
2757
0
        }
2758
0
        else
2759
0
        {
2760
0
            number[new_nelems++] = new_num;
2761
0
        }
2762
0
    }
2763
0
    return new_nelems;
2764
0
}
2765
2766
2767
/****************************************************************************
2768
 Worker placed under ProcessOneStructure wrapper (not the last nested doll)
2769
****************************************************************************/
2770
int ProcessOneStructureExCore( struct tagINCHI_CLOCK *ic,
2771
                               struct tagCANON_GLOBALS  *CG,
2772
                               STRUCT_DATA *sd,
2773
                               INPUT_PARMS *ip,
2774
                               char *szTitle,
2775
                               PINChI2 *pINChI2[INCHI_NUM],
2776
                               PINChI_Aux2 *pINChI_Aux2[INCHI_NUM],
2777
                               INCHI_IOSTREAM *inp_file,
2778
                               INCHI_IOSTREAM *log_file,
2779
                               INCHI_IOSTREAM *out_file,
2780
                               INCHI_IOSTREAM *prb_file,
2781
                               ORIG_ATOM_DATA *orig_inp_data,
2782
                               ORIG_ATOM_DATA *prep_inp_data,
2783
                               long num_inp,
2784
                               INCHI_IOS_STRING *strbuf,
2785
                               unsigned char save_opt_bits )
2786
0
{
2787
0
    int res = _IS_OKAY;
2788
0
    int mind_polymers;
2789
2790
#ifdef TARGET_LIB_FOR_WINCHI
2791
    inchi_ios_free_str( out_file );
2792
    inchi_ios_print(out_file, "Structure: %d\n", num_inp);
2793
#endif
2794
2795
    /* Polymer and pseudoelement specific */
2796
0
    res = ValidateAndPreparePolymerAndPseudoatoms( ic, CG, sd, ip, szTitle, pINChI2, pINChI_Aux2,
2797
0
                                                    inp_file, log_file, out_file, prb_file,
2798
0
                                                    orig_inp_data, prep_inp_data, num_inp, strbuf,
2799
0
                                                    save_opt_bits, &mind_polymers);
2800
0
    if (res== _IS_ERROR || res == _IS_FATAL )
2801
0
    {
2802
0
        return res;
2803
0
    }
2804
2805
    /* Call the very actual worker placed under this (ProcessOneStructureCore) wrapper */
2806
0
    res = ProcessOneStructure( ic, CG, sd, ip, szTitle, pINChI2, pINChI_Aux2,
2807
0
                               inp_file, log_file, out_file, prb_file,
2808
0
                               orig_inp_data, prep_inp_data, num_inp, strbuf,
2809
0
                               save_opt_bits);
2810
2811
0
    if ( (res == _IS_OKAY  || res == _IS_WARNING ) && mind_polymers )
2812
0
    {
2813
        /* Post-edit the polymer layer at older polymer treatment modes (1.05, 1.05+) */
2814
0
        if (ip->bPolymers == POLYMERS_LEGACY || ip->bPolymers == POLYMERS_LEGACY_PLUS)
2815
0
        {
2816
            /* Cut and hide "Zz" and related things in InChI (AuxInfo has a specifics). */
2817
0
            int n_pzz = 0, n_zy = orig_inp_data->n_zy;
2818
0
            if (orig_inp_data->polymer)
2819
0
            {
2820
0
                n_pzz = orig_inp_data->polymer->n_pzz;
2821
0
            }
2822
2823
0
            EditINCHI_HidePolymerZz(out_file, n_pzz, n_zy);
2824
2825
0
        }
2826
0
    }
2827
2828
#ifdef TARGET_LIB_FOR_WINCHI
2829
/*  if ( res == _IS_ERROR || res == _IS_FATAL )
2830
    {
2831
        inchi_ios_print(out_file, "Error %d (%s)\n", sd->nErrorCode, sd->pStrErrStruct);
2832
    }
2833
*/
2834
    /*push_to_winchi_text_window(out_file); */
2835
    /*inchi_ios_free_str(out_file);*/
2836
    /*inchi_ios_flush(out_file);*/
2837
#endif
2838
2839
0
    return res;
2840
0
}
2841
2842
2843
/****************************************************************************
2844
 Treat pseudoelement and polymers: parse, validate and set details 
2845
****************************************************************************/
2846
int ValidateAndPreparePolymerAndPseudoatoms( struct tagINCHI_CLOCK *ic,
2847
                                             struct tagCANON_GLOBALS *CG,
2848
                                             STRUCT_DATA *sd,
2849
                                             INPUT_PARMS *ip,
2850
                                             char *szTitle,
2851
                                             PINChI2 *pINChI2[INCHI_NUM],
2852
                                             PINChI_Aux2 *pINChI_Aux2[INCHI_NUM],
2853
                                             INCHI_IOSTREAM *inp_file,
2854
                                             INCHI_IOSTREAM *log_file,
2855
                                             INCHI_IOSTREAM *out_file,
2856
                                             INCHI_IOSTREAM *prb_file,
2857
                                             ORIG_ATOM_DATA *orig_inp_data,
2858
                                             ORIG_ATOM_DATA *prep_inp_data,
2859
                                             long num_inp,
2860
                                             INCHI_IOS_STRING *strbuf,
2861
                                             unsigned char save_opt_bits,
2862
                                             int *mind_polymers )
2863
0
{
2864
0
    int res = _IS_OKAY;
2865
2866
0
    int mind_pseudoelements = 0;
2867
    
2868
0
    *mind_polymers = orig_inp_data && orig_inp_data->polymer && orig_inp_data->polymer->n > 0;
2869
0
    *mind_polymers = *mind_polymers && orig_inp_data->valid_polymer &&
2870
0
        (ip->nInputType == INPUT_MOLFILE || ip->nInputType == INPUT_SDFILE);
2871
0
    mind_pseudoelements = (ip->bNPZz == 1) || (ip->bPolymers != POLYMERS_NO);
2872
2873
2874
    /* Validate the data */
2875
0
    res = OAD_ValidatePolymerAndPseudoElementData(orig_inp_data,
2876
0
        ip->bPolymers,
2877
0
        ip->bNPZz,
2878
0
        sd->pStrErrStruct,
2879
0
        ip->bNoWarnings);
2880
0
    if (res)
2881
0
    {
2882
0
        sd->nErrorCode = res;
2883
0
        inchi_ios_eprint( log_file, "Error %d (%s) structure #%ld.%s%s%s%s\n",
2884
0
                          sd->nErrorCode, sd->pStrErrStruct, num_inp,
2885
0
                          SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
2886
0
        res = _IS_ERROR;
2887
0
        if (orig_inp_data) /* djb-rwth: fixing a NULL pointer dereference */
2888
0
            orig_inp_data->num_inp_atoms = -1;
2889
0
        goto exit_function;
2890
0
    }
2891
2892
0
    if (*mind_polymers || mind_pseudoelements)
2893
0
    {
2894
        /*OrigAtData_DebugTrace(orig_inp_data);*/
2895
0
        if (*mind_polymers &&
2896
0
            ip->bPolymers != POLYMERS_MODERN &&
2897
0
            (ip->bFrameShiftScheme == FSS_STARS_CYCLED || ip->bFrameShiftScheme == FSS_STARS_CYCLED_SORTED))
2898
0
        {
2899
            /*  Analyze and cyclize frame-shift eligible CRUs using InChI canonical numbers 
2900
                (do this only at older polymer treatment modes 1.05, 1.05+)         
2901
            */
2902
0
            res = OAD_Polymer_CyclizeCloseableUnits( orig_inp_data,
2903
0
                                                     ip->bPolymers,
2904
0
                                                     sd->pStrErrStruct,
2905
0
                                                     ip->bNoWarnings );
2906
0
            if (res)
2907
0
            {
2908
0
                sd->nErrorCode = res;
2909
0
                AddErrorMessage(sd->pStrErrStruct, "Error while processing polymer-related input");
2910
0
                res = _IS_ERROR;
2911
0
                orig_inp_data->num_inp_atoms = -1;
2912
0
                goto exit_function;
2913
0
            }
2914
            /*OrigAtData_DebugTrace(orig_inp_data);*/
2915
0
        }
2916
0
    }
2917
2918
0
exit_function:
2919
2920
0
    return res;
2921
0
}
2922
2923
2924
/****************************************************************************
2925
 Get InChI and AuxInfo of totally unedited original structure.
2926
 The intent is to preserve AuxInfo for the very original structure
2927
 in order to keep a final ability to restore that structure. 
2928
****************************************************************************/
2929
int OAD_ProcessOneStructureNoEdits( struct tagINCHI_CLOCK    *ic,
2930
                                    struct tagCANON_GLOBALS  *CG,
2931
                                    STRUCT_DATA              *sd,
2932
                                    INPUT_PARMS              *ip,
2933
                                    char                     *szTitle,
2934
                                    PINChI2                  *pINChI2[INCHI_NUM],
2935
                                    PINChI_Aux2              *pINChI_Aux2[INCHI_NUM],
2936
                                    INCHI_IOSTREAM           *inp_file,
2937
                                    INCHI_IOSTREAM           *log_file,
2938
                                    INCHI_IOSTREAM           *out_file,
2939
                                    INCHI_IOSTREAM           *prb_file,
2940
                                    ORIG_ATOM_DATA           *orig_inp_data,
2941
                                    ORIG_ATOM_DATA           *prep_inp_data,
2942
                                    long                     num_inp,
2943
                                    INCHI_IOS_STRING         *strbuf,
2944
                                    unsigned char            save_opt_bits,
2945
                                    int                      *n_pzz,
2946
                                    char           **sinchi, 
2947
                                    char           **saux)
2948
0
{
2949
0
    size_t slen;
2950
0
    int ret = _IS_OKAY, dup_fail = 0;
2951
0
    POSEContext dup_context, *dup = &dup_context;
2952
2953
0
    *n_pzz = 0;
2954
0
    *sinchi = NULL;
2955
0
    *saux = NULL;
2956
2957
    /* Make a working copy of all the native input */
2958
0
    dup_fail = POSEContext_Init(dup, sd, ip, szTitle, pINChI2, pINChI_Aux2,
2959
0
        inp_file, log_file, out_file, prb_file,
2960
0
        orig_inp_data, prep_inp_data,
2961
0
        num_inp, strbuf, save_opt_bits);
2962
0
    if (dup_fail)
2963
0
    {
2964
0
        ret = _IS_ERROR;
2965
0
        goto exit_function;
2966
0
    }
2967
2968
    /* Set necessary for this specific case options */
2969
0
    dup->orig_inp_data->polymer->treat = dup->ip.bPolymers = POLYMERS_MODERN;
2970
0
    dup->ip.bFoldPolymerSRU = 0;
2971
0
    dup->ip.bFrameShiftScheme = FSS_NONE;
2972
0
    dup->ip.bINChIOutputOptions &= ~(INCHI_OUT_NO_AUX_INFO | INCHI_OUT_SHORT_AUX_INFO);
2973
0
    dup->ip.bDisplay = dup->ip.bDisplayCompositeResults = dup->ip.bDisplayEachComponentINChI = 0;
2974
0
    dup->ip.bFoldPolymerSRU = 0;
2975
    /*dup->ip.bTautFlags |= TG_FLAG_RECONNECT_COORD;*/
2976
2977
    /* Calculate */
2978
0
    ret = ProcessOneStructureExCore( ic, CG, &dup->sd, &dup->ip, dup->szTitle,
2979
0
                                     dup->pINChI2, dup->pINChI_Aux2,
2980
0
                                     dup->inp_file, dup->log_file,
2981
0
                                     dup->out_file, dup->prb_file,
2982
0
                                     dup->orig_inp_data, dup->prep_inp_data,
2983
0
                                     dup->num_inp, dup->strbuf, dup->save_opt_bits );
2984
2985
0
    if (ret == _IS_FATAL || ret == _IS_ERROR)
2986
0
    {
2987
0
        goto exit_function;
2988
0
    }
2989
    
2990
0
    *n_pzz = dup->orig_inp_data->polymer->n_pzz;
2991
    /* Extract InChI */
2992
0
    slen = dup->out_file->s.nUsedLength;
2993
0
    extract_inchi_substring(sinchi, dup->out_file->s.pStr, slen);
2994
0
    if (!*sinchi)
2995
0
    {
2996
0
        ret = _IS_ERROR;
2997
0
    }
2998
0
    if (ret == _IS_FATAL || ret == _IS_ERROR)
2999
0
    {
3000
0
        goto exit_function;
3001
0
    }
3002
    /* Extract AuxInfo */
3003
0
    slen = dup->out_file->s.nUsedLength;
3004
0
    extract_auxinfo_substring(saux, dup->out_file->s.pStr, slen);
3005
0
    if (!*saux)
3006
0
    {
3007
0
        ret = _IS_ERROR;
3008
0
    }
3009
0
    if (ret == _IS_FATAL || ret == _IS_ERROR)
3010
0
    {
3011
0
        goto exit_function;
3012
0
    }
3013
3014
0
exit_function:
3015
0
    POSEContext_Free(dup);
3016
3017
0
    return ret;
3018
0
}
3019
3020
3021
/****************************************************************************
3022
Get InChI and AuxInfo of original structure using 1.05+ InChI version.
3023
****************************************************************************/
3024
int OAD_ProcessOneStructure105Plus( struct tagINCHI_CLOCK    *ic,
3025
                                    struct tagCANON_GLOBALS  *CG,
3026
                                    STRUCT_DATA              *sd,
3027
                                    INPUT_PARMS              *ip,
3028
                                    char                     *szTitle,
3029
                                    PINChI2                  *pINChI2[INCHI_NUM],
3030
                                    PINChI_Aux2              *pINChI_Aux2[INCHI_NUM],
3031
                                    INCHI_IOSTREAM           *inp_file,
3032
                                    INCHI_IOSTREAM           *log_file,
3033
                                    INCHI_IOSTREAM           *out_file,
3034
                                    INCHI_IOSTREAM           *prb_file,
3035
                                    ORIG_ATOM_DATA           *orig_inp_data,
3036
                                    ORIG_ATOM_DATA           *prep_inp_data,
3037
                                    long                     num_inp,
3038
                                    INCHI_IOS_STRING         *strbuf,
3039
                                    unsigned char            save_opt_bits,
3040
                                    char           **sinchi,
3041
                                    char           **saux)
3042
0
{
3043
0
    size_t slen;
3044
0
    int ret = _IS_OKAY, dup_fail = 0;
3045
0
    POSEContext dup_context, *dup = &dup_context;
3046
3047
0
    *sinchi = NULL;
3048
0
    *saux = NULL;
3049
3050
    /* Make a working copy of all the native input */
3051
0
    dup_fail = POSEContext_Init(dup, sd, ip, szTitle, pINChI2, pINChI_Aux2,
3052
0
                                inp_file, log_file, out_file, prb_file,
3053
0
                                orig_inp_data, prep_inp_data,
3054
0
                                num_inp, strbuf, save_opt_bits);
3055
0
    if (dup_fail)
3056
0
    {
3057
0
        ret = _IS_ERROR;
3058
0
        goto exit_function;
3059
0
    }
3060
3061
    /* Set necessary for this specific case options */
3062
    /* 1.05+ polymer treatment mode: hidden Zz, senior bkbond comes the first */
3063
0
    dup->orig_inp_data->polymer->treat = dup->ip.bPolymers = POLYMERS_LEGACY_PLUS;
3064
    /* include full aux info */
3065
0
    dup->ip.bINChIOutputOptions &= ~(INCHI_OUT_NO_AUX_INFO | INCHI_OUT_SHORT_AUX_INFO);
3066
    /* request no /D display in inchi-1 executable */
3067
0
    dup->ip.bDisplay = dup->ip.bDisplayCompositeResults = dup->ip.bDisplayEachComponentINChI = 0;
3068
3069
    /* Calculate */
3070
0
    ret = ProcessOneStructureExCore(ic, CG, &dup->sd, &dup->ip, dup->szTitle,
3071
0
                                    dup->pINChI2, dup->pINChI_Aux2,
3072
0
                                    dup->inp_file, dup->log_file,
3073
0
                                    dup->out_file, dup->prb_file,
3074
0
                                    dup->orig_inp_data, dup->prep_inp_data,
3075
0
                                    dup->num_inp, dup->strbuf, dup->save_opt_bits);
3076
3077
0
    if (ret == _IS_FATAL || ret == _IS_ERROR)
3078
0
    {
3079
0
        goto exit_function;
3080
0
    }
3081
3082
    /* Extract InChI */
3083
0
    slen = dup->out_file->s.nUsedLength;
3084
0
    extract_inchi_substring(sinchi, dup->out_file->s.pStr, slen);
3085
0
    if (!*sinchi)
3086
0
    {
3087
0
        ret = _IS_ERROR;
3088
0
    }
3089
0
    if (ret == _IS_FATAL || ret == _IS_ERROR)
3090
0
    {
3091
0
        goto exit_function;
3092
0
    }
3093
    /* Extract AuxInfo */
3094
0
    slen = dup->out_file->s.nUsedLength;
3095
0
    extract_auxinfo_substring(saux, dup->out_file->s.pStr, slen);
3096
0
    if (!*saux)
3097
0
    {
3098
0
        ret = _IS_ERROR;
3099
0
    }
3100
0
    if (ret == _IS_FATAL || ret == _IS_ERROR)
3101
0
    {
3102
0
        goto exit_function;
3103
0
    }
3104
3105
3106
0
exit_function:
3107
0
    POSEContext_Free(dup);
3108
3109
0
    return ret;
3110
0
}
3111
3112
3113
/****************************************************************************
3114
 Mark atoms to be renumbered or removed
3115
 at_renum[initial number] := new_number or -1 (mark of deletion)
3116
****************************************************************************/
3117
int mark_atoms_to_delete_or_renumber( ORIG_ATOM_DATA *orig_at_data,
3118
                                      OAD_StructureEdits *ed,
3119
                                      int *at_renum)
3120
0
{
3121
0
    int i, j;
3122
0
    int fail=0, ret = 0;
3123
0
    size_t *atnums = NULL; /* djb-rwth: needs to be size_t type */
3124
0
    size_t max_atoms = orig_at_data->num_inp_atoms;
3125
3126
    /* NB:  new/old ORIG_ATOM_DATA atom numbers are 0-based (==orig_number-1) 
3127
            while those in ed->... are just 1-based orig_numbers */
3128
    
3129
0
    for (i = 0; (size_t)i < max_atoms; i++)
3130
0
    {
3131
0
        at_renum[i] = i;
3132
0
    }
3133
3134
0
    if (ed->del_side_chains)
3135
0
    {
3136
        /* Extend list of atoms to be deleted with those connected to original ones
3137
        (i.e., delete a whole connected component(s) comprising original atoms)
3138
        */
3139
0
        int natnums = 0;
3140
0
        atnums = (size_t *)inchi_calloc(max_atoms, sizeof(size_t)); /* djb-rwth: size_t type used for max_atoms to fit the definition of inchi_calloc  */
3141
0
        if (!atnums)
3142
0
        {
3143
0
            return _IS_ERROR;
3144
0
        }
3145
0
        for (i = 0; (size_t)i < max_atoms; i++)
3146
0
        {
3147
0
            int iatom = ed->del_atom->item[i] - 1;
3148
0
            subgraf *sg = NULL;
3149
0
            subgraf_pathfinder *spf = NULL;
3150
0
            if (i >= ed->del_atom->used) /* NB: ed->del_atom->used may be increased within this loop */
3151
0
            {
3152
0
                break;
3153
0
            }
3154
0
            for (j = 0; (size_t)j < max_atoms; j++)
3155
0
            {
3156
0
                atnums[j] = orig_at_data->at[j].orig_at_number; /*j+1;*/
3157
0
            }
3158
0
            sg = subgraf_new(orig_at_data, max_atoms, (int*)atnums);
3159
0
            memset(atnums, 0, max_atoms * sizeof(int)); /* djb-rwth: memset_s C11/Annex K variant? */
3160
0
            if (!sg)
3161
0
            {
3162
0
                ret = _IS_ERROR;
3163
0
                goto exit_function;
3164
0
            }
3165
0
            spf = subgraf_pathfinder_new(sg, orig_at_data, iatom, iatom);
3166
0
            if (!spf)
3167
0
            {
3168
0
                ret = _IS_ERROR;
3169
0
                goto exit_function;
3170
0
            }
3171
0
            spf->start = iatom;
3172
0
            spf->nseen = 0;
3173
0
            natnums = subgraf_pathfinder_collect_all(spf, 0, NULL, (int*)atnums);
3174
0
            if (natnums)
3175
0
            {
3176
0
                for (j = 0; j < natnums; j++)
3177
0
                {
3178
0
                    fail = IntArray_AppendIfAbsent(ed->del_atom, atnums[j]); /* djb-rwth: ui_rr? */
3179
0
                    if (fail)
3180
0
                    {
3181
0
                        ret = _IS_ERROR;
3182
0
                        goto exit_function;
3183
0
                    }
3184
0
                }
3185
0
            }
3186
0
            subgraf_free(sg);
3187
0
            subgraf_pathfinder_free(spf);
3188
0
        }
3189
3190
0
    } /* if (ed->del_side_chains) */
3191
3192
0
    for (i = max_atoms - 1; i >= 0; i--)
3193
0
    {
3194
0
        int orig_num = i + 1; /* NB: ed->del_atom->item contains orig# which are (OAD# + 1) */
3195
0
        if (is_in_the_ilist(ed->del_atom->item, orig_num, ed->del_atom->used)) 
3196
0
        {
3197
            /* mark as deleted atnum */
3198
0
            at_renum[i] = -1;
3199
            /* shift other atnums */
3200
0
            for (j = max_atoms - 1; j > i; j--)
3201
0
            {
3202
0
                if (at_renum[j] != -1)
3203
0
                {
3204
0
                    at_renum[j]--;
3205
0
                }
3206
0
            }
3207
0
        }
3208
0
    }
3209
3210
3211
0
exit_function:
3212
0
    if (atnums)
3213
0
    {
3214
0
        inchi_free(atnums);
3215
0
    }
3216
0
    return ret;
3217
0
}
3218
3219
3220
#if (BUILD_WITH_ENG_OPTIONS==1)
3221
#if ALLOW_SUBSTRUCTURE_FILTERING==1
3222
int check_presence_of_the_encoded_substructure(ORIG_ATOM_DATA *orig_inp_data);
3223
int OrigAtData_CheckForSubstructure(ORIG_ATOM_DATA *orig_inp_data)
3224
{
3225
    int ok = 0;
3226
3227
    ok = check_presence_of_the_encoded_substructure(orig_inp_data);
3228
3229
    return ok;
3230
}
3231
int check_presence_of_the_encoded_substructure(ORIG_ATOM_DATA *oad)
3232
{
3233
    int i, ok;
3234
3235
    /* Place sub-structure filtering code below.
3236
3237
       Return 1 if structure matches some hard-coded pattern
3238
       
3239
       In this example pattern is a presence of a pseudo atom.
3240
    */
3241
3242
    ok = 0;
3243
    for (i = 0; i < oad->num_inp_atoms; i++)
3244
    {
3245
        if (oad->at[i].el_number == EL_NUMBER_ZZ || oad->at[i].el_number == EL_NUMBER_ZY)
3246
        {
3247
            ok = 1;
3248
            break;
3249
        }
3250
    }
3251
    return ok;
3252
}
3253
#endif
3254
#endif