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