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