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 : : SortAndPrintINChI and misc. processing (display, tests, error treatment, etc.)
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 : :
55 : : #include "mode.h"
56 : :
57 : : #ifndef COMPILE_ANSI_ONLY
58 : : #include <conio.h>
59 : : #endif
60 : :
61 : : #include "ichimain.h"
62 : : #include "ichi_io.h"
63 : : #include "mol_fmt.h"
64 : : #include "ichicant.h"
65 : : #include "inchi_api.h"
66 : : #include "readinch.h"
67 : : #ifdef TARGET_LIB_FOR_WINCHI
68 : : #include "../../../IChI_lib/src/ichi_lib.h"
69 : : #include "inchi_api.h"
70 : : #else
71 : : #include "inchi_gui.h"
72 : : #endif
73 : : #include "readinch.h"
74 : :
75 : : #include "bcf_s.h"
76 : :
77 : : #ifdef TARGET_LIB_FOR_WINCHI
78 : :
79 : : void( *FWPRINT )
80 : : ( const char * format, va_list argptr ) = NULL;
81 : : void( *FWPUSH )
82 : : ( const char *s );
83 : : void( *DRAWDATA )
84 : : ( struct DrawData * pDrawData ) = NULL;
85 : : int( *DRAWDATA_EXISTS )
86 : : ( int nComponent, int nType, int bReconnected ) = NULL;
87 : : struct DrawData * ( *GET_DRAWDATA )
88 : : ( int nComponent, int nType, int bReconnected ) = NULL;
89 : : #endif
90 : :
91 : : /* Local */
92 : : int GetProcessingWarningsOneInChI( INChI *pINChI,
93 : : INP_ATOM_DATA *inp_norm_data,
94 : : char *pStrErrStruct,
95 : : int bNoWarnings);
96 : :
97 : :
98 : :
99 : : /****************************************************************************
100 : : Main InChI serialization procedure
101 : : ****************************************************************************/
102 : 54 : int SortAndPrintINChI( CANON_GLOBALS *pCG,
103 : : INCHI_IOSTREAM *out_file,
104 : : INCHI_IOS_STRING *strbuf,
105 : : INCHI_IOSTREAM *log_file,
106 : : INPUT_PARMS *ip,
107 : : ORIG_ATOM_DATA *orig_inp_data,
108 : : ORIG_ATOM_DATA *prep_inp_data,
109 : : COMP_ATOM_DATA composite_norm_data[INCHI_NUM][TAUT_NUM + 1],
110 : : ORIG_STRUCT *pOrigStruct,
111 : : int num_components[INCHI_NUM],
112 : : int num_non_taut[INCHI_NUM],
113 : : int num_taut[INCHI_NUM],
114 : : INCHI_MODE bTautFlags[INCHI_NUM],
115 : : INCHI_MODE bTautFlagsDone[INCHI_NUM],
116 : : NORM_CANON_FLAGS *pncFlags,
117 : : long num_inp,
118 : : PINChI2 *pINChI[INCHI_NUM],
119 : : PINChI_Aux2 *pINChI_Aux[INCHI_NUM],
120 : : int *pSortPrintINChIFlags,
121 : : unsigned char save_opt_bits )
122 : : {
123 : : INCHI_SORT *pINChISort[INCHI_NUM][TAUT_NUM];
124 : : int j, i, k, k1, ret, ret2, iINChI, max_num_components; /* djb-rwth: ignoring LLVM warning: variable used */
125 : : int INCHI_basic_or_INCHI_reconnected;
126 : : /* djb-rwth: removing redundant variables */
127 : 54 : int bDisconnectedCoord = ( 0 != ( bTautFlagsDone[0] & TG_FLAG_DISCONNECT_COORD_DONE ) );
128 : : int bINChIOutputOptions0, bCurOption, bINChIOutputOptionsCur, bEmbedReconnected;
129 : : static const char szAnnHdr[] = "InChI ANNOTATED CONTENTS";
130 : : #ifdef TARGET_LIB_FOR_WINCHI
131 : : int ikflag = 0;
132 : : out_file->type = INCHI_IOS_TYPE_STRING;
133 : : #endif
134 : :
135 : : /*
136 : : Note:
137 : :
138 : : pINChI[INCHI_BAS] refers to either disconnected or original structure;
139 : : num_components[INCHI_BAS] > 0 if there was input structure
140 : : pINChI[INCHI_REC] refers to the reconnected structure,
141 : : and only if the input structure has been disconnected, that is,
142 : : num_components[INCHI_REC] > 0
143 : : */
144 : :
145 : 54 : ret = 1;
146 : :
147 [ + + ]: 162 : for (i = 0; i < INCHI_NUM; i++)
148 : : {
149 [ + + ]: 324 : for (k = 0; k < TAUT_NUM; k++)
150 : : {
151 : 216 : bTautFlags[i] |= pncFlags->bTautFlags[i][k];
152 : 216 : bTautFlagsDone[i] |= pncFlags->bTautFlagsDone[i][k];
153 : : }
154 : : }
155 : :
156 : : /* djb-rwth: removing redundant code */
157 : :
158 : 54 : max_num_components = 0;
159 [ + + ]: 162 : for (j = 0; j < INCHI_NUM; j++)
160 : : {
161 [ + + ]: 108 : if (max_num_components < num_components[j])
162 : : {
163 : 54 : max_num_components = num_components[j];
164 : : }
165 : : }
166 [ - + ]: 54 : if (max_num_components <= 0)
167 : : {
168 : 0 : max_num_components = 1;
169 : : }
170 : :
171 [ + + ]: 162 : for (j = 0, i = 0; j < INCHI_NUM; j++)
172 : : {
173 [ + + ]: 108 : if (num_components[j])
174 : : {
175 [ + + ]: 162 : for (k1 = 0; k1 < TAUT_NUM; k1++)
176 : : {
177 : 108 : pINChISort[j][k1] =
178 : 108 : (INCHI_SORT *) inchi_calloc( max_num_components,
179 : : sizeof( pINChISort[0][0][0] ) );
180 : 108 : i += !pINChISort[j][k1]; /* number of failed allocatons */
181 : : }
182 : : }
183 : : else
184 : : {
185 [ + + ]: 162 : for (k1 = 0; k1 < TAUT_NUM; k1++)
186 : : {
187 : 108 : pINChISort[j][k1] = NULL; /* keep BC happy */
188 : : }
189 : : }
190 : : }
191 : :
192 [ - + ]: 54 : if (i)
193 : : {
194 : 0 : ret = CT_OUT_OF_RAM;
195 : 0 : goto exit_function;
196 : : }
197 : :
198 [ + + ]: 162 : for (j = 0; j < INCHI_NUM; j++)
199 : : {
200 [ + + ]: 108 : if (!num_components[j])
201 : : {
202 : 54 : continue;
203 : : }
204 : 54 : iINChI = j;
205 : :
206 : : #if ( OUTPUT_CONNECTED_METAL_ONLY == 1 ) /* test: output connected as the only one INChI */
207 : : if (INCHI_BAS == j && num_components[INCHI_REC])
208 : : {
209 : : j = INCHI_REC;
210 : : }
211 : : #endif
212 : :
213 : : /* j = INCHI_BAS; <- for debug only */
214 : : /* for only normal or disconnected coord compounds */
215 : : /* (j=0=INCHI_BAS => normal or disconnected, j=1=INCHI_REC => reconnected */
216 : :
217 [ + + ]: 162 : for (k1 = 0; k1 < TAUT_NUM; k1++)
218 : : {
219 [ + + ]: 246 : for (i = 0; i < num_components[j]; i++)
220 : : {
221 [ + + ]: 414 : for (k = 0; k < TAUT_NUM; k++)
222 : : {
223 : 276 : pINChISort[j][k1][i].pINChI[k] = pINChI[j][i][k];
224 : 276 : pINChISort[j][k1][i].pINChI_Aux[k] = pINChI_Aux[j][i][k];
225 : : }
226 : 138 : pINChISort[j][k1][i].ord_number = i;
227 : : }
228 : : }
229 : :
230 : : /* Sort component INChIs */
231 [ + + ]: 162 : for (k1 = 0; k1 < TAUT_NUM; k1++)
232 : : {
233 [ + + - ]: 108 : switch (k1)
234 : : {
235 : 54 : case TAUT_NON:
236 : 54 : qsort( pINChISort[j][k1],
237 : 54 : num_components[j],
238 : : sizeof( pINChISort[0][0][0] ),
239 : : CompINChINonTaut2 );
240 : 54 : break;
241 : 54 : case TAUT_YES:
242 : 54 : qsort( pINChISort[j][k1],
243 : 54 : num_components[j],
244 : : sizeof( pINChISort[0][0][0] ),
245 : : CompINChITaut2 );
246 : 54 : break;
247 : : }
248 : : }
249 : :
250 : : #ifndef COMPILE_ANSI_ONLY
251 : : /* Find equivalent and wINChI display order;
252 : : use requested in ip->bCompareComponents comparison */
253 : :
254 : : ret = SaveEquComponentsInfoAndSortOrder( iINChI, pINChISort[j],
255 : : num_components,
256 : : orig_inp_data, prep_inp_data,
257 : : #if ( FIX_DALKE_BUGS == 1 )
258 : : composite_norm_data ? composite_norm_data[j] : NULL,
259 : : #else
260 : : composite_norm_data[j],
261 : : #endif
262 : : ip->bCompareComponents );
263 : : if (RETURNED_ERROR( ret ))
264 : : {
265 : : ret = 0;
266 : : goto exit_function;
267 : : }
268 : : else
269 : : {
270 : : ret = 1;
271 : : }
272 : : #endif
273 : : } /* j */
274 : :
275 [ - + ]: 54 : if (!( ip->bINChIOutputOptions & INCHI_OUT_PRINT_OPTIONS ))
276 : : {
277 : : /* Prepare InChI from the structures obtained by
278 : : reversing InChI for returning to the caller */
279 [ # # ]: 0 : for (j = 0; j < INCHI_NUM; j++)
280 : : {
281 [ # # ]: 0 : if (!num_components[j])
282 : : {
283 : 0 : continue;
284 : : }
285 : :
286 : : /* pINChI[iINCHI][iComponent][bTaut] */
287 : : /* j = disconnected/connected */
288 : : /* k1 = sort order for Mobile or Fixed H */
289 : :
290 : 0 : k1 = TAUT_YES; /* in Mobile H order */
291 : : /* store components in Mobile H order */
292 : :
293 [ # # # # ]: 0 : for (i = 0; i < num_components[j] && i < max_num_components; i++) /* djb-rwth: fixing undefined index value / buffer overflow */
294 : : {
295 : :
296 [ # # ]: 0 : if (pINChISort[j][k1][i].pINChI[TAUT_NON] &&
297 [ # # ]: 0 : !pINChISort[j][k1][i].pINChI[TAUT_YES])
298 : : {
299 : : /* make sure Mobile-H is always present */
300 [ # # ]: 0 : for (k = 0; k < TAUT_NUM; k++)
301 : : {
302 [ # # ]: 0 : pINChI[j][i][k] = pINChISort[j][k1][i].pINChI[ALT_TAUT( k )];
303 [ # # ]: 0 : pINChI_Aux[j][i][k] = pINChISort[j][k1][i].pINChI_Aux[ALT_TAUT( k )];
304 : : }
305 : : }
306 : : else
307 : : {
308 [ # # ]: 0 : for (k = 0; k < TAUT_NUM; k++)
309 : : {
310 : 0 : pINChI[j][i][k] = pINChISort[j][k1][i].pINChI[k];
311 : 0 : pINChI_Aux[j][i][k] = pINChISort[j][k1][i].pINChI_Aux[k];
312 : : }
313 : : }
314 : : }
315 : : }
316 : : }
317 : : else
318 : : {
319 : : /* Print InChI string(s) */
320 : 54 : bINChIOutputOptions0 = ip->bINChIOutputOptions & ~INCHI_OUT_PRINT_OPTIONS;
321 : 54 : bEmbedReconnected = ip->bINChIOutputOptions & INCHI_OUT_EMBED_REC;
322 : :
323 [ + + ]: 162 : for (i = 1; i <= 2; i++)
324 : : {
325 : 108 : bCurOption = INCHI_OUT_PLAIN_TEXT;
326 [ + + ]: 108 : if (i == 2)
327 : : {
328 : 54 : bCurOption = INCHI_OUT_PLAIN_TEXT_COMMENTS;
329 : : /* continue; */
330 : : }
331 [ + + ]: 108 : if (!( ip->bINChIOutputOptions & bCurOption ))
332 : : {
333 : 54 : continue;
334 : : }
335 : :
336 : 54 : bINChIOutputOptionsCur = bINChIOutputOptions0 | bCurOption;
337 [ + - ]: 54 : if (i == 1)
338 : : {
339 : : /* output INChI */
340 : 54 : bINChIOutputOptionsCur |= bEmbedReconnected;
341 : : }
342 [ # # ]: 0 : else if (i == 2)
343 : : {
344 : : /* output annotation */
345 : 0 : inchi_ios_print( out_file, "\n==== %s ====\n", szAnnHdr );
346 : : ITRACE_( "\n==== %s ====\n", szAnnHdr );
347 : 0 : bINChIOutputOptionsCur |= bEmbedReconnected;
348 : 0 : bINChIOutputOptionsCur &= ~INCHI_OUT_TABBED_OUTPUT;
349 : : }
350 : : else
351 : : {
352 : 0 : continue;
353 : : }
354 : :
355 : : #if 0 /*^^^#ifdef TARGET_LIB_FOR_WINCHI*/
356 : : inchi_ios_free_str( out_file );
357 : : #endif
358 : :
359 : 54 : INCHI_basic_or_INCHI_reconnected = INCHI_BAS;
360 : :
361 : 54 : ret2 = OutputINChI2( pCG,
362 : : strbuf,
363 : : pINChISort,
364 : : INCHI_basic_or_INCHI_reconnected,
365 : : orig_inp_data,
366 : : pOrigStruct,
367 : : ip,
368 : : bDisconnectedCoord,
369 : : OUT_TN,
370 : : bINChIOutputOptionsCur,
371 : : num_components,
372 : : num_non_taut,
373 : : num_taut,
374 : : out_file,
375 : : log_file,
376 : : num_inp,
377 : : pSortPrintINChIFlags,
378 : : save_opt_bits );
379 : :
380 : 54 : ret &= ret2;
381 : :
382 : : #ifdef TARGET_LIB_FOR_WINCHI
383 : : /* always calculate InChIKey */
384 : : winchi_calc_inchikey( ret, &ikflag, ip, out_file, log_file );
385 : : /*push_to_winchi_text_window( out_file );
386 : : inchi_ios_flush( out_file );*/
387 : :
388 : : #endif
389 : :
390 [ - + ]: 54 : if (!ret)
391 : : {
392 : 0 : break;
393 : : }
394 : : } /* i */
395 : : }
396 : :
397 : :
398 : 54 : exit_function:
399 : :
400 [ + + ]: 162 : for (j = 0; j < INCHI_NUM; j++)
401 : : {
402 [ + + ]: 324 : for (k1 = 0; k1 < TAUT_NUM; k1++) /* djb-rwth: removing redundant code */
403 : : {
404 [ + + ]: 216 : if (pINChISort[j][k1])
405 : : {
406 [ + - ]: 108 : inchi_free( pINChISort[j][k1] );
407 : : }
408 : : }
409 : : }
410 : :
411 : :
412 [ + - ]: 54 : ret = ret ? 0 : _IS_FATAL;
413 : :
414 : 54 : return ret;
415 : : }
416 : :
417 : :
418 : : /****************************************************************************
419 : : Specific to winchi-1 calculation of InChIKey
420 : : ****************************************************************************/
421 : 0 : void winchi_calc_inchikey( int ret,
422 : : int *ikflag,
423 : : INPUT_PARMS *ip,
424 : : INCHI_IOSTREAM *out_file,
425 : : INCHI_IOSTREAM *log_file )
426 : : {
427 : : char ik_string[256]; /* Resulting InChIKey string */
428 : 0 : int ik_ret = 0; /* InChIKey-calc result code */
429 : 0 : int xhash1 = 0, xhash2 = 0;
430 : : char szXtra1[256], szXtra2[256];
431 : 0 : size_t slen = out_file->s.nUsedLength;
432 : 0 : char *buf = NULL;
433 : :
434 : 0 : ( *ikflag )++;
435 [ # # ]: 0 : if (*ikflag != 1)
436 : : {
437 : 0 : return;
438 : : }
439 : :
440 [ # # ]: 0 : if (ret == 0)
441 : : {
442 : 0 : inchi_ios_flush( out_file );
443 : 0 : return;
444 : : }
445 : :
446 : 0 : extract_inchi_substring( &buf, out_file->s.pStr, slen );
447 : :
448 : : /* Calculate and print InChIKey */
449 [ # # ]: 0 : if (NULL != buf)
450 : : {
451 : 0 : xhash1 = xhash2 = 0;
452 [ # # ]: 0 : if (( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1 ) ||
453 [ # # ]: 0 : ( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2 ))
454 : : {
455 : 0 : xhash1 = 1;
456 : : }
457 [ # # ]: 0 : if (( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA2 ) ||
458 [ # # ]: 0 : ( ip->bCalcInChIHash == INCHIHASH_KEY_XTRA1_XTRA2 ))
459 : : {
460 : 0 : xhash2 = 1;
461 : : }
462 : 0 : ik_ret = GetINCHIKeyFromINCHI( buf, xhash1, xhash2, ik_string, szXtra1, szXtra2 );
463 [ # # ]: 0 : inchi_free( buf );
464 : : }
465 : : else
466 : : {
467 : 0 : ik_ret = 3;
468 : : }
469 : :
470 [ # # ]: 0 : if (ik_ret == INCHIKEY_OK)
471 : : {
472 : : /* NB: correctly treat tabbed output with InChIKey & hash extensions */
473 : 0 : char csep = '\n';
474 [ # # ]: 0 : if (ip->bINChIOutputOptions & INCHI_OUT_TABBED_OUTPUT)
475 : : {
476 : 0 : csep = '\t';
477 : : }
478 : 0 : inchi_ios_print( out_file, "InChIKey=%-s", ik_string );
479 [ # # ]: 0 : if (xhash1)
480 : : {
481 : 0 : inchi_ios_print( out_file, "%cXHash1=%-s", csep, szXtra1 );
482 : : }
483 [ # # ]: 0 : if (xhash2)
484 : : {
485 : 0 : inchi_ios_print( out_file, "%cXHash2=%-s", csep, szXtra2 );
486 : : }
487 : 0 : inchi_ios_print( out_file, "\n" );
488 : : }
489 : : else
490 : : {
491 : 0 : inchi_ios_print( log_file, "Warning (Could not compute InChIKey)\n" ); /*: ", num_inp);*/
492 : : }
493 : : /*inchi_ios_flush(out_file);*/
494 : :
495 : 0 : return;
496 : : }
497 : :
498 : :
499 : : #ifndef COMPILE_ANSI_ONLY /* { */
500 : :
501 : :
502 : : /****************************************************************************/
503 : : int SaveEquComponentsInfoAndSortOrder( int iINChI,
504 : : INCHI_SORT *pINChISort[TAUT_NUM],
505 : : int *num_components,
506 : : ORIG_ATOM_DATA *orig_inp_data,
507 : : ORIG_ATOM_DATA *prep_inp_data,
508 : : COMP_ATOM_DATA composite_norm_data[TAUT_NUM + 1],
509 : : int bCompareComponents )
510 : : {
511 : : int nRet = 0, i, k, nNumDeleted;
512 : : int bCompareIsotopic, bCompareTaut, bCompareAlt;
513 : : ORIG_ATOM_DATA *inp_data = NULL;
514 : :
515 : : /* Equivalent components and sorting order */
516 : : /* bCompareComponents: bit = 1 => compare */
517 : : /* bit = 2 => compare non-isotopic */
518 : : /* bit = 4 => compare non-tautomeric */
519 : :
520 : : if (num_components[iINChI] <= 1)
521 : : {
522 : : return 0;
523 : : }
524 : :
525 : : #ifdef TARGET_LIB_FOR_WINCHI
526 : : if (!DRAWDATA)
527 : : return 0;
528 : : #endif
529 : :
530 : : if (!( bCompareComponents & CMP_COMPONENTS ))
531 : : {
532 : : return 0;
533 : : }
534 : :
535 : : bCompareIsotopic = !( bCompareComponents & CMP_COMPONENTS_NONISO );
536 : :
537 : : bCompareTaut = ( bCompareComponents & CMP_COMPONENTS_NONTAUT )
538 : : ? TAUT_NON
539 : : : TAUT_YES;
540 : :
541 : : bCompareAlt = ALT_TAUT( bCompareTaut );
542 : :
543 : : if (num_components[iINChI] > 1)
544 : : {
545 : : if (prep_inp_data[iINChI].bSavedInINCHI_LIB[iINChI] &&
546 : : prep_inp_data[iINChI].bPreprocessed[iINChI])
547 : : {
548 : : inp_data = prep_inp_data + iINChI;
549 : : }
550 : : else if (orig_inp_data->bSavedInINCHI_LIB[iINChI] &&
551 : : !orig_inp_data->bPreprocessed[iINChI])
552 : : {
553 : : inp_data = orig_inp_data;
554 : : }
555 : : else
556 : : {
557 : : inp_data = NULL;
558 : : }
559 : :
560 : : if (inp_data && !inp_data->nEquLabels &&
561 : : !prep_inp_data[iINChI].nSortedOrder)
562 : : {
563 : : int i1, i2, nSet;
564 : : AT_NUMB nAtNo;
565 : : AT_NUMB nNumAtoms = (AT_NUMB) inp_data->num_inp_atoms;
566 : :
567 : : if (( prep_inp_data[iINChI].nSortedOrder =
568 : : (AT_NUMB *) inchi_calloc( (long long)num_components[iINChI] + 1,
569 : : sizeof( prep_inp_data[0].nSortedOrder[0] ) ) )) /* djb-rwth: cast operator added */
570 : : {
571 : : inp_data->nNumEquSets = 0;
572 : :
573 : : for (i1 = 0, nSet = 0; i1 < num_components[iINChI]; i1 = i2)
574 : : {
575 : : nNumDeleted =
576 : : ( pINChISort[bCompareTaut][i1].pINChI[bCompareTaut] &&
577 : : pINChISort[bCompareTaut][i1].pINChI[bCompareTaut]->bDeleted );
578 : :
579 : : for (i2 = i1 + 1; i2 < num_components[iINChI]; i2++)
580 : : {
581 : : /* isotopic/non-isotopic comparison does not separate equivalent components */
582 : : if (CompINChI2( pINChISort[bCompareTaut] + i1,
583 : : pINChISort[bCompareTaut] + i2,
584 : : bCompareTaut, bCompareIsotopic ))
585 : : {
586 : : break;
587 : : }
588 : : else
589 : : {
590 : : nNumDeleted +=
591 : : ( pINChISort[bCompareTaut][i2].pINChI[bCompareTaut] &&
592 : : pINChISort[bCompareTaut][i2].pINChI[bCompareTaut]->bDeleted );
593 : : }
594 : : }
595 : :
596 : : if (i2 - i1 - nNumDeleted > 1)
597 : : {
598 : : if (inp_data->nEquLabels ||
599 : : ( inp_data->nEquLabels =
600 : : (AT_NUMB *) inchi_calloc( (long long)inp_data->num_inp_atoms + 1,
601 : : sizeof( inp_data->nEquLabels[0] ) ) )) /* djb-rwth: cast operator added */
602 : : {
603 : : nSet++;
604 : : /* found i2-i1 equivalent components && */
605 : : /* memory has been allocated */
606 : : for (i = i1; i < i2; i++)
607 : : {
608 : : INChI_Aux *pINChI_Aux;
609 : : int aux_test;
610 : :
611 : : if (pINChISort[bCompareTaut][i].pINChI[bCompareTaut] &&
612 : : pINChISort[bCompareTaut][i].pINChI[bCompareTaut]->bDeleted)
613 : : continue;
614 : :
615 : : aux_test =
616 : : ( pINChISort[bCompareTaut][i].pINChI_Aux[bCompareTaut] &&
617 : : pINChISort[bCompareTaut][i].pINChI_Aux[bCompareTaut]->nNumberOfAtoms );
618 : :
619 : : pINChI_Aux =
620 : : aux_test ? pINChISort[bCompareTaut][i].pINChI_Aux[bCompareTaut]
621 : : : ( pINChISort[bCompareTaut][i].pINChI_Aux[bCompareAlt] &&
622 : : pINChISort[bCompareTaut][i].pINChI_Aux[bCompareAlt]->nNumberOfAtoms )
623 : : ? pINChISort[bCompareTaut][i].pINChI_Aux[bCompareAlt]
624 : : : (INChI_Aux *) NULL;
625 : :
626 : : if (pINChI_Aux && pINChI_Aux->nOrigAtNosInCanonOrd)
627 : : {
628 : : for (k = 0; k < pINChI_Aux->nNumberOfAtoms; k++)
629 : : {
630 : : if (( nAtNo = pINChI_Aux->nOrigAtNosInCanonOrd[k] ) &&
631 : : nAtNo <= nNumAtoms)
632 : : {
633 : : inp_data->nEquLabels[nAtNo - 1] = nSet;
634 : : }
635 : : }
636 : : }
637 : : }
638 : : }
639 : : else
640 : : {
641 : : return CT_OUT_OF_RAM;
642 : : }
643 : : }
644 : : }
645 : :
646 : : nRet |= nSet ? 1 : 0;
647 : : }
648 : : else
649 : : {
650 : : return CT_OUT_OF_RAM;
651 : : }
652 : :
653 : : inp_data->nNumEquSets = nSet;
654 : : /* output order */
655 : : prep_inp_data[iINChI].nSortedOrder[0] = 0;
656 : : for (i1 = 0; i1 < num_components[iINChI]; i1++)
657 : : {
658 : : prep_inp_data[iINChI].nSortedOrder[i1 + 1] =
659 : : pINChISort[TAUT_YES][i1].ord_number + 1;
660 : : }
661 : :
662 : : #ifdef TARGET_LIB_FOR_WINCHI /* { */
663 : : if (DRAWDATA && GET_DRAWDATA &&
664 : : inp_data->nNumEquSets > 0 &&
665 : : inp_data->nEquLabels)
666 : : {
667 : : int nType = inp_data->bPreprocessed[iINChI]
668 : : ? COMPONENT_ORIGINAL_PREPROCESSED
669 : : : COMPONENT_ORIGINAL;
670 : :
671 : : struct DrawData *pDrawData = GET_DRAWDATA( 0, nType, iINChI );
672 : : if (pDrawData &&
673 : : pDrawData->pWindowData &&
674 : : !pDrawData->pWindowData->nEquLabels)
675 : : {
676 : : /* copy equivalence data from inp_data */
677 : : /* to pDrawData->pWindowData */
678 : : if (inp_data->nEquLabels &&
679 : : ( pDrawData->pWindowData->nEquLabels =
680 : : (AT_NUMB *) inchi_calloc( inp_data->num_inp_atoms,
681 : : sizeof( inp_data->nEquLabels[0] ) ) ))
682 : : {
683 : : memcpy( pDrawData->pWindowData->nEquLabels,
684 : : inp_data->nEquLabels,
685 : : inp_data->num_inp_atoms *
686 : : sizeof( inp_data->nEquLabels[0] ) );
687 : : pDrawData->pWindowData->nNumEquSets =
688 : : inp_data->nNumEquSets;
689 : : pDrawData->pWindowData->nCurEquLabel = 0;
690 : : }
691 : : }
692 : : }
693 : :
694 : : #endif /* } TARGET_LIB_FOR_WINCHI */
695 : : }
696 : : }
697 : :
698 : : return nRet;
699 : : }
700 : :
701 : :
702 : : /****************************************************************************/
703 : : int DisplayTheWholeCompositeStructure( struct tagCANON_GLOBALS *pCG,
704 : : struct tagINCHI_CLOCK *ic,
705 : : INPUT_PARMS *ip,
706 : : struct tagStructData *sd,
707 : : long num_inp,
708 : : int iINChI,
709 : : PINChI2 *pINChI2,
710 : : PINChI_Aux2 *pINChI_Aux2,
711 : : ORIG_ATOM_DATA *orig_inp_data,
712 : : ORIG_ATOM_DATA *prep_inp_data,
713 : : COMP_ATOM_DATA composite_norm_data[TAUT_NUM + 1] )
714 : : {
715 : : ORIG_ATOM_DATA *inp_data = NULL;
716 : : int jj, j, k, err = 0, nNumIntermediateTaut = 0, bDisplayTaut;
717 : : char szTitle[256];
718 : : int nNumTautComponents, m;
719 : : int bCompareIsotopic = !( ip->bCompareComponents & CMP_COMPONENTS_NONISO );
720 : : int bCompareTaut = ( ip->bCompareComponents & CMP_COMPONENTS_NONTAUT ) ? TAUT_NON : TAUT_YES;
721 : :
722 : : if (ip->bCompareComponents & CMP_COMPONENTS)
723 : : {
724 : : if (prep_inp_data[iINChI].bSavedInINCHI_LIB[iINChI] && prep_inp_data[iINChI].bPreprocessed[iINChI])
725 : : {
726 : : inp_data = prep_inp_data + iINChI;
727 : : }
728 : : else if (orig_inp_data->bSavedInINCHI_LIB[iINChI] && !orig_inp_data->bPreprocessed[iINChI])
729 : : {
730 : : inp_data = orig_inp_data;
731 : : }
732 : : }
733 : :
734 : : /**************************************************************************
735 : : * display from one up to 4 structure pictures-results for all components *
736 : : * Enable buttons: *
737 : : * BN (non-tautomeric non-isotopic): inp_norm_data[0]->bExists *
738 : : * TN (tautomeric non-isotopic): inp_norm_data[1]->bExists *
739 : : * BI (non-tautomeric isotopic): inp_norm_data[0]->bExists && *
740 : : * inp_norm_data[0]->bHasIsotopicLayer *
741 : : * TI (tautomeric isotopic): inp_norm_data[1]->bExists && *
742 : : * inp_norm_data[1]->bHasIsotopicLayer *
743 : : **************************************************************************/
744 : :
745 : : for ( jj = 0;
746 : : ip->bDisplayCompositeResults && !sd->bUserQuitComponentDisplay && jj <= TAUT_INI;
747 : : jj++)
748 : : {
749 : : j = ( jj == 0 )
750 : : ? TAUT_NON : ( jj == 1 ) ? TAUT_INI : ( jj == 2 ) ? TAUT_YES : -1;
751 : :
752 : : if (j < 0)
753 : : {
754 : : continue;
755 : : }
756 : :
757 : : if (composite_norm_data[j].bExists &&
758 : : composite_norm_data[j].num_components > 1)
759 : : {
760 : :
761 : : bDisplayTaut = ( !( ip->nMode & REQ_MODE_BASIC ) && !j ) ? -1 : j;
762 : : nNumTautComponents = 0;
763 : : if (bDisplayTaut)
764 : : {
765 : : /* find whether the structure is actually tautomeric */
766 : : for (m = 0; m < composite_norm_data[TAUT_YES].num_components; m++)
767 : : {
768 : : if (!pINChI2[m][TAUT_YES])
769 : : {
770 : : continue;
771 : : }
772 : : if (pINChI2[m][TAUT_YES]->bDeleted ||
773 : : pINChI2[m][TAUT_YES]->lenTautomer > 0)
774 : : {
775 : : nNumTautComponents++;
776 : : }
777 : : }
778 : : }
779 : :
780 : : for (k = 0;
781 : : k <= composite_norm_data[j].bHasIsotopicLayer && !sd->bUserQuitComponentDisplay;
782 : : k++)
783 : : {
784 : : /* added number of components, added another format */
785 : : /* for a single component case - DCh */
786 : : int bMobileH = ( bDisplayTaut > 0 && nNumTautComponents );
787 : : sprintf(szTitle, "%s Structure #%ld%s%s.%s%s%s%s%s",
788 : : j == TAUT_INI ? "Preprocessed" : "Result for", num_inp,
789 : : bMobileH ? ", mobile H" :
790 : : bDisplayTaut == 0 ? ", fixed H" : "",
791 : : /*j? ", mobile H":", fixed H",*/
792 : : k ? ", isotopic" : "",
793 : : SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue),
794 : : iINChI ? " (Reconnected)" : "");
795 : : #ifndef TARGET_LIB_FOR_WINCHI
796 : : /****** Display composite Result structure **************/
797 : : nNumIntermediateTaut += ( j == TAUT_INI );
798 : : /* display TAUT_INI (preprocessed) only once */
799 : : if (j != TAUT_INI || nNumIntermediateTaut == 1)
800 : : {
801 : : err =
802 : : DisplayCompositeStructure( pCG,
803 : : composite_norm_data,
804 : : orig_inp_data->polymer,
805 : : j == TAUT_INI ? 1 : k,
806 : : /* bIsotopic*/
807 : : j, /*tautomeric*/
808 : : j == TAUT_INI ? NULL
809 : : : pINChI2,
810 : : j == TAUT_INI ? NULL
811 : : : pINChI_Aux2,
812 : : ip->bAbcNumbers,
813 : : &ip->dp,
814 : : ip->nMode,
815 : : szTitle );
816 : : }
817 : : if ((sd->bUserQuitComponentDisplay = ( err == ESC_KEY ))) /* djb-rwth: addressing LLVM warning */
818 : : {
819 : : break;
820 : : }
821 : :
822 : : if (inp_data &&
823 : : inp_data->nEquLabels &&
824 : : inp_data->nNumEquSets &&
825 : : !sd->bUserQuitComponentDisplay &&
826 : : ( ( j == bCompareTaut || (bCompareTaut && j == TAUT_INI) ) ||
827 : : (bCompareTaut && !composite_norm_data[bCompareTaut].bExists) ) &&
828 : : ( k == bCompareIsotopic || (bCompareIsotopic && !composite_norm_data[j].bHasIsotopicLayer) ) /* djb-rwth: addressing LLVM warnings */
829 : : ) /* djb-rwth: addressing LLVM warning */
830 : : {
831 : : AT_NUMB nEquSet;
832 : : int bDisplaySaved = ip->bDisplay;
833 : :
834 : : /****** Display Equ Sets of composite Result structure **************/
835 : : for (nEquSet = 1;
836 : : nEquSet <= inp_data->nNumEquSets;
837 : : nEquSet++)
838 : : {
839 : : sprintf(szTitle, "Equ set %d of %d, %s Structure #%ld%s%s.%s%s%s%s%s",
840 : : nEquSet, inp_data->nNumEquSets,
841 : : j == TAUT_INI ? "Preprocessed" : "Result for",
842 : : num_inp,
843 : : (bDisplayTaut > 0 && nNumTautComponents) ? ", mobile H" : bDisplayTaut == 0 ? ", fixed H" : "",
844 : : /*j? ", mobile H":", fixed H",*/
845 : : k ? ", isotopic" : "",
846 : : SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue), iINChI ? " (Reconnected)" : "");
847 : : ip->dp.nEquLabels = inp_data->nEquLabels;
848 : : ip->dp.nCurEquLabel = nEquSet;
849 : : ip->dp.nNumEquSets = inp_data->nNumEquSets;
850 : : ip->bDisplay = 1; /* force display if it was not requested */
851 : : err = DisplayCompositeStructure( pCG,
852 : : composite_norm_data,
853 : : inp_data->polymer,
854 : : k, j,
855 : : pINChI2, pINChI_Aux2,
856 : : ip->bAbcNumbers,
857 : : &ip->dp,
858 : : ip->nMode,
859 : : szTitle );
860 : : ip->dp.nEquLabels = NULL;
861 : : ip->dp.nCurEquLabel = 0;
862 : : ip->dp.nNumEquSets = 0;
863 : : ip->bDisplay = bDisplaySaved; /* restore display option */
864 : :
865 : : if ((sd->bUserQuitComponentDisplay = ( err == ESC_KEY ))) /* djb-rwth: addressing LLVM warning */
866 : : {
867 : : break;
868 : : }
869 : : }
870 : : }
871 : : #else
872 : : if (DRAWDATA && j <= TAUT_YES)
873 : : {
874 : : struct DrawData vDrawData;
875 : : vDrawData.pWindowData =
876 : : CreateWinDataComposite_( pCG,
877 : : composite_norm_data,
878 : : k,
879 : : j,
880 : : pINChI2,
881 : : pINChI_Aux2,
882 : : ip->bAbcNumbers,
883 : : &ip->dp,
884 : : ip->nMode );
885 : :
886 : : /* vDrawData.pWindowData = CreateWinData_( composite_norm_data[j].at, composite_norm_data[j].num_at,
887 : : k, j, pINChI[i], pINChI_Aux[i],ip->bAbcNumbers, &ip->dp, ip->nMode ); */
888 : :
889 : : if (vDrawData.pWindowData != NULL)
890 : : {
891 : : int nType;
892 : : vDrawData.nComponent = 0;
893 : : if (j == 0)
894 : : nType = ( k == 0 ) ? COMPONENT_BN : COMPONENT_BI;
895 : : else
896 : : nType = ( k == 0 ) ? COMPONENT_TN : COMPONENT_TI;
897 : : vDrawData.nType = nType;
898 : : vDrawData.bReconnected = iINChI; /* 0=>main; 1=>reconnected */
899 : : vDrawData.szTitle = inchi__strdup( szTitle );
900 : : vDrawData.pWindowData->szTitle = inchi__strdup( szTitle );
901 : : if (inp_data && inp_data->nEquLabels &&
902 : : inp_data->nNumEquSets &&
903 : : ( j == bCompareTaut || bCompareTaut && !composite_norm_data[bCompareTaut].bExists ) &&
904 : : ( k == bCompareIsotopic || bCompareIsotopic && !composite_norm_data[j].bHasIsotopicLayer ) &&
905 : : ( vDrawData.pWindowData->nEquLabels = (AT_NUMB *) inchi_calloc( inp_data->num_inp_atoms,
906 : : sizeof( inp_data->nEquLabels[0] ) ) ))
907 : : {
908 : : memcpy( vDrawData.pWindowData->nEquLabels, inp_data->nEquLabels,
909 : : inp_data->num_inp_atoms * sizeof( inp_data->nEquLabels[0] ) );
910 : : vDrawData.pWindowData->nNumEquSets = inp_data->nNumEquSets;
911 : : vDrawData.pWindowData->nCurEquLabel = 0;
912 : : }
913 : : DRAWDATA( &vDrawData );
914 : : }
915 : : }
916 : : else if (DRAWDATA && GET_DRAWDATA && j == TAUT_INI)
917 : : {
918 : : struct DrawData vDrawData;
919 : : struct DrawData *pDrawData;
920 : :
921 : : if (!( ip->bCompareComponents & CMP_COMPONENTS ) ||
922 : : ( ip->bCompareComponents & CMP_COMPONENTS_NONTAUT ) ||
923 : : !k != !composite_norm_data[j].bHasIsotopicLayer)
924 : : {
925 : :
926 : : continue;
927 : : }
928 : : vDrawData.pWindowData =
929 : : CreateWinDataComposite_( pCG,
930 : : composite_norm_data,
931 : : 1 /*k*/,
932 : : j,
933 : : NULL,
934 : : NULL,
935 : : ip->bAbcNumbers,
936 : : &ip->dp,
937 : : ip->nMode );
938 : :
939 : :
940 : :
941 : : if (vDrawData.pWindowData != NULL)
942 : : {
943 : : int nType = COMPONENT_ORIGINAL_PREPROCESSED;
944 : : pDrawData = GET_DRAWDATA( 0, nType, iINChI );
945 : : if (pDrawData)
946 : : {
947 : : FreeDrawData( pDrawData );
948 : : pDrawData->pWindowData = vDrawData.pWindowData;
949 : : vDrawData.pWindowData = NULL;
950 : : }
951 : : else
952 : : {
953 : : pDrawData = &vDrawData;
954 : : }
955 : :
956 : : /* vDrawData.pWindowData = CreateWinData_( composite_norm_data[j].at, composite_norm_data[j].num_at,
957 : : k, j, pINChI[i], pINChI_Aux[i],ip->bAbcNumbers, &ip->dp, ip->nMode ); */
958 : :
959 : : pDrawData->nComponent = 0;
960 : : pDrawData->nType = nType;
961 : : pDrawData->bReconnected = iINChI; /* 0=>main; 1=>reconnected */
962 : : pDrawData->szTitle = inchi__strdup( szTitle );
963 : : pDrawData->pWindowData->szTitle = inchi__strdup( szTitle );
964 : : if (inp_data && inp_data->nEquLabels &&
965 : : inp_data->nNumEquSets &&
966 : : /*(j == bCompareTaut || bCompareTaut && !composite_norm_data[bCompareTaut].bExists) &&*/
967 : : /*(k == bCompareIsotopic || bCompareIsotopic && !composite_norm_data[j].bHasIsotopicLayer) &&*/
968 : : ( pDrawData->pWindowData->nEquLabels = (AT_NUMB *) inchi_calloc( inp_data->num_inp_atoms,
969 : : sizeof( inp_data->nEquLabels[0] ) ) ))
970 : : {
971 : : memcpy( pDrawData->pWindowData->nEquLabels,
972 : : inp_data->nEquLabels,
973 : : inp_data->num_inp_atoms * sizeof( inp_data->nEquLabels[0] ) );
974 : : pDrawData->pWindowData->nNumEquSets = inp_data->nNumEquSets;
975 : : pDrawData->pWindowData->nCurEquLabel = 0;
976 : : }
977 : : if (pDrawData == &vDrawData)
978 : : {
979 : : DRAWDATA( pDrawData ); /* there was no prepocessed structure */
980 : : }
981 : : }
982 : : }
983 : :
984 : : #endif /* #ifndef TARGET_LIB_FOR_WINCHI */
985 : : }
986 : : }
987 : : }
988 : :
989 : : return err;
990 : : }
991 : :
992 : :
993 : : /****************************************************************************/
994 : : int DisplayTheWholeStructure( struct tagCANON_GLOBALS *pCG,
995 : : struct tagINCHI_CLOCK *ic,
996 : : STRUCT_DATA *sd,
997 : : INPUT_PARMS *ip,
998 : : char *szTitle,
999 : : INCHI_IOSTREAM *inp_file,
1000 : : INCHI_IOSTREAM *log_file,
1001 : : ORIG_ATOM_DATA *orig_inp_data,
1002 : : long num_inp,
1003 : : int iINChI,
1004 : : int bShowStruct,
1005 : : int bINCHI_LIB_Flag )
1006 : : {
1007 : :
1008 : : int bDisplayEqu = 0;
1009 : :
1010 : : #ifndef TARGET_LIB_FOR_WINCHI
1011 : :
1012 : : /* Displaying equivalent input structures when disconnection has been done: */
1013 : : /* in case of TARGET_LIB_FOR_WINCHI equivalence info is always unknown here and bOriginalReconnected=0 */
1014 : :
1015 : : int bOriginalReconnected = iINChI < 0 &&
1016 : : orig_inp_data && orig_inp_data->nEquLabels &&
1017 : : ( sd->bTautFlagsDone[INCHI_BAS] & TG_FLAG_DISCONNECT_COORD_DONE ) &&
1018 : : ( ip->bTautFlags & TG_FLAG_RECONNECT_COORD );
1019 : :
1020 : : const char *lpszType =
1021 : : bOriginalReconnected ? " (Reconnected)"
1022 : : : ( iINChI < 0 ) ? ""
1023 : : : ( iINChI == INCHI_BAS ) ? " (Preprocessed)"
1024 : : : ( iINChI == INCHI_REC ) ? " (Reconnected)"
1025 : : : ""; /* djb-rwth: ignoring LLVM warning: variable used */
1026 : :
1027 : : int err = 0; /* djb-rwth: ignoring LLVM warning: variable used */
1028 : :
1029 : : /* Display the original structure */
1030 : :
1031 : : bDisplayEqu = bShowStruct && ip->bDisplay &&
1032 : : ip->dp.nEquLabels && 0 < ip->dp.nCurEquLabel && ip->dp.nCurEquLabel <= ip->dp.nNumEquSets;
1033 : : #else
1034 : : if (!DRAWDATA || !DRAWDATA_EXISTS)
1035 : : return 0;
1036 : : #endif
1037 : :
1038 : :
1039 : : #if !defined(TARGET_API_LIB) && !defined(COMPILE_ANSI_ONLY)
1040 : : /* Ask the user whether to process the input structure or quit*/
1041 : : if (ip->bDisplay && inp_file->f != stdin)
1042 : : {
1043 : : if (user_quit( ic, bDisplayEqu ? "Enter=Display identical components, Esc=Stop ?"
1044 : : : "Enter=Display, Esc=Stop ?",
1045 : : ip->ulDisplTime ))
1046 : : {
1047 : : sd->bUserQuit = 1;
1048 : : goto exit_function;
1049 : : }
1050 : : }
1051 : : #endif
1052 : :
1053 : : /*
1054 : : * Display the whole input structure in console app
1055 : : */
1056 : :
1057 : : /* #ifndef TARGET_LIB_FOR_WINCHI */
1058 : :
1059 : : #if ( !defined( TARGET_LIB_FOR_WINCHI ) && !defined(TARGET_EXE_STANDALONE) )
1060 : : if (bShowStruct && ip->bDisplay)
1061 : : {
1062 : : if (bDisplayEqu)
1063 : : {
1064 : : sprintf( szTitle, " Equ Set %d of %d, Input Structure #%ld.%s%s%s%s%s",
1065 : : ip->dp.nCurEquLabel, ip->dp.nNumEquSets,
1066 : : num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), lpszType );
1067 : : }
1068 : : else
1069 : : {
1070 : : sprintf( szTitle, "Input Structure #%ld.%s%s%s%s%s", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ), lpszType );
1071 : : }
1072 : : err = DisplayStructure( orig_inp_data->at, orig_inp_data->num_inp_atoms,
1073 : : orig_inp_data->polymer,
1074 : : 0, 1, 0, NULL, 1/*isotopic*/, 0/*taut*/, NULL, NULL,
1075 : : ip->bAbcNumbers, &ip->dp, ip->nMode, szTitle );
1076 : : sd->bUserQuitComponent = ( err == ESC_KEY );
1077 : : if (!err)
1078 : : {
1079 : : inchi_fprintf( stderr, "Cannot display the structure\n" );
1080 : : }
1081 : : }
1082 : : if (!bDisplayEqu)
1083 : : {
1084 : : /* console output progress report */
1085 : : if (ip->bDisplay && !sd->bUserQuitComponent)
1086 : : {
1087 : : if (iINChI == 1)
1088 : : {
1089 : : if (ip->bDisplay)
1090 : : inchi_ios_eprint( log_file, "Processing (rec) structure #%ld.%s%s%s%s...\n", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
1091 : : else
1092 : : inchi_fprintf( stderr, "Processing (rec) structure #%ld.%s%s%s%s...\r", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
1093 : : }
1094 : : else
1095 : : {
1096 : : if (ip->bDisplay)
1097 : : inchi_ios_eprint( log_file, "Processing structure #%ld.%s%s%s%s...\n", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
1098 : : else
1099 : : inchi_fprintf( stderr, "Processing structure #%ld.%s%s%s%s...\r", num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
1100 : : }
1101 : : }
1102 : : }
1103 : : #endif
1104 : :
1105 : :
1106 : : /*
1107 : : * Store the whole input structure in GUI application
1108 : : */
1109 : :
1110 : : #ifdef TARGET_LIB_FOR_WINCHI
1111 : : if (ip->bDisplay && bINCHI_LIB_Flag)
1112 : : #else
1113 : : if (( ip->bDisplay || ( ip->bCompareComponents & CMP_COMPONENTS ) ) && bINCHI_LIB_Flag)
1114 : : #endif
1115 : :
1116 : : {
1117 : : int bBit, k, bReconnected, nComponent, bPreprocessed;
1118 : :
1119 : : for (bBit = 1, k = 0; k < 8; k++, bBit <<= 1)
1120 : : {
1121 : : /******************************************************************************
1122 : : * bReconnected = k%2 (0 or 1)
1123 : : * nComponent = k/4 (0 or 1)
1124 : : * bPreprocessed = (k/2)%2 (0 or 1)
1125 : : ******************************************************************************/
1126 : : if (!( bINCHI_LIB_Flag & bBit ))
1127 : : {
1128 : : continue;
1129 : : }
1130 : :
1131 : : bReconnected = k % 2;
1132 : : nComponent = k / 4;
1133 : : bPreprocessed = ( ( k / 2 ) % 2 );
1134 : :
1135 : : sprintf(szTitle, "%s Structure #%ld.%s%s%s%s",
1136 : : bPreprocessed ? "Preprocessed" : bReconnected ? "Reconnected" : "Input",
1137 : : num_inp,
1138 : : SDF_LBL_VAL(ip->pSdfLabel, ip->pSdfValue));
1139 : :
1140 : : #ifdef TARGET_LIB_FOR_WINCHI
1141 : : if (DRAWDATA && DRAWDATA_EXISTS)
1142 : : {
1143 : : struct DrawData vDrawData;
1144 : : int nType = bPreprocessed ? COMPONENT_ORIGINAL_PREPROCESSED : COMPONENT_ORIGINAL;
1145 : : if (DRAWDATA_EXISTS( nComponent, bPreprocessed, bReconnected ))
1146 : : {
1147 : : /*
1148 : : TEMPORARILY DISABLED TO MAKE WINCHI TREAT SOME POLYMERS
1149 : : sd->nErrorType = _IS_FATAL;
1150 : : sd->nErrorCode = CT_UNKNOWN_ERR;
1151 : : return -1;
1152 : : */
1153 : : }
1154 : : vDrawData.pWindowData = CreateWinData_( pCG,
1155 : : orig_inp_data->at,
1156 : : orig_inp_data->num_inp_atoms,
1157 : : 0,
1158 : : 1 /* bAdd_DT_to_num_H */,
1159 : : 0,
1160 : : NULL,
1161 : : 1,
1162 : : 0,
1163 : : NULL,
1164 : : NULL,
1165 : : ip->bAbcNumbers,
1166 : : &ip->dp,
1167 : : ip->nMode );
1168 : : if (vDrawData.pWindowData != NULL)
1169 : : {
1170 : : vDrawData.nComponent = nComponent;
1171 : : vDrawData.nType = nType; /* COMPONENT_ORIGINAL or COMPONENT_ORIGINAL_PREPROCESSED */
1172 : : vDrawData.bReconnected = bReconnected; /* 0=>main; 1=>reconnected */
1173 : : vDrawData.pWindowData->szTitle = inchi__strdup( szTitle );
1174 : : vDrawData.szTitle = inchi__strdup( szTitle );
1175 : : DRAWDATA( &vDrawData );
1176 : : if (!nComponent)
1177 : : {
1178 : : /* keep track of saved INCHI_LIB data */
1179 : : orig_inp_data->bSavedInINCHI_LIB[bReconnected] ++;
1180 : : orig_inp_data->bPreprocessed[bReconnected] = bPreprocessed;
1181 : : }
1182 : : }
1183 : : }
1184 : : #else
1185 : : if (!nComponent && orig_inp_data) /* djb-rwth: fixing a NULL pointer dereference */
1186 : : {
1187 : : /* keep track of saved INCHI_LIB data */
1188 : : orig_inp_data->bSavedInINCHI_LIB[bReconnected] ++;
1189 : : orig_inp_data->bPreprocessed[bReconnected] = bPreprocessed;
1190 : : }
1191 : : #endif
1192 : : }
1193 : : }
1194 : :
1195 : : exit_function:
1196 : :
1197 : : return sd->bUserQuit;
1198 : : }
1199 : :
1200 : : #else
1201 : : /* dummies */
1202 : :
1203 : : /****************************************************************************/
1204 : 0 : int DisplayTheWholeStructure( struct tagCANON_GLOBALS *pCG,
1205 : : struct tagINCHI_CLOCK *ic,
1206 : : STRUCT_DATA *sd,
1207 : : INPUT_PARMS *ip,
1208 : : char *szTitle,
1209 : : INCHI_IOSTREAM *inp_file,
1210 : : INCHI_IOSTREAM *log_file,
1211 : : ORIG_ATOM_DATA *orig_inp_data,
1212 : : long num_inp,
1213 : : int iINChI,
1214 : : int bShowStruct,
1215 : : int bINCHI_LIB_Flag )
1216 : : {
1217 : 0 : return 0;
1218 : : }
1219 : :
1220 : :
1221 : : /****************************************************************************/
1222 : 0 : int DisplayStructure( struct tagCANON_GLOBALS *pCG,
1223 : : inp_ATOM *at,
1224 : : int num_at,
1225 : : OAD_Polymer *polymer,
1226 : : int num_removed_H,
1227 : : int bAdd_DT_to_num_H,
1228 : : int nNumRemovedProtons,
1229 : : NUM_H *nNumRemovedProtonsIsotopic,
1230 : : int bIsotopic,
1231 : : int j /*bTautomeric*/,
1232 : : INChI **cur_INChI,
1233 : : INChI_Aux **cur_INChI_Aux,
1234 : : int bAbcNumbers,
1235 : : DRAW_PARMS *dp,
1236 : : INCHI_MODE nMode,
1237 : : char *szTitle )
1238 : : {
1239 : 0 : return 0;
1240 : : }
1241 : :
1242 : :
1243 : :
1244 : :
1245 : : #endif /* }COMPILE_ANSI_ONLY */
1246 : :
1247 : :
1248 : : #ifndef TARGET_API_LIB
1249 : :
1250 : :
1251 : : /****************************************************************************/
1252 : : void SplitTime( unsigned long ulTotalTime,
1253 : : int *hours, int *minutes,
1254 : : int *seconds, int *mseconds )
1255 : : {
1256 : :
1257 : : *mseconds = (int) ( ulTotalTime % 1000 );
1258 : : ulTotalTime /= 1000;
1259 : : *seconds = (int) ( ulTotalTime % 60 );
1260 : : ulTotalTime /= 60;
1261 : : *minutes = (int) ( ulTotalTime % 60 );
1262 : : ulTotalTime /= 60;
1263 : : *hours = (int) ( ulTotalTime );
1264 : : }
1265 : : #endif
1266 : :
1267 : :
1268 : : /****************************************************************************
1269 : : Check if structure is chiral
1270 : : ****************************************************************************/
1271 : 7 : int bIsStructChiral( PINChI2 *pINChI2[INCHI_NUM], int num_components[] )
1272 : : {
1273 : : int i, j, k;
1274 : : INChI *pINChI;
1275 : : INChI_Stereo *Stereo;
1276 : :
1277 [ + - ]: 7 : for (j = 0; j < INCHI_NUM; j++)
1278 : : {
1279 : : /* disconnected / reconnected */
1280 [ - + ]: 7 : if (!num_components[j])
1281 : : {
1282 : 0 : continue;
1283 : : }
1284 : :
1285 [ + - ]: 7 : for (i = 0; i < num_components[j]; i++)
1286 : : {
1287 : : /* i-th component */
1288 [ + - ]: 14 : for (k = 0; k < TAUT_NUM; k++)
1289 : : {
1290 : : /* mobile/immobile H */
1291 [ + + ]: 14 : if (( pINChI = pINChI2[j][i][k] ) &&
1292 [ + - ]: 7 : !pINChI->bDeleted &&
1293 [ + - ]: 7 : pINChI->nNumberOfAtoms > 0)
1294 : : {
1295 : :
1296 [ + - ]: 7 : if (( Stereo = pINChI->Stereo ) &&
1297 [ + - ]: 7 : Stereo->t_parity &&
1298 [ + - ]: 7 : Stereo->nNumberOfStereoCenters > 0 &&
1299 [ + - ]: 7 : Stereo->nCompInv2Abs)
1300 : : {
1301 : 7 : return 1; /* inversion changed stereo */
1302 : : }
1303 [ # # ]: 0 : if (( Stereo = pINChI->StereoIsotopic ) &&
1304 [ # # ]: 0 : Stereo->t_parity &&
1305 [ # # ]: 0 : Stereo->nNumberOfStereoCenters > 0 &&
1306 [ # # ]: 0 : Stereo->nCompInv2Abs)
1307 : : {
1308 : 0 : return 1; /* inversion changed stereo */
1309 : : }
1310 : : }
1311 : : }
1312 : : }
1313 : : }
1314 : :
1315 : 0 : return 0;
1316 : : }
1317 : :
1318 : :
1319 : : /****************************************************************************
1320 : : Release InChI work memory
1321 : : ****************************************************************************/
1322 : 54 : void FreeAllINChIArrays( PINChI2 *pINChI[INCHI_NUM],
1323 : : PINChI_Aux2 *pINChI_Aux[INCHI_NUM],
1324 : : int num_components[INCHI_NUM] )
1325 : : {
1326 : : int k;
1327 [ + + ]: 162 : for (k = 0; k < INCHI_NUM; k++)
1328 : : {
1329 : 108 : int nk = num_components[k];
1330 : :
1331 : 108 : FreeINChIArrays( pINChI[k], pINChI_Aux[k], num_components[k] );
1332 : :
1333 : 108 : num_components[k] = 0;
1334 : :
1335 [ + + ]: 108 : if (nk && /* added check for nk: 2013-12-15 IPl */
1336 [ + - ]: 54 : pINChI[k])
1337 : : {
1338 [ + - ]: 54 : inchi_free( pINChI[k] );
1339 : 54 : pINChI[k] = NULL;
1340 : : }
1341 : :
1342 [ + + ]: 108 : if (nk && /* added check for nk: 2013-12-15 IPl */
1343 [ + - ]: 54 : pINChI_Aux[k])
1344 : : {
1345 [ + - ]: 54 : inchi_free( pINChI_Aux[k] );
1346 : 54 : pINChI_Aux[k] = NULL;
1347 : : }
1348 : : }
1349 : :
1350 : 54 : return;
1351 : : }
1352 : :
1353 : :
1354 : : /****************************************************************************
1355 : : Release InChI work memory
1356 : : ****************************************************************************/
1357 : 108 : void FreeINChIArrays( PINChI2 *pINChI, PINChI_Aux2 *pINChI_Aux, int num_components )
1358 : : {
1359 : : int i, k;
1360 : : /* Release allocated memory */
1361 [ + + ]: 108 : if (pINChI)
1362 : : {
1363 [ + + ]: 123 : for (i = 0; i < num_components; i++)
1364 : : {
1365 [ + + ]: 207 : for (k = 0; k < TAUT_NUM; k++)
1366 : : {
1367 : 138 : Free_INChI( &pINChI[i][k] );
1368 : : }
1369 : : }
1370 : : }
1371 [ + + ]: 108 : if (pINChI_Aux)
1372 : : {
1373 [ + + ]: 123 : for (i = 0; i < num_components; i++)
1374 : : {
1375 [ + + ]: 207 : for (k = 0; k < TAUT_NUM; k++)
1376 : : {
1377 : 138 : Free_INChI_Aux( &pINChI_Aux[i][k] );
1378 : : }
1379 : : }
1380 : : }
1381 : 108 : }
1382 : :
1383 : :
1384 : : /****************************************************************************
1385 : : Treat errors returned by CreateOneComponentINChI( ... )
1386 : : ****************************************************************************/
1387 : 0 : int TreatErrorsInCreateOneComponentINChI( STRUCT_DATA *sd,
1388 : : INPUT_PARMS *ip,
1389 : : ORIG_ATOM_DATA *orig_inp_data,
1390 : : int i, long num_inp,
1391 : : INCHI_IOSTREAM *inp_file,
1392 : : INCHI_IOSTREAM *log_file,
1393 : : INCHI_IOSTREAM *out_file,
1394 : : INCHI_IOSTREAM *prb_file )
1395 : : {
1396 [ # # ]: 0 : if (sd->nErrorCode)
1397 : : {
1398 : 0 : AddErrorMessage( sd->pStrErrStruct, ErrMsg( sd->nErrorCode ) );
1399 : 0 : inchi_ios_eprint( log_file,
1400 : : "Error %d (%s) structure #%ld component %d.%s%s%s%s\n",
1401 : 0 : sd->nErrorCode, sd->pStrErrStruct,
1402 [ # # # # : 0 : num_inp, i + 1, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
# # # # #
# # # # #
# # # # #
# # # #
# ]
1403 [ # # ]: 0 : sd->nErrorType = ( sd->nErrorCode == CT_OUT_OF_RAM || sd->nErrorCode == CT_USER_QUIT_ERR )
1404 : : ? _IS_FATAL
1405 [ # # ]: 0 : : _IS_ERROR;
1406 : :
1407 : : #ifdef TARGET_LIB_FOR_WINCHI
1408 : : if (( ip->bINChIOutputOptions & INCHI_OUT_WINCHI_WINDOW ) &&
1409 : : ( ip->bINChIOutputOptions & INCHI_OUT_PLAIN_TEXT ))
1410 : : {
1411 : : sd->nErrorType = ProcessStructError( out_file, log_file,
1412 : : sd->pStrErrStruct, sd->nErrorType,
1413 : : num_inp, ip );
1414 : : /* Save the problem structure */
1415 : : if (prb_file->f &&
1416 : : 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd &&
1417 : : !ip->bSaveAllGoodStructsAsProblem)
1418 : : {
1419 : : MolfileSaveCopy( inp_file, sd->fPtrStart, sd->fPtrEnd, prb_file->f, num_inp );
1420 : : }
1421 : : }
1422 : : else
1423 : : {
1424 : : /* Save the problem structure */
1425 : : if (sd->nErrorCode &&
1426 : : prb_file->f &&
1427 : : 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd &&
1428 : : !ip->bSaveAllGoodStructsAsProblem)
1429 : : {
1430 : : MolfileSaveCopy( inp_file, sd->fPtrStart, sd->fPtrEnd, prb_file->f, num_inp );
1431 : : }
1432 : : }
1433 : : #endif
1434 : : }
1435 : :
1436 : : /* #ifndef TARGET_API_LIB */
1437 : : #if ( !defined( TARGET_API_LIB ) && !defined(TARGET_EXE_STANDALONE) )
1438 : : /* print the logfile record */
1439 : : if (log_file->f && log_file->f != stderr && ( sd->ulStructTime >= 1000 || sd->nErrorCode ))
1440 : : {
1441 : : fprintf( log_file->f, "%10lu msec structure #%ld.%s%s%s%s (%d component%s, %d atom%s, error=%d).\n",
1442 : : sd->ulStructTime, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ),
1443 : : orig_inp_data->num_components, orig_inp_data->num_components == 1 ? "" : "s",
1444 : : orig_inp_data->num_inp_atoms, orig_inp_data->num_inp_atoms == 1 ? "" : "s", sd->nErrorCode );
1445 : : }
1446 : : #endif
1447 : :
1448 : 0 : return sd->nErrorType;
1449 : : }
1450 : :
1451 : :
1452 : : /****************************************************************************/
1453 : 54 : int TreatCreateINChIWarning( STRUCT_DATA *sd,
1454 : : INPUT_PARMS *ip,
1455 : : ORIG_ATOM_DATA *orig_inp_data,
1456 : : long num_inp,
1457 : : INCHI_IOSTREAM *inp_file,
1458 : : INCHI_IOSTREAM *log_file,
1459 : : INCHI_IOSTREAM *out_file,
1460 : : INCHI_IOSTREAM *prb_file )
1461 : : {
1462 : :
1463 : : #if ( bRELEASE_VERSION == 0 && (EXTR_FLAGS || EXTR_MASK) )
1464 : : if (EXTR_MASK ? ( ( sd->bExtract & EXTR_MASK ) == EXTR_FLAGS )
1465 : : : ( sd->bExtract & EXTR_FLAGS )
1466 : : )
1467 : : {
1468 : : char szMsg[64];
1469 : : sprintf( szMsg, "ExtractStruct.code=0x%X", sd->bExtract );
1470 : : if (!ip->bNoWarnings)
1471 : : {
1472 : : WarningMessage( sd->pStrErrStruct, szMsg );
1473 : : }
1474 : : }
1475 : : #endif
1476 : :
1477 [ + - + + ]: 54 : if (!sd->nErrorCode && sd->pStrErrStruct[0])
1478 : : {
1479 : 28 : inchi_ios_eprint( log_file, "Warning (%s) structure #%ld.%s%s%s%s\n",
1480 [ - + - - : 35 : sd->pStrErrStruct, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ) );
- + - - -
+ - - - -
- - - + -
- - + -
- ]
1481 : 7 : sd->nErrorType = _IS_WARNING;
1482 : :
1483 : : #ifdef TARGET_LIB_FOR_WINCHI
1484 : : if (( ip->bINChIOutputOptions & INCHI_OUT_WINCHI_WINDOW ) &&
1485 : : ( ip->bINChIOutputOptions & INCHI_OUT_PLAIN_TEXT ))
1486 : : {
1487 : : sd->nErrorType = ProcessStructError( out_file,
1488 : : log_file,
1489 : : sd->pStrErrStruct,
1490 : : sd->nErrorType,
1491 : : num_inp,
1492 : : ip );
1493 : : }
1494 : : #endif
1495 : : /* save the structure as a problem structure if requested */
1496 [ - + - - ]: 7 : if (ip->bSaveWarningStructsAsProblem && !ip->bSaveAllGoodStructsAsProblem &&
1497 [ # # # # : 0 : prb_file->f && 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd)
# # ]
1498 : : { /* djb-rwth: addressing coverity ID #499545 -- return values handled properly */
1499 : 0 : MolfileSaveCopy( inp_file,
1500 : : sd->fPtrStart,
1501 : : sd->fPtrEnd,
1502 : : prb_file->f,
1503 : : num_inp );
1504 : : }
1505 : :
1506 : : #if ( bRELEASE_VERSION == 0 )
1507 : : /* otherwise extract the structure as a problem structure if requested */
1508 : : else
1509 : : if (( EXTR_MASK ? ( ( sd->bExtract & EXTR_MASK ) == EXTR_FLAGS ) : ( sd->bExtract & EXTR_FLAGS ) )
1510 : : && !ip->bSaveAllGoodStructsAsProblem &&
1511 : : prb_file->f &&
1512 : : 0L <= sd->fPtrStart && sd->fPtrStart < sd->fPtrEnd)
1513 : : {
1514 : : MolfileSaveCopy( inp_file->f,
1515 : : sd->fPtrStart,
1516 : : sd->fPtrEnd,
1517 : : prb_file->f,
1518 : : num_inp );
1519 : : }
1520 : : #endif
1521 : : }
1522 : :
1523 : : #if ( bRELEASE_VERSION != 1 && bOUTPUT_ONE_STRUCT_TIME == 1 )
1524 : : #ifndef TARGET_API_LIB
1525 : : if (log_file && log_file != stderr)
1526 : : {
1527 : : fprintf( log_file, "%10lu msec structure %1dD #%ld.%s%s%s%s (%d component%s, %d atom%s, error=%d).\n",
1528 : : sd->ulStructTime, orig_inp_data->num_dimensions, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ),
1529 : : orig_inp_data->num_components, orig_inp_data->num_components == 1 ? "" : "s",
1530 : : orig_inp_data->num_inp_atoms, orig_inp_data->num_inp_atoms == 1 ? "" : "s", sd->nErrorCode );
1531 : : }
1532 : : #else
1533 : : if (log_file)
1534 : : {
1535 : : inchi_ios_eprint( log_file, "%10lu msec structure %1dD #%ld.%s%s%s%s (%d component%s, %d atom%s, error=%d).\n",
1536 : : sd->ulStructTime, orig_inp_data->num_dimensions, num_inp, SDF_LBL_VAL( ip->pSdfLabel, ip->pSdfValue ),
1537 : : orig_inp_data->num_components, orig_inp_data->num_components == 1 ? "" : "s",
1538 : : orig_inp_data->num_inp_atoms, orig_inp_data->num_inp_atoms == 1 ? "" : "s", sd->nErrorCode );
1539 : : }
1540 : : #endif
1541 : : #endif
1542 : :
1543 : 54 : return sd->nErrorType;
1544 : : }
1545 : :
1546 : :
1547 : : /****************************************************************************
1548 : : Treat errors/warnings
1549 : : ****************************************************************************/
1550 : 69 : int GetProcessingWarningsOneComponentInChI( INChI *cur_INChI[],
1551 : : INP_ATOM_DATA **inp_norm_data,
1552 : : STRUCT_DATA *sd,
1553 : : int bNoWarnings )
1554 : : {
1555 : 69 : int i, ret = 0;
1556 [ + + ]: 207 : for (i = 0; i < TAUT_NUM; i++)
1557 : : {
1558 [ + + + - ]: 138 : if (cur_INChI[i] && cur_INChI[i]->nNumberOfAtoms > 0)
1559 : : {
1560 : 69 : ret |= GetProcessingWarningsOneInChI( cur_INChI[i],
1561 : 69 : inp_norm_data[i],
1562 : 69 : sd->pStrErrStruct,
1563 : : bNoWarnings );
1564 : : }
1565 : : }
1566 : :
1567 : 69 : return ret;
1568 : : }
1569 : :
1570 : :
1571 : : /****************************************************************************
1572 : : Treat errors/warnings
1573 : : ****************************************************************************/
1574 : 69 : int GetProcessingWarningsOneInChI( INChI *pINChI,
1575 : : INP_ATOM_DATA *inp_norm_data,
1576 : : char *pStrErrStruct,
1577 : : int bNoWarnings )
1578 : : {
1579 : : int j;
1580 : : int nAmbiguousStereoAtoms, nAmbiguousStereoBonds;
1581 : 69 : nAmbiguousStereoAtoms = 0;
1582 : 69 : nAmbiguousStereoBonds = 0;
1583 : :
1584 [ + - ]: 69 : if (inp_norm_data->at)
1585 : : {
1586 [ + + ]: 688 : for (j = 0; j < pINChI->nNumberOfAtoms; j++)
1587 : : {
1588 [ - + ]: 619 : if (inp_norm_data->at[j].bAmbiguousStereo & ( AMBIGUOUS_STEREO_ATOM | AMBIGUOUS_STEREO_ATOM_ISO ))
1589 : : {
1590 : 0 : nAmbiguousStereoAtoms++;
1591 : : }
1592 [ - + ]: 619 : if (inp_norm_data->at[j].bAmbiguousStereo & ( AMBIGUOUS_STEREO_BOND | AMBIGUOUS_STEREO_BOND_ISO ))
1593 : : {
1594 : 0 : nAmbiguousStereoBonds++;
1595 : : }
1596 : : }
1597 [ - + ]: 69 : if (nAmbiguousStereoAtoms)
1598 : : {
1599 [ # # ]: 0 : if (!bNoWarnings)
1600 : : {
1601 : 0 : WarningMessage( pStrErrStruct, "Ambiguous stereo:" );
1602 : 0 : WarningMessage( pStrErrStruct, "center(s)" );
1603 : : }
1604 : : }
1605 [ - + ]: 69 : if (nAmbiguousStereoBonds)
1606 : : {
1607 [ # # ]: 0 : if (!bNoWarnings)
1608 : : {
1609 : 0 : WarningMessage( pStrErrStruct, "Ambiguous stereo:" );
1610 : 0 : WarningMessage( pStrErrStruct, "bond(s)" );
1611 : : }
1612 : : }
1613 : : }
1614 : :
1615 [ + - - + ]: 69 : return ( nAmbiguousStereoAtoms || nAmbiguousStereoBonds );
1616 : : }
|