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 : : #include <stdlib.h>
42 : : #include <string.h>
43 : : #include <math.h>
44 : :
45 : : /* */
46 : :
47 : : /* #define CHECK_WIN32_VC_HEAP */
48 : :
49 : : #include "mode.h"
50 : :
51 : : #if ( READ_INCHI_STRING == 1 )
52 : :
53 : : #include "ichitime.h"
54 : :
55 : : /* reverse InChI */
56 : :
57 : : #include "ichitime.h"
58 : : #include "ichicant.h"
59 : : #include "ichirvrs.h"
60 : : #include "inchicmp.h"
61 : :
62 : : #include "inchi_gui.h"
63 : :
64 : : #include "bcf_s.h"
65 : :
66 : : #if 0
67 : : #ifndef COMPILE_ANSI_ONLY
68 : : #ifndef TARGET_LIB_FOR_WINCHI
69 : : #include "inchi_gui.h"
70 : : #endif
71 : : #endif
72 : : #endif
73 : :
74 : :
75 : : #ifdef TARGET_LIB_FOR_WINCHI
76 : : /* dummies */
77 : : /****************************************************************************/
78 : : int DisplayStructure(struct tagCANON_GLOBALS* pCG,
79 : : inp_ATOM* at,
80 : : int num_at,
81 : : OAD_Polymer* polymer,
82 : : int num_removed_H,
83 : : int bAdd_DT_to_num_H,
84 : : int nNumRemovedProtons,
85 : : NUM_H* nNumRemovedProtonsIsotopic,
86 : : int bIsotopic,
87 : : int j /*bTautomeric*/,
88 : : INChI** cur_INChI,
89 : : INChI_Aux** cur_INChI_Aux,
90 : : int bAbcNumbers,
91 : : DRAW_PARMS* dp,
92 : : INCHI_MODE nMode,
93 : : char* szTitle)
94 : : {
95 : : return 0;
96 : : }
97 : : #endif /* TARGET_LIB_FOR_WINCHI */
98 : :
99 : :
100 : : /****************************************************************************/
101 : 0 : int InChI2Atom(INCHI_CLOCK* ic,
102 : : CANON_GLOBALS* pCG,
103 : : ICHICONST INPUT_PARMS* ip,
104 : : STRUCT_DATA* sd,
105 : : const char* szCurHdr,
106 : : long num_inp,
107 : : StrFromINChI* pStruct,
108 : : int iComponent,
109 : : int iAtNoOffset,
110 : : int bI2A_Flag,
111 : : int bHasSomeFixedH,
112 : : InpInChI* OneInput)
113 : : {
114 : 0 : int ret = 0;
115 : :
116 : 0 : int iINChI = (bI2A_Flag & I2A_FLAG_RECMET) ? INCHI_REC : INCHI_BAS;
117 : 0 : int bMobileH = (bI2A_Flag & I2A_FLAG_FIXEDH) ? TAUT_NON : TAUT_YES;
118 : :
119 : : INChI* pInChI[TAUT_NUM];
120 : :
121 : :
122 : :
123 : 0 : memset(pInChI, 0, sizeof(pInChI)); /* djb-rwth: memset_s C11/Annex K variant? */
124 : :
125 : :
126 : : /* disconnected or reconnected */
127 : :
128 [ # # ]: 0 : if (iINChI == INCHI_REC)
129 : : {
130 [ # # ]: 0 : if (!OneInput->nNumComponents[iINChI][TAUT_YES])
131 : : {
132 : 0 : iINChI = INCHI_BAS;
133 : : }
134 : : }
135 [ # # ]: 0 : if (iComponent >= OneInput->nNumComponents[iINChI][TAUT_YES])
136 : : {
137 : 0 : return 0; /* component does not exist */
138 : : }
139 : :
140 : : /* mobile or fixed H */
141 : 0 : pStruct->bFixedHExists = 0;
142 [ # # ]: 0 : if (bMobileH == TAUT_NON)
143 : : {
144 [ # # ]: 0 : if (!OneInput->nNumComponents[iINChI][bMobileH])
145 : : {
146 : : /* only one InChI exists (no mobile H) */
147 : 0 : bMobileH = TAUT_YES;
148 : : }
149 : : }
150 [ # # ]: 0 : if (iComponent >= OneInput->nNumComponents[iINChI][bMobileH])
151 : : {
152 : 0 : return 0; /* component does not exist */
153 : : }
154 : :
155 : : /* pointer to the InChI that is going to be reversed */
156 : 0 : pInChI[0] = &OneInput->pInpInChI[iINChI][bMobileH][iComponent];
157 : 0 : pStruct->bMobileH = bMobileH;
158 : 0 : pStruct->iINCHI = iINChI;
159 : :
160 : : /* deleted component only in case Mobile-H and compound contains only protons */
161 [ # # ]: 0 : if (pInChI[0]->bDeleted)
162 : : {
163 : 0 : return 0; /* deleted component, presumably H(+) */
164 : : }
165 : :
166 [ # # # # ]: 0 : if (bMobileH == TAUT_NON && OneInput->nNumProtons[iINChI][TAUT_YES].pNumProtons)
167 : : {
168 : 0 : pStruct->nNumRemovedProtonsMobHInChI =
169 : 0 : OneInput->nNumProtons[iINChI][TAUT_YES].pNumProtons[iComponent].nNumRemovedProtons;
170 : : }
171 : :
172 [ # # # # ]: 0 : if (bMobileH == TAUT_NON ||
173 : 0 : (bMobileH == TAUT_YES &&
174 [ # # ]: 0 : OneInput->pInpInChI[iINChI][TAUT_NON] &&
175 [ # # ]: 0 : OneInput->pInpInChI[iINChI][TAUT_NON][iComponent].nNumberOfAtoms > 0 &&
176 [ # # ]: 0 : !OneInput->pInpInChI[iINChI][TAUT_NON][iComponent].bDeleted) /* djb-rwth: addressing LLVM warning */
177 : : )
178 : : {
179 : 0 : pStruct->bFixedHExists = 1;
180 : : }
181 : :
182 [ # # ]: 0 : if (bMobileH == TAUT_NON &&
183 [ # # ]: 0 : iComponent < OneInput->nNumComponents[iINChI][TAUT_YES] &&
184 [ # # ]: 0 : OneInput->pInpInChI[iINChI][TAUT_YES] &&
185 [ # # ]: 0 : OneInput->pInpInChI[iINChI][TAUT_YES][iComponent].nNumberOfAtoms > 0 &&
186 [ # # ]: 0 : !OneInput->pInpInChI[iINChI][TAUT_YES][iComponent].bDeleted
187 : : )
188 : : {
189 : : /* pointer to the Mobile-H InChI if we are reversing Fixed-H InChI */
190 : 0 : pInChI[1] = &OneInput->pInpInChI[iINChI][TAUT_YES][iComponent];
191 : : }
192 : :
193 : 0 : pStruct->num_inp_actual = OneInput->num_inp;
194 : :
195 : : /* Intercept and correct non-polymer Zz to Zy if applicable */
196 [ # # ]: 0 : if (OneInput->polymer)
197 : : {
198 : : int a, k, new_num;
199 : 0 : OAD_Polymer* p = OneInput->polymer;
200 : 0 : pStruct->n_pzz = 0;
201 : 0 : pStruct->n_zy = 0;
202 [ # # ]: 0 : for (a = 0; a < pInChI[0]->nNumberOfAtoms; a++)
203 : : {
204 : 0 : int aglob = iAtNoOffset + a + 1;
205 [ # # ]: 0 : if (pInChI[0]->nAtom[a] == EL_NUMBER_ZZ)
206 : : {
207 : 0 : new_num = EL_NUMBER_ZY; /* Zy */
208 [ # # ]: 0 : for (k = 0; k < p->n; k++)
209 : : {
210 [ # # # # ]: 0 : if ((aglob == p->units[k]->cap1) || (aglob == p->units[k]->cap2))
211 : : {
212 : 0 : new_num = EL_NUMBER_ZZ;
213 : 0 : break;
214 : : }
215 : : }
216 : 0 : pInChI[0]->nAtom[a] = new_num;
217 [ # # ]: 0 : if (new_num == EL_NUMBER_ZY)
218 : : {
219 : 0 : pStruct->n_zy++;
220 : : }
221 [ # # ]: 0 : else if (new_num == EL_NUMBER_ZZ)
222 : : {
223 : 0 : pStruct->n_pzz++;
224 : : }
225 : : }
226 : : }
227 : : }
228 : :
229 : 0 : ret = OneInChI2Atom(ic, pCG, ip, sd, szCurHdr, num_inp, pStruct,
230 : : iComponent, 0 /* iAtNoOffset*/, bHasSomeFixedH, pInChI);
231 : :
232 : : /* djb-rwth: fixing oss-fuzz issue #66758, #30283 */
233 [ # # # # ]: 0 : if (pStruct->at && pStruct->at2)
234 : : {
235 : : int a;
236 [ # # ]: 0 : for (a = 0; a < pInChI[0]->nNumberOfAtoms; a++)
237 : : {
238 [ # # ]: 0 : if (pInChI[0]->nAtom[a] == EL_NUMBER_ZY)
239 : : {
240 : 0 : pInChI[0]->nAtom[a] = EL_NUMBER_ZZ;
241 : 0 : pStruct->at[a].el_number = EL_NUMBER_ZZ;
242 : 0 : strcpy(pStruct->at[a].elname, "Zz");
243 : 0 : pStruct->at2[a].el_number = EL_NUMBER_ZZ;
244 : 0 : strcpy(pStruct->at2[a].elname, "Zz");
245 : 0 : pStruct->n_zy--;
246 : 0 : pStruct->n_pzz++;
247 : : }
248 : : }
249 : : }
250 : :
251 : 0 : return ret; /* same interpretation as in ProcessOneStructure ??? */
252 : : }
253 : :
254 : :
255 : : /****************************************************************************/
256 : 0 : void RemoveFixHInChIIdentical2MobH(InpInChI* pOneInput)
257 : : {
258 : : int iInchiRec, cur_num_comp, k;
259 : :
260 : : /* eliminate Fixed-H InChI that are exactly same as the corresponding Mobile-H structures */
261 [ # # ]: 0 : for (iInchiRec = 0; iInchiRec < INCHI_NUM; iInchiRec++)
262 : : {
263 : 0 : cur_num_comp = inchi_min(pOneInput->nNumComponents[iInchiRec][TAUT_YES],
264 : : pOneInput->nNumComponents[iInchiRec][TAUT_NON]);
265 [ # # ]: 0 : for (k = 0; k < cur_num_comp; k++)
266 : : {
267 [ # # ]: 0 : if (!CompareReversedINChI(pOneInput->pInpInChI[iInchiRec][TAUT_YES] + k,
268 : 0 : pOneInput->pInpInChI[iInchiRec][TAUT_NON] + k, NULL, NULL))
269 : : {
270 : 0 : Free_INChI_Members(pOneInput->pInpInChI[iInchiRec][TAUT_NON] + k);
271 : 0 : memset(pOneInput->pInpInChI[iInchiRec][TAUT_NON] + k, 0, sizeof(pOneInput->pInpInChI[0][0][0])); /* djb-rwth: memset_s C11/Annex K variant? */
272 : : }
273 : : }
274 : : }
275 : 0 : }
276 : :
277 : :
278 : : /****************************************************************************
279 : : mark Disconnected InChI components that are exactly same as Reconnected ones
280 : : Disconnected will have a negative number of the reconnected component
281 : : Reconnected will have a positive number of the disconnected component
282 : : ****************************************************************************/
283 : 0 : int MarkDisconectedIdenticalToReconnected(InpInChI* pOneInput)
284 : : {
285 : 0 : int k1, k2, num_marked = 0;
286 : 0 : int k1max = inchi_max(pOneInput->nNumComponents[INCHI_BAS][TAUT_YES],
287 : : pOneInput->nNumComponents[INCHI_BAS][TAUT_NON]);
288 : :
289 [ # # ]: 0 : for (k1 = 0; k1 < k1max; k1++)
290 : : {
291 : 0 : int k2max = inchi_max(pOneInput->nNumComponents[INCHI_REC][TAUT_YES],
292 : : pOneInput->nNumComponents[INCHI_REC][TAUT_NON]);
293 : :
294 [ # # ]: 0 : for (k2 = 0; k2 < k2max; k2++)
295 : : {
296 : 0 : int eqM = k1 < pOneInput->nNumComponents[INCHI_BAS][TAUT_YES]
297 : 0 : &&
298 [ # # ]: 0 : k2 < pOneInput->nNumComponents[INCHI_REC][TAUT_YES]
299 : 0 : &&
300 [ # # ]: 0 : !pOneInput->pInpInChI[INCHI_REC][TAUT_YES][k2].nLink /* already linked */
301 : 0 : &&
302 [ # # ]: 0 : !pOneInput->pInpInChI[INCHI_BAS][TAUT_YES][k1].bDeleted
303 : 0 : &&
304 [ # # ]: 0 : pOneInput->pInpInChI[INCHI_BAS][TAUT_YES][k1].nNumberOfAtoms
305 : 0 : &&
306 : 0 : pOneInput->pInpInChI[INCHI_BAS][TAUT_YES][k1].nNumberOfAtoms ==
307 [ # # ]: 0 : pOneInput->pInpInChI[INCHI_REC][TAUT_YES][k2].nNumberOfAtoms
308 : 0 : &&
309 [ # # ]: 0 : !pOneInput->pInpInChI[INCHI_REC][TAUT_YES][k2].bDeleted
310 [ # # # # ]: 0 : &&
311 : 0 : !CompareReversedINChI(pOneInput->pInpInChI[INCHI_REC][TAUT_YES] + k2,
312 : 0 : pOneInput->pInpInChI[INCHI_BAS][TAUT_YES] + k1,
313 : : NULL, NULL);
314 : :
315 : 0 : int isF1 = k1 < pOneInput->nNumComponents[INCHI_BAS][TAUT_NON]
316 : 0 : &&
317 [ # # ]: 0 : 0 == pOneInput->pInpInChI[INCHI_BAS][TAUT_NON][k1].bDeleted
318 [ # # ]: 0 : &&
319 [ # # ]: 0 : 0 < pOneInput->pInpInChI[INCHI_BAS][TAUT_NON][k1].nNumberOfAtoms
320 : : ;
321 : :
322 : 0 : int isF2 = k2 < pOneInput->nNumComponents[INCHI_REC][TAUT_NON]
323 : 0 : &&
324 [ # # ]: 0 : 0 == pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].bDeleted
325 [ # # ]: 0 : &&
326 [ # # ]: 0 : 0 < pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].nNumberOfAtoms
327 : : ;
328 : :
329 : 0 : int eqF = isF1
330 [ # # ]: 0 : &&
331 : : isF2
332 : 0 : &&
333 [ # # ]: 0 : !pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].nLink
334 : 0 : &&
335 : 0 : pOneInput->pInpInChI[INCHI_BAS][TAUT_NON][k1].nNumberOfAtoms ==
336 [ # # ]: 0 : pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].nNumberOfAtoms
337 [ # # # # ]: 0 : &&
338 : 0 : !CompareReversedINChI(pOneInput->pInpInChI[INCHI_REC][TAUT_NON] + k2,
339 : 0 : pOneInput->pInpInChI[INCHI_BAS][TAUT_NON] + k1,
340 : : NULL, NULL)
341 : : ;
342 : :
343 [ # # # # : 0 : if (eqM && ((!isF1 && !isF2) || eqF)) /* djb-rwth: addressing LLVM warning */
# # # # ]
344 : : {
345 : 0 : pOneInput->pInpInChI[INCHI_BAS][TAUT_YES][k1].nLink = -(k2 + 1);
346 : 0 : pOneInput->pInpInChI[INCHI_REC][TAUT_YES][k2].nLink = (k1 + 1);
347 [ # # ]: 0 : if (eqF)
348 : : {
349 : 0 : pOneInput->pInpInChI[INCHI_BAS][TAUT_NON][k1].nLink = -(k2 + 1);
350 : 0 : pOneInput->pInpInChI[INCHI_REC][TAUT_NON][k2].nLink = (k1 + 1);
351 : : }
352 : 0 : num_marked++;
353 : 0 : break;
354 : : /* equal InChI has been deleted from the disconnected layer, get next k1 */
355 : : }
356 : : }
357 : : }
358 : :
359 : 0 : return num_marked;
360 : : }
361 : :
362 : :
363 : : /****************************************************************************/
364 : 0 : void SetUpSrm(SRM* pSrm)
365 : : {
366 : : /* structure restore parms !!!!! */
367 : 0 : memset(pSrm, 0, sizeof(pSrm[0])); /* djb-rwth: memset_s C11/Annex K variant? */
368 : 0 : pSrm->bFixStereoBonds = FIX_STEREO_BOND_ORDER;
369 : 0 : pSrm->nMetal2EndpointMinBondOrder = 1;
370 : 0 : pSrm->nMetal2EndpointInitEdgeFlow = 0;
371 : :
372 : : if (METAL_FREE_CHARGE_VAL == 1)
373 : : {
374 : 0 : pSrm->bMetalAddFlower = 1;
375 : : /* the next 3 parameters: */
376 : : /* 0, 0, 0 => all bonds 0, no init radical on metal */
377 : : /* 0, 0, 1 => all bonds 0, init radical on metal */
378 : : /* 0, 1, 0 => wrong */
379 : : /* 0, 1, 1 => all bonds 1, no init radical on metal */
380 : : /* 1, 0, 1 => min bond order 1, all bonds to metal have order 1 */
381 : : /* 1, 1, 0 => wrong */
382 : : /* 1, 1, 1 => wrong */
383 : 0 : pSrm->nMetalMinBondOrder = 0;
384 : 0 : pSrm->nMetalInitEdgeFlow = 1;
385 : 0 : pSrm->nMetalInitBondOrder = 1;
386 : 0 : pSrm->bStereoRemovesMetalFlag = pSrm->bFixStereoBonds;
387 : 0 : pSrm->nMetalFlowerParam_D = 16;
388 : 0 : pSrm->nMetalMaxCharge_D = 16;
389 : : }
390 : : else
391 : : {
392 : : pSrm->bMetalAddFlower = 0;
393 : : pSrm->nMetalMinBondOrder = 1;
394 : : pSrm->nMetalInitEdgeFlow = 0;
395 : : pSrm->nMetalInitBondOrder = 1;
396 : : pSrm->bStereoRemovesMetalFlag = pSrm->bFixStereoBonds;
397 : : pSrm->nMetalFlowerParam_D = 16;
398 : : pSrm->nMetalMaxCharge_D = 0;
399 : : }
400 : 0 : pSrm->nMetal2EndpointInitBondOrder = pSrm->nMetal2EndpointMinBondOrder
401 : 0 : + pSrm->nMetal2EndpointInitEdgeFlow;
402 : 0 : }
403 : :
404 : :
405 : : /****************************************************************************/
406 : 0 : int MergeStructureComponents(ICHICONST INPUT_PARMS* ip,
407 : : STRUCT_DATA* sd,
408 : : long num_inp,
409 : : char* szCurHdr,
410 : : ICHICONST SRM* pSrm,
411 : : int bReqNonTaut,
412 : : StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
413 : : InpInChI* pOneInput)
414 : : {
415 : : int iInchiRec, iMobileH, iAlternH, num_components, tot_just_atoms, tot_atoms, cur_nA, cur_nH; /* djb-rwth: removing redundant variables */
416 : : int k, i, j, ret, iCurAtomOffs, iNxtAtomOffs, iCurDelHOffs, iNxtDelHOffs, len, len2, iShiftH, icomp;
417 : 0 : int* nAtomOffs = NULL, * nDelHOffs = NULL;
418 : : StrFromINChI* pStruct1;
419 : 0 : inp_ATOM* at = NULL, * a;
420 : :
421 : 0 : ret = 0;
422 : 0 : pOneInput->num_atoms = 0;
423 : : /* select highest detail level */
424 [ # # ]: 0 : if ((num_components = pOneInput->nNumComponents[INCHI_REC][TAUT_NON])) /* djb-rwth: addressing LLVM warning */
425 : : {
426 : 0 : iInchiRec = INCHI_REC;
427 : 0 : iMobileH = TAUT_NON;
428 : : }
429 : : else
430 : : {
431 [ # # ]: 0 : if ((num_components = pOneInput->nNumComponents[INCHI_REC][TAUT_YES])) /* djb-rwth: addressing LLVM warning */
432 : : {
433 : 0 : iInchiRec = INCHI_REC;
434 : 0 : iMobileH = TAUT_YES;
435 : : }
436 : : else
437 : : {
438 [ # # ]: 0 : if ((num_components = pOneInput->nNumComponents[INCHI_BAS][TAUT_NON])) /* djb-rwth: addressing LLVM warning */
439 : : {
440 : 0 : iInchiRec = INCHI_BAS;
441 : 0 : iMobileH = TAUT_NON;
442 : : }
443 : : else
444 : : {
445 [ # # ]: 0 : if ((num_components = pOneInput->nNumComponents[INCHI_BAS][TAUT_YES])) /* djb-rwth: addressing LLVM warning */
446 : : {
447 : 0 : iInchiRec = INCHI_BAS;
448 : 0 : iMobileH = TAUT_YES;
449 : : }
450 : : else
451 : : {
452 : 0 : return 0; /* no components available */
453 : : }
454 : : }
455 : : }
456 : : }
457 : :
458 : 0 : nAtomOffs = (int*)inchi_malloc(((long long)num_components + 1) * sizeof(nAtomOffs[0])); /* djb-rwth: cast operator added */
459 : 0 : nDelHOffs = (int*)inchi_malloc(((long long)num_components + 1) * sizeof(nDelHOffs[0])); /* djb-rwth: cast operator added */
460 [ # # # # ]: 0 : if (!nAtomOffs || !nDelHOffs)
461 : : {
462 : 0 : ret = RI_ERR_ALLOC;
463 : 0 : goto exit_function;
464 : : }
465 : : /* count number of atoms and removed H */
466 : : /* djb-rwth: removing redundant code */
467 [ # # # # ]: 0 : iAlternH = (iMobileH == TAUT_NON && pOneInput->nNumComponents[iInchiRec][TAUT_YES]) ? TAUT_YES : -1;
468 : 0 : nAtomOffs[0] = nDelHOffs[0] = 0;
469 [ # # ]: 0 : for (k = 0; k < num_components; k++)
470 : : {
471 [ # # ]: 0 : pStruct1 = pStruct[iInchiRec][iMobileH][k].num_atoms ? pStruct[iInchiRec][iMobileH] + k :
472 : 0 : iAlternH >= 0 &&
473 [ # # # # ]: 0 : pStruct[iInchiRec][iAlternH][k].num_atoms ? pStruct[iInchiRec][iAlternH] + k : NULL;
474 [ # # # # : 0 : if (!pStruct1 || !pStruct1->at2 || !pStruct1->num_atoms || pStruct1->bDeleted)
# # # # ]
475 : : {
476 : 0 : cur_nA = cur_nH = 0;
477 : : }
478 : : else
479 : : {
480 : 0 : cur_nA = pStruct1->num_atoms;
481 : 0 : cur_nH = pStruct1->num_deleted_H;
482 : : }
483 : 0 : nAtomOffs[k + 1] = nAtomOffs[k] + cur_nA;
484 : 0 : nDelHOffs[k + 1] = nDelHOffs[k] + cur_nH;
485 : : }
486 : 0 : tot_just_atoms = nAtomOffs[num_components];
487 : : /* shift all H to the end */
488 [ # # ]: 0 : for (k = 0; k <= num_components; k++)
489 : : {
490 : 0 : nDelHOffs[k] += tot_just_atoms;
491 : : }
492 : 0 : tot_atoms = nDelHOffs[num_components];
493 : :
494 : : /* merge atoms together: 1. Allocate */
495 : 0 : at = (inp_ATOM*)inchi_malloc(((long long)tot_atoms + 1) * sizeof(at[0])); /* djb-rwth: cast operator added */
496 [ # # ]: 0 : if (NULL == at)
497 : : {
498 : 0 : ret = RI_ERR_ALLOC;
499 : 0 : goto exit_function;
500 : : }
501 [ # # ]: 0 : if (!tot_atoms)
502 : : {
503 : 0 : ret = 0;
504 : 0 : goto exit_function; /* empty structure */
505 : : }
506 : : /* merge atoms together: 2. Copy */
507 [ # # ]: 0 : for (k = 0; k < num_components; k++)
508 : : {
509 [ # # ]: 0 : pStruct1 = pStruct[iInchiRec][iMobileH][k].num_atoms ? pStruct[iInchiRec][iMobileH] + k :
510 : 0 : iAlternH >= 0 &&
511 [ # # # # ]: 0 : pStruct[iInchiRec][iAlternH][k].num_atoms ? pStruct[iInchiRec][iAlternH] + k : NULL;
512 [ # # # # ]: 0 : if ((len = nAtomOffs[k + 1] - nAtomOffs[k]) && pStruct1) /* djb-rwth: addressing LLVM warning; fixing coverity ID #499555 */
513 : : {
514 : 0 : memcpy(at + nAtomOffs[k], pStruct1->at2, len * sizeof(at[0]));
515 [ # # ]: 0 : if ((len2 = nDelHOffs[k + 1] - nDelHOffs[k])) /* djb-rwth: addressing LLVM warning */
516 : : {
517 : 0 : memcpy(at + nDelHOffs[k], pStruct1->at2 + len, len2 * sizeof(at[0]));
518 : : }
519 : : }
520 : : }
521 : : /* merge atoms together: 3. Update atom numbers */
522 : 0 : icomp = 0;
523 [ # # ]: 0 : for (k = 0; k < num_components; k++)
524 : : {
525 : 0 : iCurAtomOffs = nAtomOffs[k];
526 : 0 : iNxtAtomOffs = nAtomOffs[k + 1];
527 : 0 : iCurDelHOffs = nDelHOffs[k];
528 : 0 : iNxtDelHOffs = nDelHOffs[k + 1];
529 : 0 : len = nAtomOffs[k + 1] - nAtomOffs[k]; /* number of atoms in a component excluding explicit H */
530 : 0 : iShiftH = iCurDelHOffs - len;
531 [ # # ]: 0 : if (!len)
532 : : {
533 : 0 : continue;
534 : : }
535 : 0 : icomp++; /* current component number */
536 : : /* update atoms */
537 [ # # ]: 0 : for (i = iCurAtomOffs; i < iNxtAtomOffs; i++)
538 : : {
539 : :
540 : 0 : a = at + i;
541 : :
542 : 0 : a->endpoint = 0;
543 : 0 : a->bAmbiguousStereo = 0;
544 : 0 : a->at_type = 0;
545 : 0 : a->bCutVertex = 0;
546 : 0 : a->bUsed0DParity = 0;
547 : 0 : a->cFlags = 0;
548 : 0 : a->nBlockSystem = 0;
549 : 0 : a->nNumAtInRingSystem = 0;
550 : 0 : a->nRingSystem = 0;
551 : : /* djb-rwth: addressing coverity ID #499524 -- initialisation with at */
552 : :
553 [ # # ]: 0 : for (j = 0; j < a->valence; j++)
554 : : {
555 [ # # ]: 0 : if (a->neighbor[j] < len)
556 : : {
557 : 0 : a->neighbor[j] += iCurAtomOffs; /* atom */
558 : : }
559 : : else
560 : : {
561 : 0 : a->neighbor[j] += iShiftH; /* explicit H */
562 : : }
563 : : }
564 : 0 : a->orig_at_number += iCurAtomOffs;
565 : 0 : a->component = icomp;
566 [ # # ]: 0 : if (a->p_parity)
567 : : {
568 [ # # ]: 0 : for (j = 0; j < MAX_NUM_STEREO_ATOM_NEIGH; j++)
569 : : {
570 [ # # ]: 0 : if (a->p_orig_at_num[j] <= len)
571 : : {
572 : : /* originally, orig_at_num = atom_index+1, therefore <= instead of < */
573 : 0 : a->p_orig_at_num[j] += iCurAtomOffs;
574 : : }
575 : : else
576 : : {
577 : 0 : a->p_orig_at_num[j] += iShiftH;
578 : : }
579 : : }
580 : : }
581 [ # # # # ]: 0 : for (j = 0; j < MAX_NUM_STEREO_BONDS && a->sb_parity[j]; j++)
582 : : {
583 [ # # ]: 0 : if (a->sn_orig_at_num[j] <= len)
584 : : {
585 : : /* originally, orig_at_num = atom_index+1, therefore <= instead of < */
586 : 0 : a->sn_orig_at_num[j] += iCurAtomOffs;
587 : : }
588 : : else
589 : : {
590 : 0 : a->sn_orig_at_num[j] += iShiftH;
591 : : }
592 : : }
593 : : }
594 : : /* update fixed-H */
595 [ # # ]: 0 : for (i = iCurDelHOffs; i < iNxtDelHOffs; i++)
596 : : {
597 : 0 : a = at + i;
598 : 0 : a->neighbor[0] += iCurAtomOffs;
599 : 0 : a->orig_at_number += iShiftH;
600 : : }
601 : : }
602 : : /* save the results */
603 : 0 : pOneInput->atom = at;
604 : 0 : pOneInput->num_atoms = tot_atoms;
605 : 0 : at = NULL;
606 : :
607 : 0 : exit_function:
608 [ # # # # ]: 0 : if (at) inchi_free(at); /* in case of failure */
609 [ # # # # ]: 0 : if (nAtomOffs) inchi_free(nAtomOffs);
610 [ # # # # ]: 0 : if (nDelHOffs) inchi_free(nDelHOffs);
611 : 0 : return ret;
612 : : }
613 : :
614 : :
615 : : #ifndef COMPILE_ANSI_ONLY
616 : :
617 : :
618 : : static PER_DRAW_PARMS pdp;
619 : :
620 : :
621 : : /****************************************************************************/
622 : : int DisplayAllRestoredComponents(struct tagCANON_GLOBALS* pCG,
623 : : inp_ATOM* at,
624 : : int num_at,
625 : : const char* szCurHdr)
626 : : {
627 : : int ret; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
628 : : char szTitle[512];
629 : : DRAW_PARMS dp;
630 : : TBL_DRAW_PARMS tdp;
631 : : if (num_at <= 0)
632 : : {
633 : : return 0;
634 : : }
635 : : memset(&dp, 0, sizeof(dp)); /* djb-rwth: memset_s C11/Annex K variant? */
636 : : memset(&tdp, 0, sizeof(tdp)); /* djb-rwth: memset_s C11/Annex K variant? */
637 : : /*memset( &pdp, 0, sizeof(pdp) );*/
638 : : dp.sdp.tdp = &tdp;
639 : : dp.pdp = &pdp;
640 : : dp.sdp.nFontSize = -9;
641 : : sprintf(szTitle, "All Components of Restored %s Structure", szCurHdr ? szCurHdr : "(No structure name)");
642 : : ret = DisplayStructure(pCG, at, num_at,
643 : : NULL, /* OAD_Polymer *polymer, */
644 : : 0 /* nNumDeletedH*/, 0 /*bAdd_DT_to_num_H*/,
645 : : 0 /*nNumRemovedProtons*/, NULL /*NUM_H *nNumRemovedProtonsIsotopic*/,
646 : : 1 /*int bIsotopic*/, 0 /*bTautomeric*/,
647 : : NULL /* pINChI */, NULL /* INChI_Aux **cur_INChI_Aux*/,
648 : : 0 /*bAbcNumbers*/, &dp, 0 /*INCHI_MODE nMode*/, szTitle); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
649 : :
650 : : return 0;
651 : : }
652 : :
653 : :
654 : : /****************************************************************************/
655 : : int DisplayOneRestoredComponent(struct tagCANON_GLOBALS* pCG,
656 : : StrFromINChI* pStruct,
657 : : inp_ATOM* at,
658 : : int iComponent,
659 : : int nNumComponents,
660 : : int bMobileH,
661 : : const char* szCurHdr)
662 : : {
663 : : int ret, k; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
664 : : int num_at = pStruct->num_atoms;
665 : : XYZ_COORD* pxyz = pStruct->pXYZ;
666 : : char szTitle[512];
667 : : DRAW_PARMS dp;
668 : : TBL_DRAW_PARMS tdp;
669 : : int iInchiRec = pStruct->iInchiRec;
670 : : int iMobileH = pStruct->iMobileH;
671 : : INChI** pInChI = NULL;
672 : : INChI_Aux** pAux = NULL;
673 : : int nNumRemovedProtons = pAux ? pAux[iMobileH]->nNumRemovedProtons : 0;
674 : : NUM_H* nNumRemovedProtonsIsotopic = pAux ? pAux[iMobileH]->nNumRemovedIsotopicH : NULL;
675 : :
676 : :
677 : : if (num_at <= 0 || !pxyz)
678 : : {
679 : : return 0;
680 : : }
681 : : if (iInchiRec && !pStruct->RevInChI.pINChI_Aux[iInchiRec][0])
682 : : {
683 : : iInchiRec = 0;
684 : : }
685 : : k = iMobileH;
686 : : if (!bRevInchiComponentExists(pStruct, iInchiRec, k, 0))
687 : : {
688 : : k = ALT_TAUT(k);
689 : : }
690 : : pInChI = pStruct->RevInChI.pINChI[iInchiRec][0];
691 : : pAux = pStruct->RevInChI.pINChI_Aux[iInchiRec][0];
692 : :
693 : :
694 : : memset(&dp, 0, sizeof(dp)); /* djb-rwth: memset_s C11/Annex K variant? */
695 : : memset(&tdp, 0, sizeof(tdp)); /* djb-rwth: memset_s C11/Annex K variant? */
696 : : /*memset( &pdp, 0, sizeof(pdp) );*/
697 : : dp.sdp.tdp = &tdp;
698 : : dp.pdp = &pdp;
699 : : dp.sdp.nFontSize = -9;
700 : : sprintf(szTitle, "Restored %s Component %d of %d %c%c",
701 : : szCurHdr ? szCurHdr : "(No structure name)", iComponent + 1, nNumComponents,
702 : : pStruct->iInchiRec ? 'R' : 'D', pStruct->iMobileH ? 'M' : 'F');
703 : : ret = DisplayStructure(pCG, at, num_at,
704 : : NULL, /* OAD_Polymer *polymer, */
705 : : 0 /* nNumDeletedH*/, 0 /*bAdd_DT_to_num_H*/,
706 : : nNumRemovedProtons, /*NULL*/ nNumRemovedProtonsIsotopic,
707 : : 1 /*int bIsotopic*/, k,
708 : : pInChI, pAux,
709 : : 0 /*bAbcNumbers*/, &dp, 0 /*INCHI_MODE nMode*/, szTitle); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
710 : :
711 : : return 0;
712 : : }
713 : :
714 : :
715 : : /****************************************************************************/
716 : : int DisplayRestoredComponent(struct tagCANON_GLOBALS* pCG,
717 : : StrFromINChI* pStruct,
718 : : int iComponent,
719 : : int iAtNoOffset,
720 : : INChI* pInChI,
721 : : const char* szCurHdr)
722 : : {
723 : : int i, ret; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
724 : : int num_at = pStruct->num_atoms;
725 : : int num_deleted_H = pStruct->num_deleted_H;
726 : : inp_ATOM* atom = pStruct->at2;
727 : : XYZ_COORD* pxyz = pStruct->pXYZ;
728 : : inp_ATOM* at = NULL;
729 : : char szTitle[512];
730 : : DRAW_PARMS dp;
731 : : TBL_DRAW_PARMS tdp;
732 : : if (!atom || num_at <= 0 || !pxyz)
733 : : {
734 : : return 0;
735 : : }
736 : : at = (inp_ATOM*)inchi_calloc((long long)num_at + (long long)num_deleted_H, sizeof(at[0])); /* djb-rwth: cast operator added */
737 : : if (!at)
738 : : {
739 : : return RI_ERR_ALLOC;
740 : : }
741 : : memcpy(at, atom, ((long long)num_at + (long long)num_deleted_H) * sizeof(at[0])); /* djb-rwth: cast operator added */
742 : : for (i = 0; i < num_at; i++)
743 : : {
744 : : at[i].x = pxyz[i].xyz[0];
745 : : at[i].y = pxyz[i].xyz[1];
746 : : at[i].z = pxyz[i].xyz[2];
747 : : }
748 : : memset(&dp, 0, sizeof(dp)); /* djb-rwth: memset_s C11/Annex K variant? */
749 : : memset(&tdp, 0, sizeof(tdp)); /* djb-rwth: memset_s C11/Annex K variant? */
750 : : /*memset( &pdp, 0, sizeof(pdp) );*/
751 : : dp.sdp.tdp = &tdp;
752 : : dp.pdp = &pdp;
753 : : dp.sdp.nFontSize = -9;
754 : : sprintf(szTitle, "DBG Restored %s Component %d %c%c", szCurHdr ? szCurHdr : "(No structure name)", iComponent + 1, pStruct->iInchiRec ? 'R' : 'D', pStruct->iMobileH ? 'M' : 'F');
755 : :
756 : : ret = DisplayStructure(pCG, at, num_at,
757 : : NULL, /* OAD_Polymer *polymer, */
758 : : 0 /* nNumDeletedH*/, 0 /*bAdd_DT_to_num_H*/,
759 : : 0 /*nNumRemovedProtons*/, NULL /*NUM_H *nNumRemovedProtonsIsotopic*/,
760 : : 1 /*int bIsotopic*/, 0 /*bTautomeric*/,
761 : : &pInChI, NULL /* INChI_Aux **cur_INChI_Aux*/,
762 : : 0 /*bAbcNumbers*/, &dp, 0 /*INCHI_MODE nMode*/, szTitle); /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
763 : :
764 : : inchi_free(at);
765 : :
766 : : return 0;
767 : : }
768 : :
769 : :
770 : : /****************************************************************************/
771 : : int DisplayStructureComponents(struct tagCANON_GLOBALS* pCG,
772 : : ICHICONST INPUT_PARMS* ip,
773 : : STRUCT_DATA* sd,
774 : : long num_inp,
775 : : char* szCurHdr,
776 : : ICHICONST SRM* pSrm,
777 : : int bReqNonTaut,
778 : : StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
779 : : InpInChI* pOneInput)
780 : : {
781 : : int iInchiRec, iMobileH,
782 : : iCurMobH = -1,
783 : : iAlternH, num_components, tot_just_atoms, tot_atoms, cur_nA, cur_nH; /* djb-rwth: removing redundant variables */
784 : : int k, i, j, ret, iCurAtomOffs, iNxtAtomOffs, len, len2; /* djb-rwth: removing redundant variables; removing redundant variables/code */
785 : : int* nAtomOffs = NULL, * nDelHOffs = NULL, iNewCoord = 0, nNewCoord = 0; /* djb-rwth: removing redundant variables */
786 : : double x_max = -1.0e16, x_min = 1.0e16, y_max = -1.0e16, y_min = 1.0e16, delta = 0.0;
787 : : StrFromINChI* pStruct1;
788 : : inp_ATOM* at = NULL, * a;
789 : :
790 : : if (!ip->bDisplayCompositeResults && !ip->bDisplay)
791 : : {
792 : : return 0;
793 : : }
794 : :
795 : : ret = 0;
796 : : pOneInput->num_atoms = 0;
797 : : /* select highest detail level */
798 : : if ((num_components = pOneInput->nNumComponents[INCHI_REC][TAUT_NON])) /* djb-rwth: addressing LLVM warning */
799 : : {
800 : : iInchiRec = INCHI_REC;
801 : : iMobileH = TAUT_NON;
802 : : }
803 : : else
804 : : {
805 : : if ((num_components = pOneInput->nNumComponents[INCHI_REC][TAUT_YES])) /* djb-rwth: addressing LLVM warning */
806 : : {
807 : : iInchiRec = INCHI_REC;
808 : : iMobileH = TAUT_YES;
809 : : }
810 : : else
811 : : {
812 : : if ((num_components = pOneInput->nNumComponents[INCHI_BAS][TAUT_NON])) /* djb-rwth: addressing LLVM warning */
813 : : {
814 : : iInchiRec = INCHI_BAS;
815 : : iMobileH = TAUT_NON;
816 : : }
817 : : else
818 : : {
819 : : if ((num_components = pOneInput->nNumComponents[INCHI_BAS][TAUT_YES])) /* djb-rwth: addressing LLVM warning */
820 : : {
821 : : iInchiRec = INCHI_BAS;
822 : : iMobileH = TAUT_YES;
823 : : }
824 : : else
825 : : {
826 : : return 0; /* no components available */
827 : : }
828 : : }
829 : : }
830 : : }
831 : :
832 : : for (k = 0; k < num_components; k++)
833 : : {
834 : : if (pStruct[iInchiRec][iMobileH][k].bDeleted)
835 : : {
836 : : break;
837 : : }
838 : : }
839 : : num_components = k;
840 : :
841 : : nAtomOffs = (int*)inchi_malloc(((long long)num_components + 1) * sizeof(nAtomOffs[0])); /* djb-rwth: cast operator added */
842 : : nDelHOffs = (int*)inchi_malloc(((long long)num_components + 1) * sizeof(nDelHOffs[0])); /* djb-rwth: cast operator added */
843 : : if (!nAtomOffs || !nDelHOffs)
844 : : {
845 : : ret = RI_ERR_ALLOC;
846 : : goto exit_function;
847 : : }
848 : :
849 : : /* count number of atoms and removed H */
850 : : /* djb-rwth: removing redundant code */
851 : : iAlternH = (iMobileH == TAUT_NON && pOneInput->nNumComponents[iInchiRec][TAUT_YES]) ? TAUT_YES : -1;
852 : : nAtomOffs[0] = nDelHOffs[0] = 0;
853 : :
854 : : for (k = 0; k < num_components; k++)
855 : : {
856 : : pStruct1 = pStruct[iInchiRec][iMobileH][k].num_atoms ? pStruct[iInchiRec][iMobileH] + k :
857 : : iAlternH >= 0 &&
858 : : pStruct[iInchiRec][iAlternH][k].num_atoms ? pStruct[iInchiRec][iAlternH] + k : NULL;
859 : : if (!pStruct1 || !pStruct1->at2 || !pStruct1->num_atoms)
860 : : {
861 : : cur_nA = cur_nH = 0;
862 : : }
863 : : else
864 : : {
865 : : cur_nA = pStruct1->num_atoms;
866 : : cur_nH = pStruct1->num_deleted_H;
867 : : if (cur_nA && !pStruct1->pXYZ)
868 : : {
869 : : if (!k)
870 : : {
871 : : ret = 0; /* no coordinates available */
872 : : goto exit_function;
873 : : }
874 : : /* djb-rwth: removing redundant code */
875 : : }
876 : : }
877 : : nAtomOffs[k + 1] = nAtomOffs[k] + cur_nA;
878 : : nDelHOffs[k + 1] = nDelHOffs[k] + cur_nH;
879 : : }
880 : : tot_just_atoms = nAtomOffs[num_components];
881 : :
882 : : /* shift all H to the end */
883 : : for (k = 0; k <= num_components; k++)
884 : : {
885 : : nDelHOffs[k] += tot_just_atoms;
886 : : }
887 : : tot_atoms = nDelHOffs[num_components];
888 : :
889 : : /* merge atoms together: 1. Allocate */
890 : : if (NULL == (at = (inp_ATOM*)inchi_malloc(((long long)tot_atoms + 1) * sizeof(at[0])))) /* djb-rwth: cast operator added */
891 : : {
892 : : ret = RI_ERR_ALLOC;
893 : : goto exit_function;
894 : : }
895 : : if (!tot_atoms)
896 : : {
897 : : ret = 0;
898 : : goto exit_function; /* empty structure */
899 : : }
900 : :
901 : : /* merge atoms together: 2. Copy */
902 : : for (k = 0; k < num_components; k++)
903 : : {
904 : : pStruct1 = pStruct[iInchiRec][iMobileH][k].num_atoms ? pStruct[iInchiRec][iCurMobH = iMobileH] + k :
905 : : iAlternH >= 0 &&
906 : : pStruct[iInchiRec][iAlternH][k].num_atoms ? pStruct[iInchiRec][iCurMobH = iAlternH] + k : NULL;
907 : : if ((len = nAtomOffs[k + 1] - nAtomOffs[k]) && pStruct1) /* djb-rwth: addressing LLVM warning */
908 : : {
909 : : XYZ_COORD* pxyz = pStruct1->pXYZ;
910 : : len2 = nDelHOffs[k + 1] - nDelHOffs[k]; /* do not separate H from the atom: we will not need them */
911 : : iCurAtomOffs = nAtomOffs[k];
912 : : a = at + iCurAtomOffs;
913 : : memcpy(a, pStruct1->at2, ((long long)len + (long long)len2) * sizeof(at[0])); /* djb-rwth: cast operator added */
914 : : DisconnectedConnectedH(a, len, len2);
915 : : if (pxyz)
916 : : {
917 : : for (i = 0; i < len; i++)
918 : : {
919 : : a[i].x = pxyz[i].xyz[0];
920 : : x_max = inchi_max(x_max, pxyz[i].xyz[0]);
921 : : x_min = inchi_min(x_min, pxyz[i].xyz[0]);
922 : : a[i].y = pxyz[i].xyz[1];
923 : : y_max = inchi_max(y_max, pxyz[i].xyz[1]);
924 : : y_min = inchi_min(y_min, pxyz[i].xyz[1]);
925 : : a[i].z = pxyz[i].xyz[2];
926 : : nNewCoord++;
927 : : }
928 : : }
929 : : else
930 : : {
931 : : if (!iNewCoord)
932 : : {
933 : : if (!nNewCoord)
934 : : {
935 : : ret = 0;
936 : : goto exit_function; /* empty structure */
937 : : }
938 : : delta = inchi_max(x_max - x_min, y_max - y_min);
939 : : if (delta == 0.0)
940 : : {
941 : : delta = 0.5 * (x_max + x_min);
942 : : if (delta == 0.0)
943 : : delta = 1.0;
944 : : }
945 : : else
946 : : {
947 : : delta /= sqrt((double)((long long)nNewCoord + 1)); /* djb-rwth: cast operator added */
948 : : }
949 : : }
950 : : for (i = 0; i < len; i++)
951 : : {
952 : : a[i].x = x_max + delta;
953 : : a[i].y = y_max - iNewCoord * delta;
954 : : a[i].z = 0.0;
955 : : iNewCoord++;
956 : : }
957 : : if ((pStruct1->pXYZ = (XYZ_COORD*)inchi_calloc(len, sizeof(pStruct1->pXYZ[0])))) /* djb-rwth: addressing LLVM warning */
958 : : {
959 : :
960 : : for (i = 0; i < len; i++)
961 : : {
962 : : pStruct1->pXYZ[i].xyz[0] = a[i].x;
963 : : pStruct1->pXYZ[i].xyz[1] = a[i].y;
964 : : pStruct1->pXYZ[i].xyz[2] = 0.0;
965 : : }
966 : : }
967 : : }
968 : : if (ip->bDisplay || (ip->bDisplayCompositeResults && 1 == num_components)) /* djb-rwth: addressing LLVM warning */
969 : : {
970 : : DisplayOneRestoredComponent(pCG, pStruct1, a, k, num_components, iCurMobH, szCurHdr);
971 : : }
972 : : if (!pxyz && pStruct1->pXYZ)
973 : : {
974 : : inchi_free(pStruct1->pXYZ);
975 : : pStruct1->pXYZ = NULL;
976 : : }
977 : : }
978 : : }
979 : :
980 : : /* merge atoms together: 3. Update atom numbers */
981 : : /* djb-rwth: removing redundant code */
982 : : if (ip->bDisplayCompositeResults && num_components > 1)
983 : : {
984 : : for (k = 0; k < num_components; k++)
985 : : {
986 : : /* display each restored component if requested */
987 : : iCurAtomOffs = nAtomOffs[k];
988 : : iNxtAtomOffs = nAtomOffs[k + 1];
989 : : /* djb-rwth: removing redundant code */
990 : : /* djb-rwth: removing redundant code */
991 : : len = nAtomOffs[k + 1] - nAtomOffs[k]; /* number of atoms in a component excluding explicit H */
992 : : /* djb-rwth: removing redundant code */
993 : : if (!len)
994 : : {
995 : : continue;
996 : : }
997 : : /* djb-rwth: removing redundant code */
998 : : /* update atoms */
999 : : for (i = iCurAtomOffs; i < iNxtAtomOffs; i++)
1000 : : {
1001 : : a = at + i;
1002 : : for (j = 0; j < a->valence; j++)
1003 : : {
1004 : : if (a->neighbor[j] < len)
1005 : : {
1006 : : a->neighbor[j] += iCurAtomOffs; /* atom */
1007 : : }
1008 : : else
1009 : : {
1010 : : ret = RI_ERR_PROGR; /* explicit H */
1011 : : goto exit_function;
1012 : : }
1013 : : }
1014 : : a->orig_at_number += iCurAtomOffs;
1015 : : }
1016 : : }
1017 : : tot_atoms = nAtomOffs[num_components];
1018 : : DisplayAllRestoredComponents(pCG, at, tot_atoms, szCurHdr);
1019 : : }
1020 : :
1021 : : exit_function:
1022 : :
1023 : : if (at)
1024 : : {
1025 : : inchi_free(at); /* in case of failure */
1026 : : }
1027 : : if (nAtomOffs)
1028 : : {
1029 : : inchi_free(nAtomOffs);
1030 : : }
1031 : : if (nDelHOffs)
1032 : : {
1033 : : inchi_free(nDelHOffs);
1034 : : }
1035 : :
1036 : : return ret;
1037 : : }
1038 : : #endif
1039 : :
1040 : :
1041 : : /****************************************************************************/
1042 : 0 : int AllInchiToStructure(INCHI_CLOCK* ic,
1043 : : CANON_GLOBALS* pCG,
1044 : : ICHICONST INPUT_PARMS* ip_inp,
1045 : : STRUCT_DATA* sd_inp,
1046 : : long num_inp,
1047 : : char* szCurHdr,
1048 : : ICHICONST SRM* pSrm,
1049 : : int bHasSomeFixedH,
1050 : : StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
1051 : : InpInChI* pOneInput)
1052 : : {
1053 : : int iInchiRec, iMobileH, cur_num_comp, bCurI2A_Flag, k, ret, num_err;
1054 : : int iAtNoOffset;
1055 : : INPUT_PARMS* ip, ip_loc;
1056 : : STRUCT_DATA* sd, sd_loc;
1057 : 0 : long ulProcessingTime = 0;
1058 : : inchiTime ulTStart;
1059 : :
1060 : 0 : InchiTimeGet(&ulTStart);
1061 : 0 : ip = &ip_loc;
1062 : 0 : *ip = *ip_inp;
1063 : 0 : sd = &sd_loc;
1064 : 0 : memset(sd, 0, sizeof(*sd)); /* djb-rwth: memset_s C11/Annex K variant? */
1065 : 0 : sd->ulStructTime = sd_inp->ulStructTime;
1066 : 0 : ret = 0;
1067 : 0 : num_err = 0;
1068 [ # # ]: 0 : for (iInchiRec = 0; iInchiRec < INCHI_NUM; iInchiRec++)
1069 : : {
1070 : : /* Disconnected/Connected */
1071 [ # # ]: 0 : for (iMobileH = 0; iMobileH < TAUT_NUM; iMobileH++)
1072 : : {
1073 : : /* Mobile/Fixed H */
1074 : 0 : cur_num_comp = pOneInput->nNumComponents[iInchiRec][iMobileH];
1075 [ # # ]: 0 : if (!cur_num_comp)
1076 : : {
1077 : 0 : continue;
1078 : : }
1079 : : /* allocate memory for all existing components */
1080 : 0 : pStruct[iInchiRec][iMobileH] = (StrFromINChI*)inchi_calloc(cur_num_comp, sizeof(pStruct[0][0][0]));
1081 [ # # ]: 0 : if (!pStruct[iInchiRec][iMobileH])
1082 : : {
1083 : 0 : ret = RI_ERR_ALLOC;
1084 : 0 : goto exit_error;
1085 : : }
1086 : : /* set conversion mode */
1087 [ # # ]: 0 : bCurI2A_Flag = (iMobileH ? 0 : I2A_FLAG_FIXEDH) | (iInchiRec ? I2A_FLAG_RECMET : 0);
1088 [ # # ]: 0 : if (iMobileH)
1089 : : {
1090 : 0 : ip->nMode &= ~REQ_MODE_BASIC;
1091 : : }
1092 : : else
1093 : : {
1094 : 0 : ip->nMode |= REQ_MODE_BASIC;
1095 : : }
1096 : : /* InChI --> structure conversion for all components except duplicated */
1097 : 0 : iAtNoOffset = 0;
1098 [ # # ]: 0 : for (k = 0; k < cur_num_comp; k++)
1099 : : {
1100 : : /* components */
1101 [ # # # # ]: 0 : if ((!iMobileH && !pOneInput->pInpInChI[iInchiRec][iMobileH][k].nNumberOfAtoms) ||
1102 [ # # ]: 0 : pOneInput->pInpInChI[iInchiRec][iMobileH][k].bDeleted ||
1103 [ # # ]: 0 : pOneInput->pInpInChI[iInchiRec][iMobileH][k].nLink < 0) /* djb-rwth: addressing LLVM warning */
1104 : : {
1105 : 0 : pStruct[iInchiRec][iMobileH][k].nLink = pOneInput->pInpInChI[iInchiRec][iMobileH][k].nLink;
1106 : 0 : pStruct[iInchiRec][iMobileH][k].bDeleted = pOneInput->pInpInChI[iInchiRec][iMobileH][k].bDeleted;
1107 : 0 : continue; /* do not create a structure out of an unavailable
1108 : : Fixed-H InChI or out of the one present in Reconnected layer */
1109 : :
1110 : : #ifdef NEVER /* a wrong attempt to process deleted components here */
1111 : : if (pStruct[iInchiRec][iMobileH][k].nLink = pOneInput->pInpInChI[iInchiRec][iMobileH][k].nLink)
1112 : : {
1113 : : continue; /* do not create a structure out of an unavailable
1114 : : Fixed-H InChI or out of the one present in Reconnected layer */
1115 : : }
1116 : : else
1117 : : if (iMobileH && pOneInput->pInpInChI[iInchiRec][iMobileH][k].nNumberOfAtoms &&
1118 : : pOneInput->pInpInChI[iInchiRec][iMobileH][k].bDeleted &&
1119 : : pOneInput->pInpInChI[iInchiRec][iMobileH][0].bDeleted)
1120 : : {
1121 : : /* all components are protons */
1122 : : ;
1123 : : }
1124 : : else
1125 : : {
1126 : : continue;
1127 : : }
1128 : : #endif
1129 : :
1130 : : }
1131 [ # # # # : 0 : if (bHasSomeFixedH && iMobileH && k < pOneInput->nNumComponents[iInchiRec][TAUT_NON] &&
# # ]
1132 [ # # ]: 0 : pOneInput->pInpInChI[iInchiRec][TAUT_NON][k].nNumberOfAtoms)
1133 : : {
1134 : 0 : continue; /* do not process Mobile-H if Fixed-H is requested and exists */
1135 : : }
1136 : 0 : pStruct[iInchiRec][iMobileH][k].pSrm = pSrm;
1137 : 0 : pStruct[iInchiRec][iMobileH][k].iInchiRec = iInchiRec;
1138 : 0 : pStruct[iInchiRec][iMobileH][k].iMobileH = iMobileH;
1139 : :
1140 : : /****************************************************/
1141 : : /* */
1142 : : /* Convert InChI of one component into a Structure */
1143 : : /* */
1144 : : /****************************************************/
1145 : :
1146 : 0 : ret = InChI2Atom(ic, pCG, ip, sd, szCurHdr, num_inp, pStruct[iInchiRec][iMobileH] + k, k,
1147 : : iAtNoOffset /* 0*/, bCurI2A_Flag, bHasSomeFixedH, pOneInput);
1148 : 0 : pStruct[iInchiRec][iMobileH][k].nLink = pOneInput->pInpInChI[iInchiRec][iMobileH][k].nLink;
1149 [ # # ]: 0 : if (ret < 0)
1150 : : {
1151 : : #if ( bRELEASE_VERSION != 1 )
1152 : : #ifndef TARGET_API_LIB
1153 : : /* !!! Conversion Error -- Ignore for now !!! */
1154 : : fprintf(stdout, "%ld %s Conversion failed: %d, %c%c comp %d\n",
1155 : : num_inp, szCurHdr ? szCurHdr : "Struct", ret, iInchiRec ? 'R' : 'D', iMobileH ? 'M' : 'F', k + 1);
1156 : : #endif
1157 : : #endif
1158 [ # # ]: 0 : if (ret == CT_USER_QUIT_ERR)
1159 : : {
1160 : 0 : goto exit_error;
1161 : : }
1162 : 0 : pStruct[iInchiRec][iMobileH][k].nError = ret;
1163 : 0 : ret = 0; /* force to ignore the errors for now !!!! */
1164 : 0 : num_err++;
1165 : : }
1166 : 0 : iAtNoOffset += pOneInput->pInpInChI[iInchiRec][iMobileH][k].nNumberOfAtoms;
1167 : : } /* k-th component */
1168 : : }
1169 : : }
1170 : :
1171 : 0 : exit_error:
1172 : 0 : ulProcessingTime += InchiTimeElapsed(ic, &ulTStart);
1173 : 0 : sd->ulStructTime += ulProcessingTime;
1174 : :
1175 [ # # ]: 0 : return ret < 0 ? ret : num_err;
1176 : : }
1177 : :
1178 : :
1179 : : /****************************************************************************/
1180 : 0 : int AddProtonAndIsoHBalanceToMobHStruct(INCHI_CLOCK* ic,
1181 : : CANON_GLOBALS* pCG,
1182 : : ICHICONST INPUT_PARMS* ip,
1183 : : STRUCT_DATA* sd,
1184 : : long num_inp,
1185 : : int bHasSomeFixedH,
1186 : : char* szCurHdr,
1187 : : StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
1188 : : InpInChI* pOneInput)
1189 : : {
1190 : : COMPONENT_REM_PROTONS nToBeRemovedByNormFromRevrs[INCHI_NUM];
1191 : : int nRemovedByNormFromRevrs[INCHI_NUM];
1192 : : int nRemovedByRevrs[INCHI_NUM];
1193 : :
1194 : 0 : int nDeltaFromDisconnected = 0, nRemovedProtonsByNormFromRevrs, nRemovedProtonsByRevrs; /* djb-rwth: removing redundant variables */
1195 : : NUM_H nIsoDeltaFromDisconnected[NUM_H_ISOTOPES];
1196 : 0 : int iInchiRec, i, k, k1, ret = 0;
1197 : : int nChargeInChI, nChargeRevrs;
1198 : :
1199 [ # # ]: 0 : if (bHasSomeFixedH)
1200 : : {
1201 : 0 : return 0; /* 2005-03-01 */
1202 : : }
1203 : :
1204 : : /* num protons removed by InChI Normalization from the original structure */
1205 [ # # ]: 0 : for (i = 0; i < INCHI_NUM; i++)
1206 : : {
1207 : 0 : nToBeRemovedByNormFromRevrs[i].nNumRemovedProtons = pOneInput->nNumProtons[i][TAUT_YES].nNumRemovedProtons;
1208 [ # # ]: 0 : for (k = 0; k < NUM_H_ISOTOPES; k++)
1209 : : {
1210 : 0 : nToBeRemovedByNormFromRevrs[i].nNumRemovedIsotopicH[k] = pOneInput->nNumProtons[i][TAUT_YES].nNumRemovedIsotopicH[k];
1211 : : }
1212 : : }
1213 : : /* accumulate here num. protons removed by the normalization from the reversed structure */
1214 : 0 : nRemovedByNormFromRevrs[INCHI_BAS] =
1215 : 0 : nRemovedByNormFromRevrs[INCHI_REC] = 0;
1216 : 0 : nRemovedByRevrs[INCHI_REC] =
1217 : 0 : nRemovedByRevrs[INCHI_BAS] = 0;
1218 : : /* protons added/removed by InChI Normalization to/from Restored Structure might have been added by StructureRestore */
1219 : :
1220 [ # # ]: 0 : for (iInchiRec = 0; iInchiRec < INCHI_NUM; iInchiRec++)
1221 : : {
1222 [ # # ]: 0 : for (k = 0; k < pOneInput->nNumComponents[iInchiRec][TAUT_YES]; k++)
1223 : : {
1224 [ # # ]: 0 : if (!bInpInchiComponentExists(pOneInput, iInchiRec, TAUT_YES, k))
1225 : : {
1226 : 0 : continue;
1227 : : }
1228 : 0 : nRemovedProtonsByNormFromRevrs = 0; /* Num protons removed from the Restored Structure by InChI Normalization */
1229 : 0 : nRemovedProtonsByRevrs = 0; /* Num protons removed by the Reconstruction from the Restored Structure */
1230 [ # # # # : 0 : if (iInchiRec == INCHI_REC || (iInchiRec == INCHI_BAS && (pStruct[iInchiRec][TAUT_YES][k].nLink) >= 0)) /* djb-rwth: addressing LLVM warning; removing redundant code */
# # ]
1231 : 0 : {
1232 : :
1233 : 0 : REV_INCHI* pRevInChI = &pStruct[iInchiRec][TAUT_YES][k].RevInChI;
1234 : 0 : INChI_Aux** pINChI_Aux2 = pRevInChI->pINChI_Aux[iInchiRec][0]; /* component 0*/
1235 : 0 : INChI** pINChI_Revr = pRevInChI->pINChI[iInchiRec][0];
1236 : 0 : INChI* pINChI_Orig = pOneInput->pInpInChI[iInchiRec][TAUT_YES] + k;
1237 [ # # ]: 0 : nChargeRevrs = pINChI_Revr ? pINChI_Revr[TAUT_YES]->nTotalCharge : NO_VALUE_INT;
1238 : 0 : nChargeInChI = pINChI_Orig->nTotalCharge;
1239 [ # # ]: 0 : if (pINChI_Aux2)
1240 : : {
1241 : 0 : nRemovedProtonsByNormFromRevrs = pINChI_Aux2[TAUT_YES]->nNumRemovedProtons;
1242 : : }
1243 : 0 : nRemovedProtonsByRevrs = pStruct[iInchiRec][TAUT_YES][k].nNumRemovedProtonsByRevrs;
1244 : 0 : pStruct[iInchiRec][TAUT_YES][k].nChargeRevrs = nChargeRevrs;
1245 : 0 : pStruct[iInchiRec][TAUT_YES][k].nChargeInChI = nChargeInChI;
1246 : : }
1247 : : else
1248 : : {
1249 [ # # ]: 0 : if (0 <= (k1 = -(1 + pStruct[iInchiRec][TAUT_YES][k].nLink)))
1250 : : {
1251 : 0 : REV_INCHI* pRevInChI = &pStruct[INCHI_REC][TAUT_YES][k1].RevInChI;
1252 : 0 : INChI_Aux** pINChI_Aux2 = pRevInChI->pINChI_Aux[INCHI_BAS][0]; /* component 0 */
1253 : 0 : INChI** pINChI_Revr = pRevInChI->pINChI[INCHI_BAS][0];
1254 : 0 : INChI* pINChI_Orig = pOneInput->pInpInChI[INCHI_REC][TAUT_YES] + k1;
1255 [ # # ]: 0 : nChargeRevrs = pINChI_Revr ? pINChI_Revr[TAUT_YES]->nTotalCharge : NO_VALUE_INT;
1256 : 0 : nChargeInChI = pINChI_Orig->nTotalCharge;
1257 [ # # ]: 0 : if (pINChI_Aux2)
1258 : : {
1259 : 0 : nRemovedProtonsByNormFromRevrs = pINChI_Aux2[TAUT_YES]->nNumRemovedProtons;
1260 : : }
1261 : : /* this component cannot be disconnected because it is same as in reconnected layer */
1262 : 0 : nRemovedProtonsByRevrs = pStruct[INCHI_REC][TAUT_YES][k1].nNumRemovedProtonsByRevrs;
1263 : 0 : pStruct[iInchiRec][TAUT_YES][k1].nChargeRevrs = nChargeRevrs;
1264 : 0 : pStruct[iInchiRec][TAUT_YES][k1].nChargeInChI = nChargeInChI;
1265 : : }
1266 : : }
1267 : : /* how many protons (to be removed by InChI Normalization) to add =
1268 : : (proton balance in InChI} -
1269 : : {number of protons known to be removed by InChI Normalization from Reconstructed structure} */
1270 : 0 : nToBeRemovedByNormFromRevrs[iInchiRec].nNumRemovedProtons -= nRemovedProtonsByNormFromRevrs;
1271 : 0 : nRemovedByNormFromRevrs[iInchiRec] += nRemovedProtonsByNormFromRevrs;
1272 : 0 : nRemovedByRevrs[iInchiRec] += nRemovedProtonsByRevrs;
1273 : 0 : pStruct[iInchiRec][TAUT_YES][k].nRemovedProtonsByNormFromRevrs = nRemovedProtonsByNormFromRevrs;
1274 : : }
1275 : : }
1276 : :
1277 : : /* Since fixed-H layer is missing we need to add proton balance to the components */
1278 : 0 : memset(nIsoDeltaFromDisconnected, 0, sizeof(nIsoDeltaFromDisconnected)); /* djb-rwth: memset_s C11/Annex K variant? */
1279 [ # # ]: 0 : for (iInchiRec = INCHI_REC; INCHI_BAS <= iInchiRec; iInchiRec--)
1280 : : {
1281 : : /*
1282 : : if ( !pOneInput->nNumComponents[iInchiRec][TAUT_NON] &&
1283 : : pOneInput->nNumComponents[iInchiRec][TAUT_YES] ) {
1284 : : */
1285 [ # # # # ]: 0 : int bHasRecMobH = (iInchiRec == INCHI_BAS && pOneInput->nNumComponents[INCHI_REC][TAUT_YES]);
1286 : : /* bHasRecMobH means all components that could not be disconnected are in reconnected part */
1287 [ # # ]: 0 : if (iInchiRec == INCHI_BAS)
1288 : : {
1289 : : /* second pass: common structures have been changed */
1290 : 0 : nToBeRemovedByNormFromRevrs[INCHI_BAS].nNumRemovedProtons += nDeltaFromDisconnected;
1291 : : }
1292 : : /* after proton removal InChI is recalculated */
1293 : :
1294 [ # # # # : 0 : ret = AddRemProtonsInRestrStruct(ic, pCG, ip, sd, num_inp, bHasSomeFixedH, pStruct[iInchiRec][TAUT_YES],
# # ]
1295 : : pOneInput->nNumComponents[iInchiRec][TAUT_YES],
1296 : 0 : bHasRecMobH ? pStruct[INCHI_REC][TAUT_YES] : NULL,
1297 : : bHasRecMobH ? pOneInput->nNumComponents[INCHI_REC][TAUT_YES] : 0,
1298 : : &nToBeRemovedByNormFromRevrs[iInchiRec].nNumRemovedProtons,
1299 : : (iInchiRec == INCHI_REC) ? &nDeltaFromDisconnected : NULL);
1300 [ # # ]: 0 : if (ret < 0)
1301 : : {
1302 : 0 : goto exit_function;
1303 : : }
1304 : : /* djb-rwth: removing redundant code */
1305 : : /*
1306 : : }
1307 : : */
1308 : : }
1309 : :
1310 : : /* if fixed-H layer is missing then we need to add isotopic exchangeable proton balance to the components */
1311 [ # # ]: 0 : for (iInchiRec = INCHI_REC; INCHI_BAS <= iInchiRec; iInchiRec--)
1312 : : {
1313 : : /*
1314 : : if ( !pOneInput->nNumComponents[iInchiRec][TAUT_NON] &&
1315 : : pOneInput->nNumComponents[iInchiRec][TAUT_YES] ) {
1316 : : */
1317 [ # # # # ]: 0 : int bHasRecMobH = (iInchiRec == INCHI_BAS && pOneInput->nNumComponents[INCHI_REC][TAUT_YES]);
1318 : : /* bHasRecMobH means all components that could not be disconnected are in reconnected part */
1319 [ # # ]: 0 : if (iInchiRec == INCHI_BAS)
1320 : : {
1321 : : /* second pass: common structures have been changed */
1322 [ # # ]: 0 : for (k = 0; k < NUM_H_ISOTOPES; k++)
1323 : : {
1324 : 0 : nToBeRemovedByNormFromRevrs[INCHI_BAS].nNumRemovedIsotopicH[k] += nIsoDeltaFromDisconnected[k];
1325 : : }
1326 : : }
1327 : :
1328 : : /* after proton removal InChI is recalculated */
1329 [ # # # # ]: 0 : ret = AddRemIsoProtonsInRestrStruct(ic, pCG, ip, sd, num_inp, bHasSomeFixedH, pStruct[iInchiRec][TAUT_YES],
1330 : : pOneInput->nNumComponents[iInchiRec][TAUT_YES],
1331 : 0 : bHasRecMobH ? pStruct[INCHI_REC][TAUT_YES] : NULL,
1332 : : bHasRecMobH ? pOneInput->nNumComponents[INCHI_REC][TAUT_YES] : 0,
1333 [ # # ]: 0 : nToBeRemovedByNormFromRevrs[iInchiRec].nNumRemovedIsotopicH,
1334 : : (iInchiRec == INCHI_REC) ? nIsoDeltaFromDisconnected : NULL);
1335 : :
1336 [ # # ]: 0 : if (ret < 0)
1337 : : {
1338 : 0 : goto exit_function;
1339 : : }
1340 : : /* djb-rwth: removing redundant code */
1341 : : /*
1342 : : }
1343 : : */
1344 : : }
1345 : :
1346 : 0 : exit_function:
1347 : :
1348 : 0 : return ret;
1349 : : }
1350 : :
1351 : :
1352 : : /****************************************************************************/
1353 : 0 : void FreeStrFromINChI(StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
1354 : : int nNumComponents[INCHI_NUM][TAUT_NUM])
1355 : : {
1356 : : int iInchiRec, iMobileH, cur_num_comp, k, j;
1357 : : StrFromINChI* pStruct1;
1358 [ # # ]: 0 : for (iInchiRec = 0; iInchiRec < INCHI_NUM; iInchiRec++)
1359 : : {
1360 [ # # ]: 0 : for (iMobileH = 0; iMobileH < TAUT_NUM; iMobileH++)
1361 : : {
1362 : 0 : cur_num_comp = nNumComponents[iInchiRec][iMobileH];
1363 [ # # # # ]: 0 : if (!cur_num_comp || !(pStruct1 = pStruct[iInchiRec][iMobileH]))
1364 : : {
1365 : 0 : continue;
1366 : : }
1367 [ # # ]: 0 : for (k = 0; k < cur_num_comp; k++)
1368 : : {
1369 [ # # ]: 0 : if (pStruct1[k].at)
1370 : : {
1371 [ # # ]: 0 : inchi_free(pStruct1[k].at);
1372 : : }
1373 [ # # ]: 0 : if (pStruct1[k].at2)
1374 : : {
1375 [ # # ]: 0 : inchi_free(pStruct1[k].at2);
1376 : : }
1377 [ # # ]: 0 : if (pStruct1[k].st)
1378 : : {
1379 [ # # ]: 0 : inchi_free(pStruct1[k].st);
1380 : : }
1381 [ # # ]: 0 : if (pStruct1[k].pVA)
1382 : : {
1383 [ # # ]: 0 : inchi_free(pStruct1[k].pVA);
1384 : : }
1385 : : /*
1386 : : if ( pStruct1[k].ti.t_group ) {
1387 : : inchi_free( pStruct1[k].ti.t_group );
1388 : : }
1389 : : */
1390 [ # # ]: 0 : if (pStruct1[k].One_ti.t_group) {
1391 [ # # ]: 0 : inchi_free(pStruct1[k].One_ti.t_group); /* ricrogz: fixing memory leak */
1392 : : }
1393 [ # # ]: 0 : if (pStruct1[k].pXYZ)
1394 : : {
1395 [ # # ]: 0 : inchi_free(pStruct1[k].pXYZ); /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
1396 : : }
1397 : : /*==== begin ====*/
1398 : 0 : free_t_group_info(&pStruct1[k].ti);
1399 [ # # ]: 0 : if (pStruct1[k].endpoint)
1400 : : {
1401 [ # # ]: 0 : inchi_free(pStruct1[k].endpoint); /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
1402 : : }
1403 [ # # ]: 0 : if (pStruct1[k].fixed_H)
1404 : : {
1405 [ # # ]: 0 : inchi_free(pStruct1[k].fixed_H); /* djb-rwth: unresolved issue -- revision required? -- false positive as this function just does the clean-up job */
1406 : : }
1407 [ # # ]: 0 : for (j = 0; j < TAUT_NUM; j++)
1408 : : {
1409 [ # # ]: 0 : if (pStruct1[k].nAtno2Canon[j])
1410 [ # # ]: 0 : inchi_free(pStruct1[k].nAtno2Canon[j]);
1411 [ # # ]: 0 : if (pStruct1[k].nCanon2Atno[j])
1412 [ # # ]: 0 : inchi_free(pStruct1[k].nCanon2Atno[j]);
1413 : : }
1414 : : /*===== end ======*/
1415 : : /* free INChI memory */
1416 : 0 : FreeAllINChIArrays(pStruct1[k].RevInChI.pINChI,
1417 : 0 : pStruct1[k].RevInChI.pINChI_Aux,
1418 : 0 : pStruct1[k].RevInChI.num_components);
1419 : : #ifdef NEVER
1420 : : /* don't do that: these are just pointers to OneInput structure members */
1421 : : Free_INChI(&pStruct1[k].pINChI);
1422 : : Free_INChI_Aux(&pStruct1[k].pINChI_Aux);
1423 : : if (pStruct1[k].inp_norm_data)
1424 : : {
1425 : : FreeInpAtomData(pStruct1[k].inp_norm_data);
1426 : : inchi_free(pStruct1[k].inp_norm_data);
1427 : : }
1428 : : #endif
1429 : : }
1430 [ # # ]: 0 : inchi_free(pStruct[iInchiRec][iMobileH]);
1431 : 0 : pStruct[iInchiRec][iMobileH] = NULL;
1432 : : }
1433 : : }
1434 : 0 : }
1435 : :
1436 : :
1437 : : /****************************************************************************/
1438 : 0 : void FreeInpInChI(InpInChI* pOneInput)
1439 : : {
1440 : : int iINChI, k, j;
1441 [ # # ]: 0 : for (iINChI = 0; iINChI < INCHI_NUM; iINChI++)
1442 : : {
1443 [ # # ]: 0 : for (j = 0; j < TAUT_NUM; j++)
1444 : : {
1445 [ # # ]: 0 : if (pOneInput->pInpInChI[iINChI][j])
1446 : : {
1447 [ # # ]: 0 : for (k = 0; k < pOneInput->nNumComponents[iINChI][j]; k++)
1448 : : {
1449 : : #if (FIX_OSS_FUZZ_25734_28139 == 1)
1450 : 0 : U_CHAR* k_nAtom = (&pOneInput->pInpInChI[iINChI][j][k])->nAtom;
1451 : 0 : AT_NUMB* k_nConnTable = (&pOneInput->pInpInChI[iINChI][j][k])->nConnTable;
1452 : 0 : AT_NUMB* k_nTautomer = (&pOneInput->pInpInChI[iINChI][j][k])->nTautomer;
1453 : 0 : S_CHAR* k_nNum_H = (&pOneInput->pInpInChI[iINChI][j][k])->nNum_H;
1454 : 0 : S_CHAR* k_nNum_H_fixed = (&pOneInput->pInpInChI[iINChI][j][k])->nNum_H_fixed;
1455 : 0 : char* k_szHillFormula = (&pOneInput->pInpInChI[iINChI][j][k])->szHillFormula;
1456 : 0 : AT_NUMB* k_nPossibleLocationsOfIsotopicH = (&pOneInput->pInpInChI[iINChI][j][k])->nPossibleLocationsOfIsotopicH;
1457 : 0 : INChI_IsotopicAtom* k_IsotopicAtom = (&pOneInput->pInpInChI[iINChI][j][k])->IsotopicAtom;
1458 : 0 : INChI_IsotopicTGroup* k_IsotopicTGroup = (&pOneInput->pInpInChI[iINChI][j][k])->IsotopicTGroup;
1459 : 0 : INChI_Stereo* k_Stereo = (&pOneInput->pInpInChI[iINChI][j][k])->Stereo;
1460 : 0 : INChI_Stereo* k_StereoIsotopic = (&pOneInput->pInpInChI[iINChI][j][k])->StereoIsotopic;
1461 : :
1462 : : #endif
1463 : :
1464 : 0 : Free_INChI_Members(&pOneInput->pInpInChI[iINChI][j][k]);
1465 : :
1466 : : #if (FIX_OSS_FUZZ_25734_28139 == 1)
1467 : : {
1468 : : /* prevent erroneous repeated freeing in copied pInpInChIp[][][kk] */
1469 : : int kk;
1470 [ # # ]: 0 : for (kk = k + 1; kk < pOneInput->nNumComponents[iINChI][j]; kk++)
1471 : : {
1472 [ # # ]: 0 : if (k_nAtom == (&pOneInput->pInpInChI[iINChI][j][kk])->nAtom)
1473 : : {
1474 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->nAtom = NULL;
1475 : : }
1476 [ # # ]: 0 : if (k_nConnTable == (&pOneInput->pInpInChI[iINChI][j][kk])->nConnTable)
1477 : : {
1478 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->nConnTable = NULL;
1479 : : }
1480 [ # # ]: 0 : if (k_nTautomer == (&pOneInput->pInpInChI[iINChI][j][kk])->nTautomer)
1481 : : {
1482 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->nTautomer = NULL;
1483 : : }
1484 [ # # ]: 0 : if (k_nNum_H == (&pOneInput->pInpInChI[iINChI][j][kk])->nNum_H)
1485 : : {
1486 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->nNum_H = NULL;
1487 : : }
1488 [ # # ]: 0 : if (k_nNum_H_fixed == (&pOneInput->pInpInChI[iINChI][j][kk])->nNum_H_fixed)
1489 : : {
1490 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->nNum_H_fixed = NULL;
1491 : : }
1492 [ # # ]: 0 : if (k_szHillFormula == (&pOneInput->pInpInChI[iINChI][j][kk])->szHillFormula)
1493 : : {
1494 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->szHillFormula = NULL;
1495 : : }
1496 [ # # ]: 0 : if (k_nPossibleLocationsOfIsotopicH == (&pOneInput->pInpInChI[iINChI][j][kk])->nPossibleLocationsOfIsotopicH)
1497 : : {
1498 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->nPossibleLocationsOfIsotopicH = NULL;
1499 : : }
1500 : :
1501 [ # # ]: 0 : if (k_IsotopicAtom == (&pOneInput->pInpInChI[iINChI][j][kk])->IsotopicAtom)
1502 : : {
1503 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->IsotopicAtom = NULL;
1504 : : }
1505 : :
1506 [ # # ]: 0 : if (k_IsotopicTGroup == (&pOneInput->pInpInChI[iINChI][j][kk])->IsotopicTGroup)
1507 : : {
1508 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->IsotopicTGroup = NULL;
1509 : : }
1510 : :
1511 [ # # ]: 0 : if (k_Stereo == (&pOneInput->pInpInChI[iINChI][j][kk])->Stereo)
1512 : : {
1513 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->Stereo = NULL;
1514 : : }
1515 : :
1516 [ # # ]: 0 : if (k_StereoIsotopic == (&pOneInput->pInpInChI[iINChI][j][kk])->StereoIsotopic)
1517 : : {
1518 : 0 : (&pOneInput->pInpInChI[iINChI][j][kk])->StereoIsotopic = NULL;
1519 : : }
1520 : :
1521 : : }
1522 : : }
1523 : : #endif
1524 : :
1525 : : }
1526 [ # # ]: 0 : inchi_free(pOneInput->pInpInChI[iINChI][j]);
1527 : 0 : pOneInput->pInpInChI[iINChI][j] = NULL;
1528 : : }
1529 [ # # ]: 0 : if (pOneInput->nNumProtons[iINChI][j].pNumProtons)
1530 : : {
1531 [ # # ]: 0 : inchi_free(pOneInput->nNumProtons[iINChI][j].pNumProtons);
1532 : 0 : pOneInput->nNumProtons[iINChI][j].pNumProtons = NULL;
1533 : : }
1534 : : }
1535 : : }
1536 [ # # ]: 0 : if (pOneInput->atom)
1537 : : {
1538 [ # # ]: 0 : inchi_free(pOneInput->atom);
1539 : : }
1540 : :
1541 : 0 : FreeExtOrigAtData(pOneInput->polymer, pOneInput->v3000);
1542 : :
1543 : 0 : memset(pOneInput, 0, sizeof(*pOneInput)); /* djb-rwth: memset_s C11/Annex K variant? */
1544 : 0 : }
1545 : :
1546 : :
1547 : : /****************************************************************************/
1548 : 0 : int CompareAllOrigInchiToRevInChI(StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
1549 : : InpInChI* pOneInput,
1550 : : int bReqNonTaut,
1551 : : long num_inp,
1552 : : char* szCurHdr)
1553 : : {
1554 : 0 : int i, iInchiRec, iMobileH, iMobileHpStruct, num_components, iComponent, ret = 0; /* djb-rwth: ignoring LLVM warning: variable used to store function return value */
1555 : : COMPONENT_REM_PROTONS nCurRemovedProtons, nNumRemovedProtons;
1556 : : INChI* pInChI[TAUT_NUM];
1557 : : INCHI_MODE CompareInchiFlags[TAUT_NUM];
1558 : 0 : memset(pOneInput->CompareInchiFlags[0], 0, sizeof(pOneInput->CompareInchiFlags[0])); /* djb-rwth: memset_s C11/Annex K variant? */
1559 : 0 : memset(&nNumRemovedProtons, 0, sizeof(nNumRemovedProtons)); /* djb-rwth: memset_s C11/Annex K variant? */
1560 : :
1561 : : /* do we have reconnected InChI ?*/
1562 : 0 : iInchiRec = INCHI_REC;
1563 : 0 : iMobileH = TAUT_NON;
1564 [ # # # # ]: 0 : if (!pOneInput->nNumComponents[iInchiRec][TAUT_YES] && !pOneInput->nNumComponents[iInchiRec][TAUT_NON])
1565 : : {
1566 : 0 : iInchiRec = INCHI_BAS;
1567 : : }
1568 : : /* do we have Mobile or Fixed-H ? */
1569 [ # # # # ]: 0 : if (!pOneInput->nNumComponents[iInchiRec][TAUT_NON] || !bReqNonTaut)
1570 : : {
1571 : 0 : iMobileH = TAUT_YES; /* index for pOneInput */
1572 : : }
1573 : : /* if a restored structure has Fixed-H InChI then its mobile-H restored InChI is in Fixed-H pStruct */
1574 : 0 : num_components = pOneInput->nNumComponents[iInchiRec][iMobileH];
1575 [ # # ]: 0 : for (iComponent = 0; iComponent < num_components; iComponent++)
1576 : : {
1577 : 0 : int bMobileH = iMobileH;
1578 : 0 : pInChI[0] = pInChI[1] = NULL;
1579 [ # # ]: 0 : if (pOneInput->pInpInChI[iInchiRec][bMobileH][iComponent].nNumberOfAtoms &&
1580 [ # # ]: 0 : !pOneInput->pInpInChI[iInchiRec][bMobileH][iComponent].bDeleted)
1581 : : {
1582 : : /* the requested InChI layer exists */
1583 : 0 : pInChI[0] = &pOneInput->pInpInChI[iInchiRec][bMobileH][iComponent];
1584 [ # # ]: 0 : if (bMobileH == TAUT_NON)
1585 : : {
1586 : 0 : pInChI[1] = &pOneInput->pInpInChI[iInchiRec][TAUT_YES][iComponent];
1587 : : }
1588 : : }
1589 : : else
1590 : : {
1591 [ # # ]: 0 : if (bMobileH == TAUT_NON &&
1592 [ # # ]: 0 : pOneInput->pInpInChI[iInchiRec][TAUT_YES][iComponent].nNumberOfAtoms &&
1593 [ # # ]: 0 : !pOneInput->pInpInChI[iInchiRec][TAUT_YES][iComponent].bDeleted)
1594 : : {
1595 : : /* the requested Fixed-H InChI layer does not exist; however, the Mobile-H does exist */
1596 : 0 : bMobileH = TAUT_YES; /* only Mobile-H is available */
1597 : 0 : pInChI[0] = &pOneInput->pInpInChI[iInchiRec][bMobileH][iComponent];
1598 : : }
1599 : : }
1600 : 0 : memset(CompareInchiFlags, 0, sizeof(CompareInchiFlags)); /* djb-rwth: memset_s C11/Annex K variant? */
1601 : 0 : memset(&nCurRemovedProtons, 0, sizeof(nCurRemovedProtons)); /* djb-rwth: memset_s C11/Annex K variant? */
1602 : 0 : iMobileHpStruct =
1603 : : #if ( bRELEASE_VERSION == 0 )
1604 : : #ifndef TARGET_API_LIB
1605 : : /* legacy: reproduce old output */
1606 : : OldPrintCompareOneOrigInchiToRevInChI(pStruct[iInchiRec][bMobileH] + iComponent, pInChI, bMobileH,
1607 : : iComponent, num_inp, szCurHdr);
1608 : : #endif
1609 : : #endif
1610 : : /* one component comparison result bits */
1611 : 0 : ret = CompareOneOrigInchiToRevInChI(pStruct[iInchiRec][bMobileH] + iComponent, pInChI, bMobileH, iComponent,
1612 : : num_inp, szCurHdr, &nCurRemovedProtons, CompareInchiFlags);
1613 [ # # ]: 0 : if (ret >= 0)
1614 : : {
1615 : : /* no errors encountered -> accumulate removed protons from individual Mobile-H layers of components */
1616 : 0 : nNumRemovedProtons.nNumRemovedProtons += nCurRemovedProtons.nNumRemovedProtons;
1617 [ # # ]: 0 : for (i = 0; i < NUM_H_ISOTOPES; i++)
1618 : : {
1619 : 0 : nNumRemovedProtons.nNumRemovedIsotopicH[i] += nCurRemovedProtons.nNumRemovedIsotopicH[i];
1620 : : }
1621 : : /* accumulate compare bits */
1622 [ # # ]: 0 : for (i = 0; i < TAUT_NUM; i++)
1623 : : {
1624 : 0 : pOneInput->CompareInchiFlags[0][i] |= CompareInchiFlags[i];
1625 : : }
1626 : : }
1627 : : else
1628 : : {
1629 : 0 : goto exit_function;
1630 : : }
1631 : : }
1632 [ # # ]: 0 : if (iMobileH == TAUT_YES)
1633 : : {
1634 [ # # ]: 0 : if (pOneInput->nNumProtons[iInchiRec][iMobileH].pNumProtons)
1635 : : {
1636 : 0 : ret = RI_ERR_PROGR; /* in Mobile-H case proton balances are split between compoments */
1637 : : }
1638 : : else
1639 : : {
1640 : : /* num removed protons in orig. InChI num removed protons in restored InChi */
1641 [ # # ]: 0 : if (nNumRemovedProtons.nNumRemovedProtons != pOneInput->nNumProtons[iInchiRec][iMobileH].nNumRemovedProtons)
1642 : : {
1643 : : /* restored structure InChI has less or more removed protons */
1644 : 0 : pOneInput->CompareInchiFlags[0][TAUT_YES] |= INCHIDIFF_MOBH_PROTONS;
1645 : : #if ( bRELEASE_VERSION == 0 )
1646 : : /* debug output only */
1647 : : {
1648 : : int num_H_AddedByRevrs = pOneInput->nNumProtons[iInchiRec][iMobileH].nNumRemovedProtons
1649 : : - nNumRemovedProtons.nNumRemovedProtons;
1650 : : fprintf(stdout, "COMPARE_INCHI: %ld: %s %cM: Proton balance (Diff: %d, RevrsRem=%d)\n",
1651 : : num_inp, szCurHdr ? szCurHdr : "Struct", iInchiRec ? 'R' : 'D',
1652 : : pOneInput->nNumProtons[iInchiRec][iMobileH].nNumRemovedProtons, num_H_AddedByRevrs);
1653 : : }
1654 : : #endif
1655 : : }
1656 [ # # ]: 0 : for (i = 0; i < NUM_H_ISOTOPES; i++)
1657 : : {
1658 [ # # ]: 0 : if (nNumRemovedProtons.nNumRemovedIsotopicH[i] != pOneInput->nNumProtons[iInchiRec][TAUT_YES].nNumRemovedIsotopicH[i])
1659 : : {
1660 : 0 : pOneInput->CompareInchiFlags[0][TAUT_YES] |= INCHIDIFF_MOB_ISO_H;
1661 : : #if ( bRELEASE_VERSION == 0 )
1662 : : /* debug output only */
1663 : : {
1664 : : int num_H_AddedByRevrs = pOneInput->nNumProtons[iInchiRec][TAUT_YES].nNumRemovedIsotopicH[i]
1665 : : - nNumRemovedProtons.nNumRemovedIsotopicH[i];
1666 : : fprintf(stdout, "COMPARE_INCHI: %ld: %s %cM: Iso Xchg %dH balance (Diff: %d, RevrsRem=%d)\n",
1667 : : num_inp, szCurHdr ? szCurHdr : "Struct", iInchiRec ? 'R' : 'D', i + 1,
1668 : : pOneInput->nNumProtons[iInchiRec][TAUT_YES].nNumRemovedIsotopicH[i], num_H_AddedByRevrs);
1669 : : }
1670 : : #endif
1671 : : }
1672 : : }
1673 : : }
1674 : : }
1675 : :
1676 : 0 : exit_function:
1677 : :
1678 : 0 : return ret;
1679 : : }
1680 : :
1681 : :
1682 : : /****************************************************************************/
1683 : 0 : int CompareAllDisconnectedOrigInchiToRevInChI(StrFromINChI* pStruct[INCHI_NUM][TAUT_NUM],
1684 : : InpInChI* pOneInput,
1685 : : int bHasSomeFixedH,
1686 : : long num_inp,
1687 : : char* szCurHdr)
1688 : : {
1689 : : int i, k, m, n, iInChI, iMobileH, bMobileH, ifk;
1690 : : int num_components_D, num_components_R;
1691 : : int nNumCompHaveSeparateProtons_D, nNumCompHaveSeparateProtons_R;
1692 : : int num_fragments_D, num_fragments_R, num_fragments_DR, num_fragments, iComponent, ret;
1693 : : int ifInChI, ifMobileH, bfMobileH, nLink;
1694 : : COMPONENT_REM_PROTONS nNumRemovedProtons_D; /* removed from the disconnected layer of the Input InChI */
1695 : : COMPONENT_REM_PROTONS nNumRemovedProtons_D_all; /* if only totals are avalable */
1696 : : COMPONENT_REM_PROTONS nNumRemovedProtons_R; /* removed from disconnected layer of the reconstructed struct */
1697 : : COMPONENT_REM_PROTONS nNumRemovedProtons_R_all;
1698 : : INCHI_MODE CompareInchiFlags[TAUT_NUM];
1699 : : StrFromINChI* pStruct1;
1700 : : INChI_Aux* pINChI_Aux;
1701 : 0 : INCHI_SORT* pINChISort1 = NULL; /* from reversed structure */
1702 : 0 : INCHI_SORT* pINChISort2 = NULL; /* original input InChI */
1703 : 0 : int nNumNonTaut1 = 0, nNumNonTaut2 = 0;
1704 : :
1705 : 0 : ret = 0;
1706 : 0 : memset(pOneInput->CompareInchiFlags[1], 0, sizeof(pOneInput->CompareInchiFlags[1])); /* djb-rwth: memset_s C11/Annex K variant? */
1707 : :
1708 : : /* count components that are not subject to disconnection */
1709 [ # # ]: 0 : if (!pOneInput->nNumComponents[INCHI_REC][TAUT_YES] &&
1710 [ # # ]: 0 : !pOneInput->nNumComponents[INCHI_REC][TAUT_NON])
1711 : : {
1712 : 0 : return 0; /* nothing to do */
1713 : : }
1714 : :
1715 : 0 : memset(&nNumRemovedProtons_D, 0, sizeof(nNumRemovedProtons_D)); /* djb-rwth: memset_s C11/Annex K variant? */
1716 : 0 : memset(&nNumRemovedProtons_R, 0, sizeof(nNumRemovedProtons_R)); /* djb-rwth: memset_s C11/Annex K variant? */
1717 : 0 : memset(&nNumRemovedProtons_D_all, 0, sizeof(nNumRemovedProtons_D_all)); /* djb-rwth: memset_s C11/Annex K variant? */
1718 : 0 : memset(&nNumRemovedProtons_R_all, 0, sizeof(nNumRemovedProtons_R_all)); /* djb-rwth: memset_s C11/Annex K variant? */
1719 : 0 : memset(CompareInchiFlags, 0, sizeof(CompareInchiFlags)); /* djb-rwth: memset_s C11/Annex K variant? */
1720 : :
1721 : 0 : num_components_D = inchi_max(pOneInput->nNumComponents[INCHI_BAS][TAUT_YES],
1722 : : pOneInput->nNumComponents[INCHI_BAS][TAUT_NON]);
1723 : 0 : num_components_R = inchi_max(pOneInput->nNumComponents[INCHI_REC][TAUT_YES],
1724 : : pOneInput->nNumComponents[INCHI_REC][TAUT_NON]);
1725 : :
1726 : : /***********************************************************************************************/
1727 : : /* InpInChI: count fragments -- disconnected components that do not match reconnected */
1728 : : /* Accumulate removed H and isotopic H from ALL Fixed-H disconnected components except deleted */
1729 : : /* This segment collects info from the original InChI */
1730 : : /***********************************************************************************************/
1731 : : /*---- Original InChI ----*/
1732 : :
1733 : 0 : num_fragments_D = 0;
1734 : 0 : iInChI = INCHI_BAS;
1735 [ # # # # ]: 0 : iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
1736 : 0 : nNumCompHaveSeparateProtons_D = 0;
1737 : :
1738 : : /* in case of Mobile-H components here are the proton totals from the original InChI disconn. layer */
1739 : 0 : nNumRemovedProtons_D.nNumRemovedProtons = pOneInput->nNumProtons[iInChI][TAUT_YES].nNumRemovedProtons;
1740 : 0 : memcpy(nNumRemovedProtons_D.nNumRemovedIsotopicH,
1741 : 0 : pOneInput->nNumProtons[iInChI][TAUT_YES].nNumRemovedIsotopicH,
1742 : : sizeof(nNumRemovedProtons_D.nNumRemovedIsotopicH)); /* total for the disconnected layer */
1743 [ # # ]: 0 : for (k = 0; k < num_components_D; k++)
1744 : : {
1745 : 0 : bMobileH = iMobileH;
1746 [ # # ]: 0 : if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
1747 : : {
1748 [ # # ]: 0 : if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
1749 : : {
1750 : 0 : bMobileH = TAUT_YES;
1751 : : }
1752 : : else
1753 : : {
1754 : 0 : continue; /* component is missing ??? */
1755 : : }
1756 : : }
1757 [ # # ]: 0 : if (0 > (nLink = pOneInput->pInpInChI[iInChI][bMobileH][k].nLink))
1758 : : {
1759 : : /* component in Disconnected layer is linked to the identical one in the Reconnected layer */
1760 [ # # ]: 0 : if (pOneInput->nNumProtons[INCHI_REC][TAUT_YES].pNumProtons)
1761 : : {
1762 : 0 : nNumCompHaveSeparateProtons_D++;
1763 : 0 : nLink = -(1 + nLink);
1764 : 0 : nNumRemovedProtons_D.nNumRemovedProtons += pOneInput->nNumProtons[INCHI_REC][TAUT_YES].pNumProtons[nLink].nNumRemovedProtons;
1765 [ # # ]: 0 : for (m = 0; m < NUM_H_ISOTOPES; m++)
1766 : : {
1767 : 0 : nNumRemovedProtons_D.nNumRemovedIsotopicH[m] += pOneInput->nNumProtons[INCHI_REC][TAUT_YES].pNumProtons[nLink].nNumRemovedIsotopicH[m];
1768 : : }
1769 : : }
1770 : 0 : continue; /* same as reconnected */
1771 : : }
1772 : : /* component in the reconnected layer that was disconnected */
1773 : 0 : nNumNonTaut2 += (bMobileH == TAUT_NON);
1774 [ # # ]: 0 : if (pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons)
1775 : : {
1776 : 0 : nNumCompHaveSeparateProtons_D++;
1777 : 0 : nNumRemovedProtons_D.nNumRemovedProtons += pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons[k].nNumRemovedProtons;
1778 [ # # ]: 0 : for (m = 0; m < NUM_H_ISOTOPES; m++)
1779 : : {
1780 : 0 : nNumRemovedProtons_D.nNumRemovedIsotopicH[m] += pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons[k].nNumRemovedIsotopicH[m];
1781 : : }
1782 : : }
1783 : 0 : num_fragments_D++; /* number of disconnected fragments from original reconnected structure */
1784 : : }
1785 : : /* in case of Mobile-H components here are the proton totals from the original InChI */
1786 : : /*
1787 : : nNumRemovedProtons_D_all.nNumRemovedProtons = pOneInput->nNumProtons[iInChI][TAUT_YES].nNumRemovedProtons;
1788 : : memcpy( nNumRemovedProtons_D_all.nNumRemovedIsotopicH,
1789 : : pOneInput->nNumProtons[iInChI][TAUT_YES].nNumRemovedIsotopicH,
1790 : : sizeof(nNumRemovedProtons_D_all.nNumRemovedIsotopicH) );
1791 : :
1792 : : */
1793 : : /****************************************************************************************************/
1794 : : /* count fragments in reconstructed reconnected structure */
1795 : : /* accumulate removed H and isotopic H from ALL reconstructed reconnected components except deleted */
1796 : : /* This segment collects info from the reconstructed structure InChI */
1797 : : /****************************************************************************************************/
1798 : : /*---- InChI from the reconstructed reconnected structure ----*/
1799 : 0 : num_fragments_R = 0;
1800 : 0 : iInChI = INCHI_REC;
1801 [ # # # # ]: 0 : iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
1802 : 0 : nNumCompHaveSeparateProtons_R = 0;
1803 [ # # ]: 0 : for (k = 0; k < num_components_R; k++)
1804 : : {
1805 : 0 : bMobileH = iMobileH;
1806 [ # # ]: 0 : if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
1807 : : {
1808 [ # # ]: 0 : if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
1809 : : {
1810 : 0 : bMobileH = TAUT_YES;
1811 : : }
1812 : : else
1813 : : {
1814 : 0 : continue; /* component is missing ??? (Deleted proton in Mobile-H layer) */
1815 : : }
1816 : : }
1817 [ # # ]: 0 : if (0 < pOneInput->pInpInChI[iInChI][bMobileH][k].nLink)
1818 : : {
1819 : : /* this reconstructed reconnected component was NOT DISCONNECTED */
1820 : : /* same component is in the disconnected layer, it has no metal atoms or is an isolated metal atom */
1821 : 0 : pStruct1 = pStruct[iInChI][bMobileH] + k;
1822 : 0 : ifMobileH = TAUT_YES; /* Mobile-H Aux_Info contains number removed protons */
1823 : 0 : ifInChI = INCHI_BAS; /* this component cannot be reconnected */
1824 : 0 : ifk = 0; /* 0th component since it is InChI of a single component */
1825 : : /* The statement in the following line is *WRONG*, component number mixed with bMobileH: */
1826 : : /* in RevInchi, when only Mobile-H is present then its only non-NULL InChI has index 0==TAUT_NON */
1827 [ # # ]: 0 : if (bRevInchiComponentExists(pStruct1, ifInChI, ifMobileH, ifk))
1828 : : {
1829 : : /* count protons */
1830 : 0 : pINChI_Aux = pStruct1->RevInChI.pINChI_Aux[ifInChI][ifk][ifMobileH];
1831 [ # # ]: 0 : if (pINChI_Aux)
1832 : : {
1833 : 0 : nNumRemovedProtons_R.nNumRemovedProtons += pINChI_Aux->nNumRemovedProtons;
1834 [ # # ]: 0 : for (m = 0; m < NUM_H_ISOTOPES; m++)
1835 : : {
1836 : 0 : nNumRemovedProtons_R.nNumRemovedIsotopicH[m] += pINChI_Aux->nNumRemovedIsotopicH[m];
1837 : : }
1838 : : }
1839 : : }
1840 [ # # ]: 0 : nNumCompHaveSeparateProtons_R += bRevInchiComponentExists(pStruct1, ifInChI, ALT_TAUT(ifMobileH), ifk);
1841 : 0 : continue; /* same as disconnected, has no metal atoms */
1842 : : }
1843 : : /* this reconstructed reconnected component WAS DISCONNECTED; check its fragments */
1844 : : /* it does not have same component in the disconnected layer */
1845 : 0 : pStruct1 = pStruct[iInChI][bMobileH] + k;
1846 : 0 : num_fragments = pStruct1->RevInChI.num_components[INCHI_BAS];
1847 : 0 : ifInChI = INCHI_BAS; /* disconnected layer */
1848 : 0 : ifMobileH = bHasSomeFixedH ? TAUT_NON : TAUT_YES;
1849 [ # # ]: 0 : for (ifk = 0; ifk < num_fragments; ifk++)
1850 : : {
1851 : 0 : bfMobileH = ifMobileH;
1852 [ # # ]: 0 : if (!bRevInchiComponentExists(pStruct1, ifInChI, bfMobileH, ifk))
1853 : : {
1854 [ # # ]: 0 : if (bRevInchiComponentExists(pStruct1, ifInChI, TAUT_YES, ifk))
1855 : : {
1856 : 0 : bfMobileH = TAUT_YES;
1857 : : }
1858 : : else
1859 : : {
1860 : 0 : continue; /* fragment does not exist ??? */
1861 : : }
1862 : : }
1863 : 0 : nNumNonTaut1 += (bfMobileH == TAUT_NON);
1864 : 0 : nNumCompHaveSeparateProtons_R += (bfMobileH == TAUT_NON);
1865 : : /* count protons from fragments made by metal disconnection */
1866 : 0 : pINChI_Aux = pStruct1->RevInChI.pINChI_Aux[ifInChI][ifk][TAUT_YES];
1867 [ # # ]: 0 : if (pINChI_Aux)
1868 : : {
1869 : 0 : nNumRemovedProtons_R.nNumRemovedProtons += pINChI_Aux->nNumRemovedProtons;
1870 [ # # ]: 0 : for (m = 0; m < NUM_H_ISOTOPES; m++)
1871 : : {
1872 : 0 : nNumRemovedProtons_R.nNumRemovedIsotopicH[m] += pINChI_Aux->nNumRemovedIsotopicH[m];
1873 : : }
1874 : : }
1875 : 0 : num_fragments_R++; /* number of disconnected fragments from reconstructed reconnected structure */
1876 : : }
1877 : : }
1878 : :
1879 : : /*---------------- special treatment of the last reconstructed component -----------------*/
1880 : : /*---------------- this may contain separate protons added by the reconstruction ---------*/
1881 : 0 : k = num_components_R - 1;
1882 : 0 : pStruct1 = pStruct[iInChI][iMobileH] + k;
1883 [ # # # # : 0 : if (iMobileH == TAUT_YES && !bHasSomeFixedH &&
# # ]
1884 : 0 : bInpInchiComponentDeleted(pOneInput, iInChI, iMobileH, k) &&
1885 [ # # ]: 0 : (num_fragments = pStruct1->RevInChI.num_components[INCHI_BAS]))
1886 : : {
1887 : :
1888 : 0 : ifInChI = INCHI_BAS; /* disconnected layer */
1889 : 0 : ifMobileH = TAUT_YES;
1890 [ # # ]: 0 : for (ifk = 0; ifk < num_fragments; ifk++)
1891 : : {
1892 : 0 : bfMobileH = ifMobileH;
1893 [ # # ]: 0 : if (!bRevInchiComponentDeleted(pStruct1, ifInChI, bfMobileH, ifk))
1894 : : {
1895 : 0 : continue; /* fragment does exist ??? Should not happen */
1896 : : }
1897 : : /*
1898 : : nNumNonTaut1 += (bfMobileH == TAUT_NON);
1899 : : nNumCompHaveSeparateProtons_R += (bfMobileH == TAUT_NON);
1900 : : */
1901 : : /* count protons from fragments made by metal disconnection */
1902 : 0 : pINChI_Aux = pStruct1->RevInChI.pINChI_Aux[ifInChI][ifk][TAUT_YES];
1903 [ # # ]: 0 : if (pINChI_Aux)
1904 : : {
1905 : 0 : nNumRemovedProtons_R.nNumRemovedProtons += pINChI_Aux->nNumRemovedProtons;
1906 [ # # ]: 0 : for (m = 0; m < NUM_H_ISOTOPES; m++)
1907 : : {
1908 : 0 : nNumRemovedProtons_R.nNumRemovedIsotopicH[m] += pINChI_Aux->nNumRemovedIsotopicH[m];
1909 : : }
1910 : : }
1911 : : /*num_fragments_R ++;*/ /* number of disconnected fragments from reconstructed reconnected structure */
1912 : : }
1913 : : }
1914 : :
1915 : 0 : num_fragments_DR = inchi_max(num_fragments_D, num_fragments_R);
1916 : : /* in case of correct reconstruction, num_fragments_D, num_fragments_R */
1917 [ # # ]: 0 : if (!num_fragments_DR)
1918 : : {
1919 : 0 : return 0; /* no component was disconnected */
1920 : : }
1921 [ # # ]: 0 : if (num_fragments_D != num_fragments_R)
1922 : : {
1923 [ # # ]: 0 : for (i = 0; i < TAUT_NUM; i++)
1924 : : {
1925 [ # # ]: 0 : if (pOneInput->nNumComponents[INCHI_BAS][i])
1926 : : {
1927 : 0 : pOneInput->CompareInchiFlags[1][i] |= INCHIDIFF_PROBLEM;
1928 : : }
1929 : : }
1930 : 0 : return 1; /* severe error */
1931 : : }
1932 : :
1933 : 0 : pINChISort1 = (INCHI_SORT*)inchi_calloc(num_fragments_DR, sizeof(pINChISort1[0]));
1934 : 0 : pINChISort2 = (INCHI_SORT*)inchi_calloc(num_fragments_DR, sizeof(pINChISort2[0]));
1935 [ # # # # ]: 0 : if (!pINChISort1 || !pINChISort2)
1936 : : {
1937 : 0 : ret = RI_ERR_ALLOC;
1938 : 0 : goto exit_function;
1939 : : }
1940 : :
1941 : : /* accumulate original InChI of fragments -- disconnected components that do not match reconnected */
1942 : 0 : iInChI = INCHI_BAS;
1943 [ # # # # ]: 0 : iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
1944 [ # # ]: 0 : for (k = n = 0; k < num_components_D; k++)
1945 : : {
1946 : 0 : bMobileH = iMobileH;
1947 [ # # ]: 0 : if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
1948 : : {
1949 [ # # ]: 0 : if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
1950 : : {
1951 : 0 : bMobileH = TAUT_YES;
1952 : : }
1953 : : else
1954 : : {
1955 : 0 : continue; /* component is missing ??? (Deleted proton in Mobile-H layer) */
1956 : : }
1957 : : }
1958 [ # # ]: 0 : if (0 > pOneInput->pInpInChI[iInChI][bMobileH][k].nLink)
1959 : : {
1960 : 0 : continue; /* same as reconnected */
1961 : : }
1962 : : /* the component exists in disconnected layer of the orig. InChI only: it is a fragment */
1963 : 0 : pINChISort2[n].pINChI[bMobileH] = pOneInput->pInpInChI[iInChI][bMobileH] + k;
1964 [ # # # # ]: 0 : if (bMobileH == TAUT_NON &&
1965 [ # # ]: 0 : (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k) ||
1966 : 0 : bInpInchiComponentDeleted(pOneInput, iInChI, TAUT_YES, k)))
1967 : : {
1968 : 0 : pINChISort2[n].pINChI[TAUT_YES] = pOneInput->pInpInChI[iInChI][TAUT_YES] + k;
1969 : : }
1970 : : /* the last sort key is a number of removed protons */
1971 [ # # ]: 0 : pINChISort2[n].ord_number = pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons ?
1972 : 0 : pOneInput->nNumProtons[iInChI][TAUT_YES].pNumProtons[k].nNumRemovedProtons : 0;
1973 : 0 : pINChISort2[n].n1 = k; /* orig. InChI disconnected layer component number */
1974 : 0 : pINChISort2[n].n2 = -1; /* no fragment index */
1975 : 0 : n++;
1976 : : }
1977 : :
1978 : : /* accumulate fragments from the reconstructed structure */
1979 : 0 : iInChI = INCHI_REC;
1980 [ # # # # ]: 0 : iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
1981 [ # # ]: 0 : for (k = n = 0; k < num_components_R; k++)
1982 : : {
1983 : 0 : bMobileH = iMobileH;
1984 [ # # ]: 0 : if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
1985 : : {
1986 [ # # ]: 0 : if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
1987 : : {
1988 : 0 : bMobileH = TAUT_YES;
1989 : : }
1990 : : else
1991 : : {
1992 : 0 : continue; /* component is missing ??? (Deleted proton in Mobile-H layer) */
1993 : : }
1994 : : }
1995 : : /* the reconstructed structure */
1996 [ # # ]: 0 : if (0 < pOneInput->pInpInChI[iInChI][bMobileH][k].nLink)
1997 : : {
1998 : 0 : continue; /* same as disconnected, has no metal atoms */
1999 : : }
2000 : : /* this reconstructed structure was disconnected */
2001 : 0 : pStruct1 = pStruct[iInChI][bMobileH] + k;
2002 : 0 : num_fragments = pStruct1->RevInChI.num_components[INCHI_BAS];
2003 : 0 : ifInChI = INCHI_BAS;
2004 : 0 : ifMobileH = bHasSomeFixedH ? TAUT_NON : TAUT_YES;
2005 [ # # ]: 0 : for (i = 0; i < num_fragments; i++)
2006 : : {
2007 : 0 : bfMobileH = ifMobileH;
2008 [ # # ]: 0 : if (!bRevInchiComponentExists(pStruct1, ifInChI, bfMobileH, i))
2009 : : {
2010 [ # # ]: 0 : if (bRevInchiComponentExists(pStruct1, ifInChI, TAUT_YES, i))
2011 : : {
2012 : 0 : bfMobileH = TAUT_YES;
2013 : : }
2014 : : else
2015 : : {
2016 : 0 : continue; /* component is missing ??? */
2017 : : }
2018 : : }
2019 : 0 : pINChISort1[n].pINChI[bfMobileH] = pStruct1->RevInChI.pINChI[ifInChI][i][bfMobileH];
2020 [ # # ]: 0 : if (bfMobileH == TAUT_NON /*&& bRevInchiComponentExists( pStruct1, ifInChI, TAUT_YES, i )*/)
2021 : : {
2022 : 0 : pINChISort1[n].pINChI[TAUT_YES] = pStruct1->RevInChI.pINChI[ifInChI][i][TAUT_YES];
2023 : : /* remove Fixed-H InChI if is is identical to Mobile-H */
2024 : : /* do it exactly same way the identical components were removed from InpInChI */
2025 [ # # ]: 0 : if (!CompareReversedINChI(pINChISort1[n].pINChI[bfMobileH],
2026 : 0 : pINChISort1[n].pINChI[TAUT_YES], NULL, NULL))
2027 : : {
2028 : 0 : pINChISort1[n].pINChI[bfMobileH] = NULL; /* remove Fixed-H layer */
2029 : : }
2030 : : else
2031 : : {
2032 : 0 : pINChISort1[n].ord_number = pStruct1->RevInChI.pINChI_Aux[ifInChI][i][TAUT_YES]->nNumRemovedProtons;
2033 : : }
2034 : : }
2035 : :
2036 : 0 : pINChISort1[n].n1 = k; /* reconstructed reconnected structure component index */
2037 : 0 : pINChISort1[n].n2 = i; /* index of a fragment made out of this component */
2038 : 0 : n++;
2039 : : }
2040 : : }
2041 : :
2042 : : /* sort fragment InChI before comparing them */
2043 : 0 : qsort(pINChISort1, num_fragments_D, sizeof(pINChISort1[0]), CompINChITaut2);
2044 : 0 : qsort(pINChISort2, num_fragments_R, sizeof(pINChISort2[0]), CompINChITaut2);
2045 : :
2046 : : /* compare fragments -- components present in disconnected layer only */
2047 [ # # ]: 0 : for (iComponent = 0; iComponent < num_fragments_DR; iComponent++)
2048 : : {
2049 : : INChI* pInChI1[TAUT_NUM]; /* from reversed structure */
2050 : : INChI* pInChI2[TAUT_NUM]; /* original input InChI */
2051 [ # # ]: 0 : for (i = 0; i < TAUT_NUM; i++)
2052 : : {
2053 : 0 : pInChI1[i] = pINChISort1[iComponent].pINChI[i];
2054 : 0 : pInChI2[i] = pINChISort2[iComponent].pINChI[i];
2055 : : }
2056 : 0 : CompareTwoPairsOfInChI(pInChI1, pInChI2, !bHasSomeFixedH, CompareInchiFlags);
2057 : : }
2058 : :
2059 [ # # ]: 0 : if ( /*nNumNonTaut1 && nNumNonTaut2 &&*/ bHasSomeFixedH)
2060 : : {
2061 [ # # # # ]: 0 : if (nNumCompHaveSeparateProtons_D || nNumCompHaveSeparateProtons_R)
2062 : : {
2063 : : /* for each component, compare number removed protons */
2064 : : /* comparison does not make sense if Disconnected Fixed-H layer is not present */
2065 [ # # ]: 0 : for (iComponent = 0; iComponent < num_fragments_DR; iComponent++)
2066 : : {
2067 : : NUM_H nNumRemovedIsotopicH1[NUM_H_ISOTOPES];
2068 : : NUM_H nNumRemovedIsotopicH2[NUM_H_ISOTOPES];
2069 : :
2070 : 0 : memset(nNumRemovedIsotopicH1, 0, sizeof(nNumRemovedIsotopicH1)); /* djb-rwth: memset_s C11/Annex K variant? */
2071 : 0 : memset(nNumRemovedIsotopicH2, 0, sizeof(nNumRemovedIsotopicH2)); /* djb-rwth: memset_s C11/Annex K variant? */
2072 : : /* compare removed protons */
2073 [ # # ]: 0 : if (pINChISort1[iComponent].ord_number != pINChISort2[iComponent].ord_number)
2074 : : {
2075 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_MOBH_PROTONS; /* diff number of removed protons */
2076 : : }
2077 : : /* also compare removed isotopic atoms H */
2078 : 0 : k = pINChISort2[iComponent].n1; /* input InChI, OneInput */
2079 [ # # ]: 0 : if (pOneInput->nNumProtons[INCHI_BAS][TAUT_YES].pNumProtons)
2080 : : {
2081 : 0 : memcpy(nNumRemovedIsotopicH2,
2082 : 0 : pOneInput->nNumProtons[INCHI_BAS][TAUT_YES].pNumProtons[k].nNumRemovedIsotopicH,
2083 : : sizeof(nNumRemovedIsotopicH2));
2084 : : }
2085 : : /* get fragments of reconstructed structure removed protons info */
2086 : 0 : k = pINChISort1[iComponent].n1; /* restored component number */
2087 : 0 : i = pINChISort1[iComponent].n2; /* subcomponent number */
2088 : 0 : iInChI = INCHI_REC;
2089 [ # # # # ]: 0 : iMobileH = bHasSomeFixedH ? !pOneInput->nNumComponents[iInChI][TAUT_NON] : TAUT_YES;
2090 : 0 : bMobileH = iMobileH;
2091 [ # # ]: 0 : if (!bInpInchiComponentExists(pOneInput, iInChI, bMobileH, k))
2092 : : {
2093 [ # # ]: 0 : if (bInpInchiComponentExists(pOneInput, iInChI, TAUT_YES, k))
2094 : : {
2095 : 0 : bMobileH = TAUT_YES;
2096 : : }
2097 : : else
2098 : : {
2099 : 0 : goto compare_iso_H;
2100 : : }
2101 : : }
2102 [ # # ]: 0 : if (pOneInput->pInpInChI[iInChI][bMobileH][k].nLink)
2103 : : {
2104 : 0 : continue;
2105 : : /*
2106 : : ret = RI_ERR_PROGR;
2107 : : goto exit_function;
2108 : : */
2109 : : }
2110 : 0 : pStruct1 = pStruct[iInChI][bMobileH] + k;
2111 : 0 : num_fragments = pStruct1->RevInChI.num_components[INCHI_BAS];
2112 : 0 : ifInChI = INCHI_BAS;
2113 : 0 : ifMobileH = bHasSomeFixedH ? TAUT_NON : TAUT_YES;
2114 [ # # ]: 0 : if (i < num_fragments)
2115 : : {
2116 : 0 : bfMobileH = ifMobileH;
2117 [ # # ]: 0 : if (!bRevInchiComponentExists(pStruct1, ifInChI, bfMobileH, i))
2118 : : {
2119 [ # # ]: 0 : if (!bRevInchiComponentExists(pStruct1, ifInChI, TAUT_YES, i))
2120 : : /* djb-rwth: removing redundant code */
2121 : : {
2122 : 0 : goto compare_iso_H;
2123 : : }
2124 : : }
2125 : 0 : memcpy(nNumRemovedIsotopicH1,
2126 : 0 : pStruct1->RevInChI.pINChI_Aux[ifInChI][i][TAUT_YES]->nNumRemovedIsotopicH,
2127 : : sizeof(nNumRemovedIsotopicH1));
2128 : : }
2129 : 0 : compare_iso_H:
2130 [ # # ]: 0 : if (memcmp(nNumRemovedIsotopicH1, nNumRemovedIsotopicH2, sizeof(nNumRemovedIsotopicH1)))
2131 : : {
2132 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_REM_ISO_H;
2133 : : }
2134 : : }
2135 : : }
2136 : : }
2137 : : else /*if ( !nNumNonTaut1 && !nNumNonTaut2 || !bHasSomeFixedH )*/
2138 : : {
2139 : : /* compare totals for removed protons and isotopic H */
2140 : 0 : if (pOneInput->nNumProtons[INCHI_BAS][TAUT_YES].nNumRemovedProtons !=
2141 [ # # ]: 0 : nNumRemovedProtons_R.nNumRemovedProtons)
2142 : : {
2143 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_MOBH_PROTONS;
2144 : : }
2145 [ # # ]: 0 : if (memcmp(pOneInput->nNumProtons[INCHI_BAS][TAUT_YES].nNumRemovedIsotopicH,
2146 : : nNumRemovedProtons_R.nNumRemovedIsotopicH,
2147 : : sizeof(nNumRemovedProtons_R.nNumRemovedIsotopicH)))
2148 : : {
2149 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_REM_ISO_H;
2150 : : }
2151 : : }
2152 : :
2153 [ # # ]: 0 : if (!nNumNonTaut1 == !nNumNonTaut2)
2154 : : {
2155 : : ; /* difference if(nNumNonTaut1 != nNumNonTaut2) will be caught in InChI comparison */
2156 : : }
2157 : : else
2158 : : {
2159 [ # # ]: 0 : if (nNumNonTaut1)
2160 : : {
2161 : : /* reconstructed has Fixed-H while the original has not: extra Fixed-H layer */
2162 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_WRONG_TAUT;
2163 : : }
2164 : : else
2165 : : {
2166 : : /* the original InChI has Fixed-H while the reconstructed one has not: missing Fixed-H layer */
2167 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_NO_TAUT;
2168 : : }
2169 : : }
2170 [ # # ]: 0 : for (i = 0; i < TAUT_NUM; i++)
2171 : : {
2172 : 0 : pOneInput->CompareInchiFlags[1][i] |= CompareInchiFlags[i];
2173 : : }
2174 : :
2175 : : /* compare totals */
2176 [ # # ]: 0 : if (nNumRemovedProtons_R.nNumRemovedProtons != nNumRemovedProtons_D.nNumRemovedProtons)
2177 : : {
2178 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_MOBH_PROTONS; /* diff number of removed protons */
2179 : : }
2180 [ # # ]: 0 : if (memcmp(nNumRemovedProtons_R.nNumRemovedIsotopicH,
2181 : : nNumRemovedProtons_D.nNumRemovedIsotopicH,
2182 : : sizeof(nNumRemovedProtons_D.nNumRemovedIsotopicH)))
2183 : : {
2184 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_REM_ISO_H;
2185 : : }
2186 : :
2187 : 0 : exit_function:
2188 : :
2189 [ # # ]: 0 : if (pINChISort1)
2190 : : {
2191 [ # # ]: 0 : inchi_free(pINChISort1);
2192 : : }
2193 [ # # ]: 0 : if (pINChISort2)
2194 : : {
2195 [ # # ]: 0 : inchi_free(pINChISort2);
2196 : : }
2197 : :
2198 : 0 : return ret;
2199 : : }
2200 : :
2201 : :
2202 : : /****************************************************************************/
2203 : 0 : int CompareTwoPairsOfInChI(INChI* pInChI1[TAUT_NUM],
2204 : : INChI* pInChI2[TAUT_NUM],
2205 : : int bMobileH,
2206 : : INCHI_MODE CompareInchiFlags[])
2207 : : {
2208 : 0 : int iMobileH, err = 0;
2209 : : INCHI_MODE cmp;
2210 [ # # ]: 0 : for (iMobileH = 0; iMobileH < TAUT_NUM; iMobileH++)
2211 : : {
2212 [ # # ]: 0 : if (!pInChI1[iMobileH] != !pInChI2[iMobileH])
2213 : : {
2214 [ # # ]: 0 : if (iMobileH == TAUT_NON &&
2215 [ # # # # ]: 0 : pInChI1[TAUT_YES] && pInChI2[TAUT_YES]) /* djb-rwth: condition corrected */
2216 : : {
2217 : 0 : CompareInchiFlags[iMobileH] |= INCHIDIFF_COMP_HLAYER;
2218 : : }
2219 : : else
2220 : : {
2221 : 0 : CompareInchiFlags[iMobileH] |= INCHIDIFF_COMP_NUMBER;
2222 : : }
2223 : 0 : continue;
2224 : : }
2225 [ # # # # ]: 0 : if (pInChI1[iMobileH] && pInChI2[iMobileH])
2226 : : {
2227 : 0 : cmp = CompareReversedINChI3(pInChI1[iMobileH], pInChI2[iMobileH], NULL, NULL, &err);
2228 [ # # ]: 0 : if (cmp)
2229 : : {
2230 : 0 : CompareInchiFlags[iMobileH] |= cmp;
2231 : : }
2232 : : }
2233 : : }
2234 : :
2235 : 0 : return err;
2236 : : }
2237 : :
2238 : :
2239 : : /****************************************************************************/
2240 : 0 : int CompareOneOrigInchiToRevInChI(StrFromINChI* pStruct,
2241 : : INChI* pInChI[TAUT_NUM],
2242 : : int bMobileH,
2243 : : int iComponent,
2244 : : long num_inp,
2245 : : char* szCurHdr,
2246 : : COMPONENT_REM_PROTONS* nCurRemovedProtons,
2247 : : INCHI_MODE CompareInchiFlags[])
2248 : : {
2249 : 0 : int ret, err = 0;
2250 : : INCHI_MODE cmp;
2251 : :
2252 [ # # ]: 0 : if (pStruct) /* djb-rwth: fixing coverity ID #499601 */
2253 : : {
2254 : 0 : ret = pStruct->RevInChI.nRetVal;
2255 : : }
2256 : : else
2257 : : {
2258 : 0 : ret = -1;
2259 : : }
2260 : :
2261 [ # # # # : 0 : if ((ret == _IS_OKAY || ret == _IS_WARNING) && pStruct) /* djb-rwth: fixing a NULL pointer dereference */
# # ]
2262 : 0 : {
2263 : : /* ignore bMobileH for now */
2264 : : int i, i0, b /* created type */, b0 /* requested type*/, j, k;
2265 : : /* pINChI[iINCHI][iComponent][bTaut] */
2266 : : /* i0 = requested Rec/Disconnected: 1/0 */
2267 : : /* i = what InChI creaded out of the restored structure */
2268 : : /* b0 = requested Mobile/Fixed-H: 1/0 */
2269 : : /* b = what InChI creaded out of the restored structure */
2270 : 0 : i = i0 = pStruct->iINCHI;
2271 : 0 : b = b0 = pStruct->iMobileH;
2272 [ # # # # ]: 0 : if (i == INCHI_REC && !pStruct->RevInChI.num_components[i])
2273 : : {
2274 : 0 : i = INCHI_BAS;
2275 : : }
2276 [ # # # # ]: 0 : if (b == TAUT_NON && (!pStruct->RevInChI.pINChI[i] ||
2277 [ # # ]: 0 : !pStruct->RevInChI.pINChI[i][0][b] ||
2278 [ # # ]: 0 : !pStruct->RevInChI.pINChI[i][0][b]->nNumberOfAtoms))
2279 : : {
2280 : 0 : b = TAUT_YES;
2281 : : }
2282 [ # # # # : 0 : if (pStruct->bDeleted && (!pInChI[0] || pInChI[0]->bDeleted))
# # ]
2283 : : {
2284 : 0 : return 0;
2285 : : }
2286 : :
2287 [ # # ]: 0 : if (pStruct->RevInChI.pINChI[i]) /* djb-rwth: fixing a NULL pointer dereference */
2288 : : {
2289 [ # # ]: 0 : if ((pStruct->RevInChI.num_components[i] > 1 &&
2290 [ # # ]: 0 : !pStruct->RevInChI.pINChI[i][1][b]->bDeleted) ||
2291 [ # # ]: 0 : pStruct->RevInChI.num_components[i] < 1) /* djb-rwth: addressing LLVM warning */
2292 : : {
2293 : 0 : CompareInchiFlags[bMobileH] |= INCHIDIFF_COMP_NUMBER;
2294 : : }
2295 : : }
2296 [ # # # # : 0 : if (b != b0 || b != bMobileH || b0 != bMobileH || i > i0)
# # # # ]
2297 : : {
2298 : : /* do not print messages about TAUT_YES instead of TAUT_NON */
2299 : 0 : CompareInchiFlags[bMobileH] |= INCHIDIFF_COMP_HLAYER;
2300 : : }
2301 : :
2302 [ # # # # ]: 0 : if (pStruct->RevInChI.num_components[i] && pStruct->RevInChI.pINChI[i]) /* djb-rwth: fixing a NULL pointer dereference */
2303 : : {
2304 : : /* compare InChI from restored structure; '0' in [i][0][b] is the first component */
2305 [ # # # # : 0 : if (b == TAUT_YES && pStruct->RevInChI.pINChI[i][0][b]->bDeleted && ( !pInChI[0] || pInChI[0]->bDeleted ))
# # # # ]
2306 : : {
2307 : : /* the 1st component is made out of proton(s) and the input component is missing or also a proton */
2308 : 0 : cmp = 0;
2309 : : }
2310 : : else
2311 : : {
2312 : 0 : cmp = CompareReversedINChI3( pStruct->RevInChI.pINChI[i][0][b], pInChI[0], NULL, NULL, &err );
2313 [ # # ]: 0 : if (cmp)
2314 : : {
2315 : 0 : CompareInchiFlags[bMobileH] |= cmp;
2316 : : }
2317 : : }
2318 [ # # # # ]: 0 : if (b == b0 && b == TAUT_NON)
2319 : : {
2320 [ # # ]: 0 : if ((pStruct->RevInChI.pINChI[i][0][TAUT_YES] &&
2321 [ # # ]: 0 : !pStruct->RevInChI.pINChI[i][0][TAUT_YES]->bDeleted) ||
2322 [ # # # # ]: 0 : (pInChI[1] && !pInChI[1]->bDeleted)) /* djb-rwth: addressing LLVM warnings */
2323 : : {
2324 : : /* in addition to fixed-H also compare mobile-H InChI */
2325 : 0 : cmp = CompareReversedINChI3(pStruct->RevInChI.pINChI[i][0][TAUT_YES], pInChI[1], NULL, NULL, &err);
2326 [ # # ]: 0 : if (cmp)
2327 : : {
2328 : 0 : CompareInchiFlags[TAUT_YES] |= cmp;
2329 : : }
2330 : : }
2331 : : /* compare removed H */
2332 [ # # ]: 0 : if (pStruct->nNumRemovedProtonsMobHInChI != pStruct->RevInChI.pINChI_Aux[i][0][TAUT_YES]->nNumRemovedProtons)
2333 : : {
2334 : 0 : CompareInchiFlags[TAUT_YES] |= INCHIDIFF_MOBH_PROTONS;
2335 : : }
2336 : : }
2337 : 0 : memset(nCurRemovedProtons, 0, sizeof(*nCurRemovedProtons)); /* djb-rwth: memset_s C11/Annex K variant? */
2338 [ # # ]: 0 : for (k = 0; k < pStruct->RevInChI.num_components[i]; k++)
2339 : : {
2340 [ # # # # ]: 0 : if (!k || pStruct->RevInChI.pINChI[i][k][TAUT_YES]->bDeleted)
2341 : : {
2342 : : /* get removed protons from the 1st component; add othere only if they are deleted protons */
2343 : 0 : nCurRemovedProtons->nNumRemovedProtons += pStruct->RevInChI.pINChI_Aux[i][k][TAUT_YES]->nNumRemovedProtons;
2344 [ # # ]: 0 : for (j = 0; j < NUM_H_ISOTOPES; j++)
2345 : : {
2346 : 0 : nCurRemovedProtons->nNumRemovedIsotopicH[j] += pStruct->RevInChI.pINChI_Aux[i][k][TAUT_YES]->nNumRemovedIsotopicH[j];
2347 : : }
2348 : : }
2349 : : }
2350 : : }
2351 : : }
2352 : : else
2353 : : {
2354 : 0 : CompareInchiFlags[bMobileH] |= INCHIDIFF_STR2INCHI_ERR;
2355 : : }
2356 : :
2357 : 0 : return err;
2358 : : }
2359 : :
2360 : :
2361 : : /****************************************************************************/
2362 : 0 : INCHI_MODE CompareReversedStereoINChI3(INChI_Stereo* s1,
2363 : : /* InChI from reversed struct */
2364 : : INChI_Stereo* s2,
2365 : : /* input InChI */
2366 : : ICR* picr)
2367 : : {
2368 : 0 : int ret = 0;
2369 : : int j1, j2, num_dif, num_extra_undf, num_miss_undf, num_in1_only, num_in2_only; /* djb-rwth: removing redundant variables */
2370 : 0 : int bAddSb = !(picr->num_sb_undef_in1_only + picr->num_sb_in1_only + picr->num_sb_in2_only);
2371 : 0 : int bAddSc = !(picr->num_sc_undef_in1_only + picr->num_sc_in1_only + picr->num_sc_in2_only);
2372 : :
2373 [ # # ]: 0 : int nNumSc1 = s1 ? s1->nNumberOfStereoCenters : 0;
2374 [ # # ]: 0 : int nNumSc2 = s2 ? s2->nNumberOfStereoCenters : 0;
2375 [ # # ]: 0 : int nNumSb1 = s1 ? s1->nNumberOfStereoBonds : 0;
2376 [ # # ]: 0 : int nNumSb2 = s2 ? s2->nNumberOfStereoBonds : 0;
2377 : :
2378 [ # # # # : 0 : if ((nNumSc1 || nNumSc2) &&
# # ]
2379 : 0 : (nNumSc1 != nNumSc2 ||
2380 [ # # ]: 0 : memcmp(s1->nNumber, s2->nNumber, nNumSc1 * sizeof(s1->nNumber[0])) ||
2381 [ # # ]: 0 : memcmp(s1->t_parity, s2->t_parity, nNumSc1 * sizeof(s1->t_parity[0])))) /* djb-rwth: condition corrected */
2382 : : {
2383 : :
2384 : 0 : num_dif = num_extra_undf = num_miss_undf = num_in1_only = num_in2_only = 0; /* djb-rwth: removing redundant code */
2385 [ # # # # ]: 0 : for (j1 = j2 = 0; j1 < nNumSc1 && j2 < nNumSc2; )
2386 : : {
2387 [ # # ]: 0 : if (s1->nNumber[j1] == s2->nNumber[j2])
2388 : : {
2389 [ # # ]: 0 : if (s1->t_parity[j1] != s2->t_parity[j2])
2390 : : /* djb-rwth: removing redundant code */
2391 : : {
2392 : 0 : num_dif++;
2393 : : }
2394 : 0 : j1++;
2395 : 0 : j2++;
2396 : : }
2397 : : else
2398 : : {
2399 [ # # ]: 0 : if (s1->nNumber[j1] < s2->nNumber[j2])
2400 : : {
2401 : 0 : num_in1_only++;
2402 [ # # ]: 0 : if (s1->t_parity[j1] == AB_PARITY_UNDF)
2403 : : {
2404 : 0 : num_extra_undf++;
2405 : : }
2406 [ # # ]: 0 : if (bAddSc)
2407 : : {
2408 [ # # ]: 0 : if (picr->num_sc_in1_only < ICR_MAX_SC_IN1_ONLY)
2409 : 0 : picr->sc_in1_only[picr->num_sc_in1_only++] = j1;
2410 [ # # ]: 0 : if (s1->t_parity[j1] == AB_PARITY_UNDF)
2411 : : {
2412 [ # # ]: 0 : if (picr->num_sc_undef_in1_only < ICR_MAX_SC_UNDF)
2413 : 0 : picr->sc_undef_in1_only[picr->num_sc_undef_in1_only++] = j1;
2414 : : }
2415 : : }
2416 : 0 : j1++;
2417 : : }
2418 : : else
2419 : : {
2420 : 0 : num_in2_only++;
2421 [ # # ]: 0 : if (s2->t_parity[j2] == AB_PARITY_UNDF)
2422 : : {
2423 : 0 : num_miss_undf++;
2424 : : }
2425 [ # # ]: 0 : if (bAddSc)
2426 : : {
2427 [ # # ]: 0 : if (picr->num_sc_in2_only < ICR_MAX_SC_IN2_ONLY)
2428 : 0 : picr->sc_in2_only[picr->num_sc_in2_only++] = j2;
2429 [ # # ]: 0 : if (s2->t_parity[j2] == AB_PARITY_UNDF)
2430 : : {
2431 [ # # ]: 0 : if (picr->num_sc_undef_in2_only < ICR_MAX_SC_UNDF)
2432 : 0 : picr->sc_undef_in2_only[picr->num_sc_undef_in2_only++] = j1;
2433 : : }
2434 : : }
2435 : 0 : j2++;
2436 : : }
2437 : : }
2438 : : }
2439 : :
2440 [ # # ]: 0 : while (j1 < nNumSc1)
2441 : : {
2442 [ # # ]: 0 : if (s1->t_parity[j1] == AB_PARITY_UNDF)
2443 : : {
2444 : 0 : num_extra_undf++;
2445 : : }
2446 : 0 : num_in1_only++;
2447 [ # # ]: 0 : if (bAddSc)
2448 : : {
2449 [ # # ]: 0 : if (picr->num_sc_in1_only < ICR_MAX_SC_IN1_ONLY)
2450 : 0 : picr->sc_in1_only[picr->num_sc_in1_only++] = j1;
2451 [ # # ]: 0 : if (s1->t_parity[j1] == AB_PARITY_UNDF)
2452 : : {
2453 [ # # ]: 0 : if (picr->num_sc_undef_in1_only < ICR_MAX_SC_UNDF)
2454 : 0 : picr->sc_undef_in1_only[picr->num_sc_undef_in1_only++] = j1;
2455 : : }
2456 : : }
2457 : 0 : j1++;
2458 : : }
2459 : :
2460 [ # # ]: 0 : while (j2 < nNumSc2)
2461 : : {
2462 [ # # ]: 0 : if (s2->t_parity[j2] == AB_PARITY_UNDF)
2463 : : {
2464 : 0 : num_miss_undf++;
2465 : : }
2466 : 0 : num_in2_only++;
2467 [ # # ]: 0 : if (bAddSc)
2468 : : {
2469 [ # # ]: 0 : if (picr->num_sc_in2_only < ICR_MAX_SC_IN2_ONLY)
2470 : 0 : picr->sc_in2_only[picr->num_sc_in2_only++] = j2;
2471 : : }
2472 : 0 : j2++;
2473 : : }
2474 : :
2475 [ # # ]: 0 : if (num_dif)
2476 : : {
2477 : 0 : ret |= INCHIDIFF_SC_PARITY;
2478 : : }
2479 [ # # ]: 0 : if (num_in1_only)
2480 : : {
2481 [ # # ]: 0 : if (num_extra_undf)
2482 : : {
2483 : 0 : ret |= INCHIDIFF_SC_EXTRA_UNDF;
2484 : : }
2485 [ # # ]: 0 : if (num_in1_only != num_extra_undf)
2486 : : {
2487 : 0 : ret |= INCHIDIFF_SC_EXTRA;
2488 : : }
2489 : : }
2490 [ # # ]: 0 : if (num_in2_only)
2491 : : {
2492 [ # # ]: 0 : if (num_miss_undf)
2493 : : {
2494 : 0 : ret |= INCHIDIFF_SC_MISS_UNDF;
2495 : : }
2496 [ # # ]: 0 : if (num_in2_only != num_miss_undf)
2497 : : {
2498 : 0 : ret |= INCHIDIFF_SC_MISS;
2499 : : }
2500 : : }
2501 : : }
2502 : :
2503 [ # # # # : 0 : if (s1 && s2 && (s2->nCompInv2Abs != 2) && s1->nCompInv2Abs != s2->nCompInv2Abs && s1->nCompInv2Abs && s2->nCompInv2Abs)
# # # # #
# # # ]
2504 : : {
2505 : 0 : ret |= INCHIDIFF_SC_INV; /* 2007-07-13 DT: added (s2->nCompInv2Abs != 2) to fix bug reoprted by Yerin on 2007/02/28 */
2506 : : /* Bug description: falsely reported "Stereo centers/allenes: Falsely inverted" for /S2 or /S3 */
2507 : : }
2508 : :
2509 [ # # # # : 0 : if ((nNumSb1 || nNumSb2) &&
# # ]
2510 : 0 : (nNumSb1 != nNumSb2 ||
2511 [ # # ]: 0 : memcmp(s1->nBondAtom1, s2->nBondAtom1, nNumSb1 * sizeof(s1->nBondAtom1[0])) ||
2512 [ # # ]: 0 : memcmp(s1->nBondAtom2, s2->nBondAtom2, nNumSb1 * sizeof(s1->nBondAtom2[0])) ||
2513 [ # # ]: 0 : memcmp(s1->b_parity, s2->b_parity, nNumSb1 * sizeof(s1->b_parity[0]))))
2514 : : {
2515 : :
2516 : 0 : num_dif = num_extra_undf = num_miss_undf = num_in1_only = num_in2_only = 0; /* djb-rwth: removing redundant code */
2517 [ # # # # ]: 0 : for (j1 = j2 = 0; j1 < nNumSb1 && j2 < nNumSb2; )
2518 : : {
2519 [ # # ]: 0 : if (s1->nBondAtom1[j1] == s2->nBondAtom1[j2] &&
2520 [ # # ]: 0 : s1->nBondAtom2[j1] == s2->nBondAtom2[j2])
2521 : : {
2522 [ # # ]: 0 : if (s1->b_parity[j1] != s2->b_parity[j2])
2523 : : /* djb-rwth: removing redundant code */
2524 : : {
2525 : 0 : num_dif++;
2526 : : }
2527 : 0 : j1++;
2528 : 0 : j2++;
2529 : : }
2530 : : else
2531 : : {
2532 [ # # ]: 0 : if (s1->nBondAtom1[j1] < s2->nBondAtom1[j2] ||
2533 [ # # # # ]: 0 : (s1->nBondAtom1[j1] == s2->nBondAtom1[j2] && s1->nBondAtom2[j1] < s2->nBondAtom2[j2])) /* djb-rwth: addressing LLVM warning */
2534 : : {
2535 : 0 : num_in1_only++;
2536 [ # # ]: 0 : if (s1->b_parity[j1] == AB_PARITY_UNDF)
2537 : : {
2538 : 0 : num_extra_undf++;
2539 : : }
2540 [ # # ]: 0 : if (bAddSb)
2541 : : {
2542 [ # # ]: 0 : if (picr->num_sb_in1_only < ICR_MAX_SB_IN1_ONLY)
2543 : 0 : picr->sb_in1_only[picr->num_sb_in1_only++] = j1;
2544 [ # # ]: 0 : if (s1->b_parity[j1] == AB_PARITY_UNDF)
2545 : : {
2546 [ # # ]: 0 : if (picr->num_sb_undef_in1_only < ICR_MAX_SB_UNDF)
2547 : 0 : picr->sb_undef_in1_only[picr->num_sb_undef_in1_only++] = j1;
2548 : : }
2549 : : }
2550 : 0 : j1++;
2551 : : }
2552 : : else
2553 : : {
2554 : 0 : num_in2_only++;
2555 [ # # ]: 0 : if (s2->b_parity[j2] == AB_PARITY_UNDF)
2556 : : {
2557 : 0 : num_miss_undf++;
2558 : : }
2559 [ # # ]: 0 : if (bAddSb)
2560 : : {
2561 [ # # ]: 0 : if (picr->num_sb_in2_only < ICR_MAX_SB_IN2_ONLY)
2562 : 0 : picr->sb_in2_only[picr->num_sb_in2_only++] = j2;
2563 [ # # ]: 0 : if (s2->b_parity[j2] == AB_PARITY_UNDF)
2564 : : {
2565 [ # # ]: 0 : if (picr->num_sb_undef_in2_only < ICR_MAX_SB_UNDF)
2566 : 0 : picr->sb_undef_in2_only[picr->num_sb_undef_in2_only++] = j1;
2567 : : }
2568 : : }
2569 : 0 : j2++;
2570 : : }
2571 : : }
2572 : : }
2573 [ # # ]: 0 : while (j1 < nNumSb1)
2574 : : {
2575 : 0 : num_in1_only++;
2576 [ # # ]: 0 : if (s1->b_parity[j1] == AB_PARITY_UNDF)
2577 : : {
2578 : 0 : num_extra_undf++;
2579 : : }
2580 [ # # ]: 0 : if (bAddSb)
2581 : : {
2582 [ # # ]: 0 : if (picr->num_sb_in1_only < ICR_MAX_SB_IN1_ONLY)
2583 : 0 : picr->sb_in1_only[picr->num_sb_in1_only++] = j1;
2584 [ # # ]: 0 : if (s1->b_parity[j1] == AB_PARITY_UNDF)
2585 : : {
2586 [ # # ]: 0 : if (picr->num_sb_undef_in1_only < ICR_MAX_SB_UNDF)
2587 : 0 : picr->sb_undef_in1_only[picr->num_sb_undef_in1_only++] = j1;
2588 : : }
2589 : : }
2590 : 0 : j1++;
2591 : : }
2592 [ # # ]: 0 : while (j2 < nNumSb2)
2593 : : {
2594 : 0 : num_in2_only++;
2595 [ # # ]: 0 : if (s2->b_parity[j2] == AB_PARITY_UNDF)
2596 : : {
2597 : 0 : num_miss_undf++;
2598 : : }
2599 [ # # ]: 0 : if (bAddSb)
2600 : : {
2601 [ # # ]: 0 : if (picr->num_sb_in2_only < ICR_MAX_SB_IN2_ONLY)
2602 : 0 : picr->sb_in2_only[picr->num_sb_in2_only++] = j2;
2603 [ # # ]: 0 : if (s2->b_parity[j2] == AB_PARITY_UNDF)
2604 : : {
2605 [ # # ]: 0 : if (picr->num_sb_undef_in2_only < ICR_MAX_SB_UNDF)
2606 : 0 : picr->sb_undef_in2_only[picr->num_sb_undef_in2_only++] = j1;
2607 : : }
2608 : : }
2609 : 0 : j2++;
2610 : : }
2611 [ # # ]: 0 : if (num_dif)
2612 : : {
2613 : 0 : ret |= INCHIDIFF_SB_PARITY;
2614 : : }
2615 [ # # ]: 0 : if (num_in1_only)
2616 : : {
2617 [ # # ]: 0 : if (num_extra_undf)
2618 : : {
2619 : 0 : ret |= INCHIDIFF_SB_EXTRA_UNDF;
2620 : : }
2621 [ # # ]: 0 : if (num_in1_only != num_extra_undf)
2622 : : {
2623 : 0 : ret |= INCHIDIFF_SB_EXTRA;
2624 : : }
2625 : : }
2626 [ # # ]: 0 : if (num_in2_only)
2627 : : {
2628 [ # # ]: 0 : if (num_miss_undf)
2629 : : {
2630 : 0 : ret |= INCHIDIFF_SB_MISS_UNDF;
2631 : : }
2632 [ # # ]: 0 : if (num_in2_only != num_miss_undf)
2633 : : {
2634 : 0 : ret |= INCHIDIFF_SB_MISS;
2635 : : }
2636 : : }
2637 : : }
2638 : :
2639 : 0 : return ret;
2640 : : }
2641 : :
2642 : :
2643 : : /****************************************************************************/
2644 : 0 : INCHI_MODE CompareReversedINChI3(INChI* i1 /* InChI from reversed struct */,
2645 : : INChI* i2 /* input InChI */,
2646 : : INChI_Aux* a1,
2647 : : INChI_Aux* a2,
2648 : : int* err)
2649 : : {
2650 : 0 : INCHI_MODE ret = 0;
2651 : 0 : INChI_Stereo* Stereo1 = NULL, * Stereo2 = NULL;
2652 : : int n1, n2, m, j, j1, j2, ret2, num_H1, num_H2;
2653 : : ICR icr;
2654 : 0 : ICR* picr = &icr;
2655 : :
2656 : 0 : *err = 0;
2657 : :
2658 : 0 : memset(picr, 0, sizeof(*picr)); /* djb-rwth: memset_s C11/Annex K variant? */
2659 : :
2660 [ # # # # ]: 0 : if (i1 == NULL && i2 == NULL)
2661 : : {
2662 : 0 : return 0;
2663 : : }
2664 [ # # ]: 0 : if ((i1 == NULL) ^ (i2 == NULL))
2665 : : {
2666 : 0 : ret |= INCHIDIFF_PROBLEM; /* one InChI exists while another doesn't */
2667 : 0 : goto exit_function;
2668 : : }
2669 : :
2670 [ # # ]: 0 : if (i1->nErrorCode == i2->nErrorCode)
2671 : : {
2672 [ # # ]: 0 : if (i1->nErrorCode)
2673 : : {
2674 : 0 : ret |= INCHIDIFF_PROBLEM; /* both InChI have same error codes */
2675 : 0 : goto exit_function;
2676 : : }
2677 : : }
2678 : : else
2679 : : {
2680 : 0 : ret |= INCHIDIFF_PROBLEM; /* at least one InChI has an error code */
2681 : 0 : goto exit_function;
2682 : : }
2683 : :
2684 [ # # ]: 0 : if (i1->nNumberOfAtoms != i2->nNumberOfAtoms)
2685 : : {
2686 : 0 : ret |= INCHIDIFF_NUM_AT;
2687 : 0 : goto exit_function;
2688 : : }
2689 [ # # ]: 0 : if (i1->nNumberOfAtoms > 0)
2690 : : {
2691 [ # # ]: 0 : if (memcmp(i1->nAtom, i2->nAtom, i1->nNumberOfAtoms * sizeof(i1->nAtom[0])))
2692 : : {
2693 : 0 : ret |= INCHIDIFF_ATOMS;
2694 : 0 : goto exit_function;
2695 : : }
2696 : : /* INCHIDIFF_NON_TAUT_H, INCHIDIFF_MORE_FH, INCHIDIFF_LESS_FH */
2697 [ # # ]: 0 : if (memcmp(i1->nNum_H, i2->nNum_H, i1->nNumberOfAtoms * sizeof(i1->nNum_H[0])))
2698 : : {
2699 : 0 : ret |= INCHIDIFF_POSITION_H;
2700 [ # # ]: 0 : for (j1 = 0; j1 < i1->nNumberOfAtoms; j1++)
2701 : : {
2702 [ # # # # ]: 0 : if (i1->nNum_H[j1] != i2->nNum_H[j1] && picr->num_diff_pos_H < ICR_MAX_DIFF_FIXED_H)
2703 : : {
2704 : 0 : picr->diff_pos_H_at[picr->num_diff_pos_H] = j1;
2705 : 0 : picr->diff_pos_H_nH[picr->num_diff_pos_H] = i1->nNum_H[j1] - i2->nNum_H[j1];
2706 : 0 : picr->num_diff_pos_H++;
2707 : : }
2708 : : }
2709 : : }
2710 : : /* fixed H */
2711 [ # # # # ]: 0 : if (i1->nNum_H_fixed || i2->nNum_H_fixed)
2712 : : {
2713 : 0 : int bHasFixedH1 = 0, bHasFixedH2 = 0, i;
2714 [ # # ]: 0 : if (i1->nNum_H_fixed)
2715 : : {
2716 [ # # ]: 0 : for (i = 0; i < i1->nNumberOfAtoms; i++)
2717 : : {
2718 [ # # ]: 0 : if (i1->nNum_H_fixed[i])
2719 : : {
2720 : 0 : bHasFixedH1++;
2721 : : }
2722 : : }
2723 : : }
2724 [ # # ]: 0 : if (i2->nNum_H_fixed)
2725 : : {
2726 [ # # ]: 0 : for (i = 0; i < i2->nNumberOfAtoms; i++)
2727 : : {
2728 [ # # ]: 0 : if (i2->nNum_H_fixed[i])
2729 : : {
2730 : 0 : bHasFixedH2++;
2731 : : }
2732 : : }
2733 : : }
2734 [ # # # # ]: 0 : if (bHasFixedH1 && !bHasFixedH2)
2735 : : {
2736 [ # # ]: 0 : for (i = j = 0; i < i1->nNumberOfAtoms; i++)
2737 : : {
2738 [ # # ]: 0 : if (i1->nNum_H_fixed[i])
2739 : : {
2740 [ # # ]: 0 : if (j < ICR_MAX_DIFF_FIXED_H)
2741 : : {
2742 : 0 : picr->fixed_H_at1_more[j] = i;
2743 : 0 : picr->fixed_H_nH1_more[j] = i1->nNum_H_fixed[i];
2744 : 0 : j++;
2745 : : }
2746 : : }
2747 : : }
2748 : 0 : picr->num_fixed_H1_more = j;
2749 : 0 : ret |= INCHIDIFF_MORE_FH; /* Extra Fixed-H */
2750 : : }
2751 : : else
2752 : : {
2753 [ # # # # ]: 0 : if (!bHasFixedH1 && bHasFixedH2)
2754 : : {
2755 [ # # ]: 0 : for (i = j = 0; i < i2->nNumberOfAtoms; i++)
2756 : : {
2757 [ # # ]: 0 : if (i2->nNum_H_fixed[i])
2758 : : {
2759 [ # # ]: 0 : if (j < ICR_MAX_DIFF_FIXED_H)
2760 : : {
2761 : 0 : picr->fixed_H_at2_more[j] = i;
2762 : 0 : picr->fixed_H_nH2_more[j] = i2->nNum_H_fixed[i];
2763 : 0 : j++;
2764 : : }
2765 : : }
2766 : : }
2767 : 0 : picr->num_fixed_H2_more = j;
2768 : 0 : ret |= INCHIDIFF_LESS_FH; /* Missed Fixed-H */
2769 : : }
2770 : : else
2771 : : {
2772 [ # # # # ]: 0 : if (bHasFixedH1 && bHasFixedH2 &&
2773 [ # # ]: 0 : memcmp(i1->nNum_H_fixed, i2->nNum_H_fixed, i1->nNumberOfAtoms * sizeof(i1->nNum_H_fixed[0])))
2774 : : {
2775 [ # # ]: 0 : for (i = j1 = j2 = 0; i < i1->nNumberOfAtoms; i++)
2776 : : {
2777 [ # # ]: 0 : if (i1->nNum_H_fixed[i] > i2->nNum_H_fixed[i])
2778 : : {
2779 [ # # ]: 0 : if (j1 < ICR_MAX_DIFF_FIXED_H)
2780 : : {
2781 : 0 : picr->fixed_H_at1_more[j1] = i;
2782 : 0 : picr->fixed_H_nH1_more[j1] = i1->nNum_H_fixed[i] - i2->nNum_H_fixed[i];
2783 : 0 : j1++;
2784 : : }
2785 : : }
2786 : : else
2787 [ # # ]: 0 : if (i1->nNum_H_fixed[i] < i2->nNum_H_fixed[i])
2788 : : {
2789 [ # # ]: 0 : if (j2 < ICR_MAX_DIFF_FIXED_H)
2790 : : {
2791 : 0 : picr->fixed_H_at2_more[j2] = i;
2792 : 0 : picr->fixed_H_nH2_more[j2] = i2->nNum_H_fixed[i] - i1->nNum_H_fixed[i];
2793 : 0 : j2++;
2794 : : }
2795 : : }
2796 : : }
2797 [ # # # # ]: 0 : ret |= (j1 ? INCHIDIFF_MORE_FH : 0) | (j2 ? INCHIDIFF_LESS_FH : 0);
2798 : 0 : picr->num_fixed_H1_more = j1;
2799 : 0 : picr->num_fixed_H2_more = j2;
2800 : : }
2801 : : }
2802 : : }
2803 : : }
2804 : : }
2805 : :
2806 : : /* compare formulas and H */
2807 : 0 : num_H1 = 0;
2808 : 0 : num_H2 = 0;
2809 : 0 : ret2 = CompareHillFormulasNoH(i1->szHillFormula, i2->szHillFormula, &num_H1, &num_H2);
2810 : 0 : picr->tot_num_H1 = num_H1;
2811 : 0 : picr->tot_num_H2 = num_H2;
2812 [ # # ]: 0 : if (ret2)
2813 : : {
2814 : 0 : ret |= INCHIDIFF_NUM_EL;
2815 : 0 : goto exit_function;
2816 : : }
2817 [ # # ]: 0 : if (num_H1 > num_H2)
2818 : : {
2819 : 0 : ret |= INCHIDIFF_MORE_H;
2820 : : }
2821 [ # # ]: 0 : if (num_H1 < num_H2)
2822 : : {
2823 : 0 : ret |= INCHIDIFF_LESS_H;
2824 : : }
2825 : :
2826 [ # # ]: 0 : if (i1->lenConnTable != i2->lenConnTable)
2827 : : {
2828 : 0 : ret |= INCHIDIFF_CON_LEN;
2829 : 0 : goto exit_function;
2830 : : }
2831 : : else
2832 : : {
2833 [ # # # # ]: 0 : if (i1->lenConnTable > 0 && memcmp(i1->nConnTable, i2->nConnTable, i1->lenConnTable * sizeof(i1->nConnTable[0])))
2834 : : {
2835 : 0 : ret |= INCHIDIFF_CON_TBL;
2836 : 0 : goto exit_function;
2837 : : }
2838 : : }
2839 : : /* output special cases: different number of t-groups, different sizes of t-groups, different endpoints */
2840 : : /* in isotopic or deprotonated cases i1->lenTautomer == 1 && i1->nTautomer[0] = 0 */
2841 : : /*
2842 : : if ( i1->lenTautomer != i2->lenTautomer && (i1->lenTautomer > 1 || i2->lenTautomer > 1) )
2843 : : {
2844 : : ret |= INCHIDIFF_TAUT_LEN;
2845 : : }
2846 : : */
2847 : :
2848 : : /* compare number of t-groups */
2849 [ # # ]: 0 : n1 = i1->lenTautomer ? i1->nTautomer[0] : 0;
2850 [ # # ]: 0 : n2 = i2->lenTautomer ? i2->nTautomer[0] : 0;
2851 [ # # # # ]: 0 : if (!n1 && n2)
2852 : : {
2853 : 0 : ret |= INCHIDIFF_NO_TAUT;
2854 : : }
2855 : : else
2856 : : {
2857 [ # # # # ]: 0 : if (n1 && !n2)
2858 : : {
2859 : 0 : ret |= INCHIDIFF_WRONG_TAUT;
2860 : : }
2861 : : else
2862 : : {
2863 [ # # # # ]: 0 : if (n1 == 1 && n2 > 1)
2864 : : {
2865 : 0 : ret |= INCHIDIFF_SINGLE_TG;
2866 : : }
2867 : : else
2868 : : {
2869 [ # # # # ]: 0 : if (n1 > 1 && n2 == 1)
2870 : : {
2871 : 0 : ret |= INCHIDIFF_MULTIPLE_TG;
2872 : : }
2873 : : else
2874 : : {
2875 [ # # ]: 0 : if (n1 != n2)
2876 : : {
2877 : 0 : ret |= INCHIDIFF_NUM_TG;
2878 : : }
2879 : : }
2880 : : }
2881 : : }
2882 : : }
2883 : :
2884 [ # # # # ]: 0 : if (n1 || n2)
2885 : : {
2886 : : /* number of endpoints */
2887 : 0 : int num1 = 0, num2 = 0, num_M1 = 0, num_M2 = 0;
2888 : : int len, num_eq, num_in1_only, num_in2_only;
2889 : 0 : AT_NUMB* pe1 = (AT_NUMB*)inchi_malloc(((long long)i1->lenTautomer + 1) * sizeof(pe1[0])); /* djb-rwth: cast operator added */
2890 : 0 : AT_NUMB* pe2 = (AT_NUMB*)inchi_malloc(((long long)i2->lenTautomer + 1) * sizeof(pe2[0])); /* djb-rwth: cast operator added */
2891 : 0 : num_H1 = num_H2 = 0;
2892 : : /* collect endpoints, H, (-) */
2893 [ # # # # ]: 0 : if (!pe1 || !pe2)
2894 : : {
2895 [ # # # # ]: 0 : if (pe1) inchi_free(pe1);
2896 [ # # # # ]: 0 : if (pe2) inchi_free(pe2);
2897 : 0 : *err = RI_ERR_ALLOC; /* allocation error */
2898 : 0 : goto exit_function;
2899 : : }
2900 [ # # ]: 0 : for (m = 1; m < i1->lenTautomer; m += len)
2901 : : {
2902 : 0 : len = i1->nTautomer[m++];
2903 : 0 : num_H1 += i1->nTautomer[m];
2904 : 0 : num_M1 += i1->nTautomer[m + 1];
2905 [ # # ]: 0 : for (j = 2; j < len; j++)
2906 : : {
2907 : 0 : pe1[num1++] = i1->nTautomer[m + j];
2908 : : }
2909 : : }
2910 [ # # ]: 0 : for (m = 1; m < i2->lenTautomer; m += len)
2911 : : {
2912 : 0 : len = i2->nTautomer[m++];
2913 : 0 : num_H2 += i2->nTautomer[m];
2914 : 0 : num_M2 += i2->nTautomer[m + 1];
2915 [ # # ]: 0 : for (j = 2; j < len; j++)
2916 : : {
2917 : 0 : pe2[num2++] = i2->nTautomer[m + j];
2918 : : }
2919 : : }
2920 : 0 : picr->num_taut_H1 = num_H1;
2921 : 0 : picr->num_taut_H2 = num_H2;
2922 : 0 : picr->num_taut_M1 = num_M1;
2923 : 0 : picr->num_taut_M2 = num_M2;
2924 : : /* sort endpoints */
2925 : 0 : insertions_sort_AT_NUMB(pe1, num1);
2926 : 0 : insertions_sort_AT_NUMB(pe2, num2);
2927 : : /* compare */
2928 : : /*
2929 : : if ( num1 < num2 ) {
2930 : : ret |= INCHIDIFF_LESS_TG_ENDP;
2931 : : } else
2932 : : if ( num1 > num2 ) {
2933 : : ret |= INCHIDIFF_MORE_TG_ENDP;
2934 : : }
2935 : : */
2936 : : /* compare all */
2937 : 0 : num_eq = num_in1_only = num_in2_only = 0;
2938 [ # # # # ]: 0 : for (j1 = j2 = 0; j1 < num1 && j2 < num2; )
2939 : : {
2940 [ # # ]: 0 : if (pe1[j1] == pe2[j2])
2941 : : {
2942 : 0 : j1++;
2943 : 0 : j2++;
2944 : 0 : num_eq++;
2945 : : }
2946 : : else
2947 : : {
2948 [ # # ]: 0 : if (pe1[j1] < pe2[j1])
2949 : : {
2950 [ # # ]: 0 : if (picr->num_endp_in1_only < ICR_MAX_ENDP_IN1_ONLY)
2951 : : {
2952 : 0 : picr->endp_in1_only[picr->num_endp_in1_only++] = pe1[j1];
2953 : : }
2954 : 0 : j1++;
2955 : 0 : num_in1_only++;
2956 : : }
2957 : : else
2958 : : {
2959 [ # # ]: 0 : if (picr->num_endp_in2_only < ICR_MAX_ENDP_IN2_ONLY)
2960 : : {
2961 : 0 : picr->endp_in2_only[picr->num_endp_in2_only++] = pe2[j2];
2962 : : }
2963 : 0 : j2++;
2964 : 0 : num_in2_only++;
2965 : : }
2966 : : }
2967 : : }
2968 [ # # ]: 0 : while (j1 < num1)
2969 : : {
2970 [ # # ]: 0 : if (picr->num_endp_in1_only < ICR_MAX_ENDP_IN1_ONLY)
2971 : : {
2972 : 0 : picr->endp_in1_only[picr->num_endp_in1_only++] = pe1[j1];
2973 : : }
2974 : 0 : j1++;
2975 : 0 : num_in1_only++;
2976 : : }
2977 [ # # ]: 0 : while (j2 < num2)
2978 : : {
2979 [ # # ]: 0 : if (picr->num_endp_in2_only < ICR_MAX_ENDP_IN2_ONLY)
2980 : : {
2981 : 0 : picr->endp_in2_only[picr->num_endp_in2_only++] = pe2[j2];
2982 : : }
2983 : 0 : j2++;
2984 : 0 : num_in2_only++;
2985 : : }
2986 [ # # ]: 0 : if (num_in1_only)
2987 : : {
2988 : 0 : ret |= INCHIDIFF_EXTRA_TG_ENDP;
2989 : : }
2990 [ # # ]: 0 : if (num_in2_only)
2991 : : {
2992 : 0 : ret |= INCHIDIFF_MISS_TG_ENDP;
2993 : : }
2994 [ # # # # : 0 : if (!num_in1_only && !num_in2_only && num_eq)
# # ]
2995 : : {
2996 : : ; /* same t-groups endpoints */
2997 : : }
2998 : : else
2999 : : {
3000 : 0 : ret |= INCHIDIFF_DIFF_TG_ENDP;
3001 : : }
3002 [ # # ]: 0 : inchi_free(pe1);
3003 [ # # ]: 0 : inchi_free(pe2);
3004 : : }
3005 : :
3006 [ # # # # ]: 0 : if ((i1->lenTautomer > 1 && i2->lenTautomer > 1) &&
3007 [ # # ]: 0 : (i1->lenTautomer != i2->lenTautomer ||
3008 [ # # ]: 0 : memcmp(i1->nTautomer, i2->nTautomer, i1->lenTautomer * sizeof(i1->nTautomer[0]))))
3009 : 0 : ret |= INCHIDIFF_TG;
3010 : :
3011 [ # # ]: 0 : if (i1->nNumberOfIsotopicAtoms != i2->nNumberOfIsotopicAtoms)
3012 : : {
3013 : 0 : ret |= INCHIDIFF_NUM_ISO_AT;
3014 : : }
3015 : : else
3016 : : {
3017 [ # # # # ]: 0 : if (i1->nNumberOfIsotopicAtoms > 0 && memcmp(i1->IsotopicAtom, i2->IsotopicAtom, i1->nNumberOfIsotopicAtoms * sizeof(i1->IsotopicAtom[0])))
3018 : : {
3019 : 0 : ret |= INCHIDIFF_ISO_AT;
3020 : : }
3021 : : }
3022 [ # # ]: 0 : if (i1->nTotalCharge != i2->nTotalCharge)
3023 : 0 : ret |= INCHIDIFF_CHARGE;
3024 [ # # # # : 0 : if (a1 && a1->nNumRemovedProtons && (!a2 || a2->nNumRemovedProtons != a1->nNumRemovedProtons))
# # # # ]
3025 : : {
3026 : 0 : ret |= INCHIDIFF_REM_PROT;
3027 : : }
3028 [ # # # # ]: 0 : if (a1 && (!a2 ||
3029 [ # # ]: 0 : a2->nNumRemovedIsotopicH[0] != a1->nNumRemovedIsotopicH[0] ||
3030 [ # # ]: 0 : a2->nNumRemovedIsotopicH[1] != a1->nNumRemovedIsotopicH[1] ||
3031 [ # # ]: 0 : a2->nNumRemovedIsotopicH[2] != a1->nNumRemovedIsotopicH[2]))
3032 : : {
3033 : 0 : ret |= INCHIDIFF_REM_ISO_H;
3034 : : }
3035 : :
3036 : : /*
3037 : : if ( i1->nPossibleLocationsOfIsotopicH && i2->nPossibleLocationsOfIsotopicH ) {
3038 : : if ( i1->nPossibleLocationsOfIsotopicH[0] != i2->nPossibleLocationsOfIsotopicH[0] ||
3039 : : memcmp(i1->nPossibleLocationsOfIsotopicH, i2->nPossibleLocationsOfIsotopicH,
3040 : : sizeof(i1->nPossibleLocationsOfIsotopicH[0])*i1->nPossibleLocationsOfIsotopicH[0]) )
3041 : : return 18;
3042 : : } else
3043 : : if ( !i1->nPossibleLocationsOfIsotopicH != !i2->nPossibleLocationsOfIsotopicH ) {
3044 : : return 19;
3045 : : }
3046 : : */
3047 [ # # ]: 0 : if (i1->StereoIsotopic &&
3048 [ # # ]: 0 : i1->StereoIsotopic->nNumberOfStereoBonds + i1->StereoIsotopic->nNumberOfStereoCenters)
3049 : : {
3050 : 0 : Stereo1 = i1->StereoIsotopic;
3051 : : }
3052 : : else
3053 : : {
3054 : 0 : Stereo1 = i1->Stereo;
3055 : : }
3056 [ # # ]: 0 : if (i2->StereoIsotopic &&
3057 [ # # ]: 0 : i2->StereoIsotopic->nNumberOfStereoBonds + i2->StereoIsotopic->nNumberOfStereoCenters)
3058 : : {
3059 : 0 : Stereo2 = i2->StereoIsotopic;
3060 : : }
3061 : : else
3062 : : {
3063 : 0 : Stereo2 = i2->Stereo;
3064 : : }
3065 : 0 : ret |= CompareReversedStereoINChI3(Stereo1, Stereo2, picr);
3066 : :
3067 : 0 : exit_function:
3068 : 0 : picr->flags = ret;
3069 : :
3070 : 0 : return ret;
3071 : : }
3072 : :
3073 : :
3074 : : /* message group names */
3075 : : const CMP_INCHI_MSG_GROUP CompareInchiMsgsGroup[] =
3076 : : {
3077 : : {IDGRP_ERR, " Error:"},
3078 : : {IDGRP_H, " Hydrogens:"},
3079 : : {IDGRP_MOB_GRP, " Mobile-H groups:"},
3080 : : {IDGRP_ISO_AT, " Isotopic:"},
3081 : : {IDGRP_CHARGE, " Charge(s):"},
3082 : : {IDGRP_PROTONS, " Proton balance:"},
3083 : : {IDGRP_ISO_H, " Exchangeable isotopic H:"},
3084 : : {IDGRP_SC, " Stereo centers/allenes:"},
3085 : : {IDGRP_SB, " Stereobonds/cumulenes:"},
3086 : : {IDGRP_HLAYER, " Fixed-H layer:"},
3087 : : {IDGRP_COMP, " Number of components:"},
3088 : : {IDGRP_CONV_ERR," Conversion encountered:"},
3089 : : {IDGRP_ZERO, ""}
3090 : : };
3091 : :
3092 : :
3093 : :
3094 : : /* messages */
3095 : : const CMP_INCHI_MSG CompareInchiMsgs[] =
3096 : : {
3097 : : {INCHIDIFF_PROBLEM ,IDGRP_ERR, " Wrong result" }, /*0x00000001, severe: at least one InChI does not exist */
3098 : : {INCHIDIFF_POSITION_H ,IDGRP_H, " Locations or number" }, /*0x00000002, difference in non-taut {Mobile-H} or all H {Fixed-H} location/number */
3099 : : {INCHIDIFF_MORE_FH ,IDGRP_H, " Fixed-H" }, /*0x00000004, extra fixed H */
3100 : : {INCHIDIFF_LESS_FH ,IDGRP_H, " Fixed-H" }, /*0x00000004, missing fixed H */
3101 : : {INCHIDIFF_MORE_H ,IDGRP_H, " Number" }, /*0x00000008, formulas differ in number of H */
3102 : : {INCHIDIFF_LESS_H ,IDGRP_H, " Number" }, /*0x00000008, formulas differ in number of H */
3103 : : {INCHIDIFF_NO_TAUT ,IDGRP_MOB_GRP, " Missing" }, /*0x00000010, restored structure has no taut groups while the original InChI has some */
3104 : : {INCHIDIFF_WRONG_TAUT ,IDGRP_MOB_GRP, " Falsely present" }, /*0x00000020, restored has tautomerism while the original does not have it */
3105 : : {INCHIDIFF_SINGLE_TG ,IDGRP_MOB_GRP, " One instead of multiple" }, /*0x00000040, restored has 1 taut. group while the original InChI has multiple tg */
3106 : : {INCHIDIFF_MULTIPLE_TG ,IDGRP_MOB_GRP, " Multiple instead of one" }, /*0x00000080, restored has multiple tg while the original InChI has only one tg */
3107 : : {INCHIDIFF_EXTRA_TG_ENDP,IDGRP_MOB_GRP, " Attachment points" }, /*0x00000100, extra tautomeric endpoint{s} in restored structure */
3108 : : {INCHIDIFF_MISS_TG_ENDP ,IDGRP_MOB_GRP, " Attachment points" }, /*0x00000100, one or more tg endpoint is not in the restored structure */
3109 : : {INCHIDIFF_DIFF_TG_ENDP ,IDGRP_MOB_GRP, " Attachment points" }, /*0x00000100, lists of tg endpoints are different */
3110 : : {INCHIDIFF_NUM_TG ,IDGRP_MOB_GRP, " Number" }, /*0x00000200, different number of tautomeric groups */
3111 : : {INCHIDIFF_TG ,IDGRP_MOB_GRP, " Do not match" }, /*0x00000200, different tautomeric groups */
3112 : : {INCHIDIFF_NUM_ISO_AT ,IDGRP_ISO_AT, " Atoms do not match" }, /*0x00000400, ?severe: restored struct. has different number of isotopic atoms */
3113 : : {INCHIDIFF_ISO_AT ,IDGRP_ISO_AT, " Atoms do not match" }, /*0x00000400, ?severe: restored struct. has different locations/isotopes of isotopic atoms */
3114 : : {INCHIDIFF_REM_ISO_H ,IDGRP_ISO_H, " Does not match for a component" }, /*0x00000800, isotopic H removed */
3115 : : {INCHIDIFF_MOB_ISO_H ,IDGRP_ISO_H, " Do not match" }, /*0x00001000, different number of mobile exchangeable isotopic H */
3116 : : {INCHIDIFF_CHARGE ,IDGRP_CHARGE, " Do not match" }, /*0x00002000, restored structure has different charge */
3117 : : {INCHIDIFF_REM_PROT ,IDGRP_PROTONS, " Does not match for a component" }, /*0x00004000, proton{s} removed/added from the restored structure */
3118 : : {INCHIDIFF_MOBH_PROTONS ,IDGRP_PROTONS, " Does not match" }, /*0x00008000, different proton balance */
3119 : : {INCHIDIFF_SC_INV ,IDGRP_SC, " Falsely inverted" }, /*0x00010000, restores structure has different inversion stereocenter mark */
3120 : : {INCHIDIFF_SC_PARITY ,IDGRP_SC, " Wrong parity" }, /*0x00020000, restored structure has stereoatoms or allenes with different parity */
3121 : : {INCHIDIFF_SC_EXTRA_UNDF,IDGRP_SC, " Extra undefined" }, /*0x00040000, restored structure has extra undefined stereocenter{s} */
3122 : : {INCHIDIFF_SC_EXTRA ,IDGRP_SC, " Extra known" }, /*0x00080000, restored structure has extra stereocenter{s} */
3123 : : {INCHIDIFF_SC_MISS_UNDF ,IDGRP_SC, " Missing undefined" }, /*0x00100000, restored structure has not some undefined stereocenter{s} */
3124 : : {INCHIDIFF_SC_MISS ,IDGRP_SC, " Missing known" }, /*0x00200000, restored structure has not some stereocenters that are not undefined */
3125 : : {INCHIDIFF_SB_PARITY ,IDGRP_SB, " Wrong parity" }, /*0x00400000, restored structure has stereobonds or cumulenes with different parity */
3126 : : {INCHIDIFF_SB_EXTRA_UNDF,IDGRP_SB, " Extra undefined" }, /*0x00800000, restored structure has extra undefined stereobond{s} */
3127 : : {INCHIDIFF_SB_EXTRA ,IDGRP_SB, " Missing known" }, /*0x01000000, restored structure has extra stereobond{s} */
3128 : : {INCHIDIFF_SB_MISS_UNDF ,IDGRP_SB, " Missing undefined" }, /*0x02000000, restored structure has not some undefined stereocenters */
3129 : : {INCHIDIFF_SB_MISS ,IDGRP_SB, " Missing known" }, /*0x04000000, restored structure has not some stereobonds that are not undefined */
3130 : : {INCHIDIFF_COMP_HLAYER ,IDGRP_HLAYER, " Missing or extra" }, /*0x08000000, Restored component has Mobile-H layer instead of both Mobile-H & Fixed-H or both instead of one */
3131 : : {INCHIDIFF_COMP_NUMBER ,IDGRP_COMP, " Does not match" }, /*0x10000000, wrong number of components */
3132 : : {INCHIDIFF_STR2INCHI_ERR,IDGRP_CONV_ERR," Error" }, /*0x20000000 Restored structure to InChI conversion error */
3133 : : {INCHIDIFF_ZERO ,IDGRP_ZERO, "" }
3134 : : };
3135 : :
3136 : :
3137 : : /*************************************************************************/
3138 : 0 : int AddOneMsg(char* szMsg,
3139 : : int used_len,
3140 : : int tot_len,
3141 : : const char* szAddMsg,
3142 : : const char* szDelim)
3143 : : {
3144 : 0 : const char ellip[] = "...";
3145 : 0 : int len = (int)strlen(szAddMsg);
3146 [ # # # # ]: 0 : int len_delim = (used_len && szDelim) ? strlen(szDelim) : 0;
3147 : : int len_to_copy;
3148 [ # # ]: 0 : if (len + len_delim + used_len < tot_len)
3149 : : {
3150 [ # # ]: 0 : if (len_delim)
3151 : : {
3152 : 0 : strcpy(szMsg + used_len, szDelim);
3153 : 0 : used_len += len_delim;
3154 : : }
3155 : 0 : strcpy(szMsg + used_len, szAddMsg);
3156 : 0 : used_len += len;
3157 : : }
3158 : : else
3159 : : {
3160 [ # # ]: 0 : if ((len_to_copy = (tot_len - used_len - len_delim - (int)sizeof(ellip))) > 10)
3161 : : {
3162 [ # # ]: 0 : if (len_delim)
3163 : : {
3164 : 0 : strcpy(szMsg + used_len, szDelim);
3165 : 0 : used_len += len_delim;
3166 : : }
3167 : 0 : strncpy(szMsg + used_len, szAddMsg, len_to_copy);
3168 : 0 : used_len += len_to_copy;
3169 : 0 : strcpy(szMsg + used_len, ellip);
3170 : 0 : used_len += sizeof(ellip) - 1;
3171 : : }
3172 : : }
3173 : :
3174 : 0 : return used_len;
3175 : : }
3176 : :
3177 : :
3178 : : /****************************************************************************/
3179 : 0 : int FillOutCompareMessage(char* szMsg, int nLenMsg, INCHI_MODE bits[])
3180 : : {
3181 : 0 : int bMobileH, k, n, len = (int)strlen(szMsg);
3182 : : int iPrevGrpIdx, iCurGrpIdx, bFound;
3183 : : INCHI_MODE bit;
3184 : : static const char* hdr = " Problems/mismatches:";
3185 : : char szOneMsg[256];
3186 : :
3187 : 0 : int mismatch = 0;
3188 : :
3189 [ # # # # ]: 0 : if (bits[TAUT_YES] || bits[TAUT_NON])
3190 : : {
3191 : :
3192 : 0 : mismatch = -1;
3193 : :
3194 [ # # ]: 0 : if (!strstr(szMsg, hdr))
3195 : : {
3196 : 0 : len = AddOneMsg(szMsg, len, nLenMsg, hdr, NULL);
3197 : : }
3198 : :
3199 [ # # ]: 0 : for (bMobileH = TAUT_YES; 0 <= bMobileH; bMobileH--)
3200 : : {
3201 : : /* bMobileH = TAUT_YES, TAUT_NON */
3202 : :
3203 [ # # ]: 0 : if (bits[bMobileH])
3204 : : {
3205 [ # # ]: 0 : strcpy(szOneMsg, bMobileH == TAUT_YES ? " Mobile-H(" : " Fixed-H(");
3206 : 0 : len = AddOneMsg(szMsg, len, nLenMsg, szOneMsg, NULL);
3207 : : }
3208 : :
3209 : 0 : bit = 1;
3210 : 0 : iPrevGrpIdx = -1;
3211 : :
3212 : : do
3213 : : {
3214 [ # # ]: 0 : if (bit & bits[bMobileH])
3215 : : {
3216 : : /* search for the message */
3217 : 0 : bFound = 0;
3218 [ # # # # ]: 0 : for (k = 0; CompareInchiMsgs[k].nBit != INCHIDIFF_ZERO && !bFound; k++)
3219 : : {
3220 [ # # ]: 0 : if (bit & (INCHI_MODE)CompareInchiMsgs[k].nBit)
3221 : : {
3222 : : /* message found */
3223 [ # # ]: 0 : for (n = 0; CompareInchiMsgsGroup[n].nGroupID != IDGRP_ZERO; n++)
3224 : : {
3225 [ # # ]: 0 : if (CompareInchiMsgsGroup[n].nGroupID == CompareInchiMsgs[k].nGroupID)
3226 : : {
3227 : 0 : iCurGrpIdx = n;
3228 [ # # ]: 0 : if (iCurGrpIdx != iPrevGrpIdx)
3229 : : {
3230 [ # # ]: 0 : if (iPrevGrpIdx >= 0)
3231 : : {
3232 : 0 : len = AddOneMsg(szMsg, len, nLenMsg, ";", NULL);
3233 : : }
3234 : 0 : len = AddOneMsg(szMsg, len, nLenMsg, CompareInchiMsgsGroup[iCurGrpIdx].szGroupName, NULL);
3235 : : }
3236 [ # # ]: 0 : len = AddOneMsg(szMsg, len, nLenMsg, CompareInchiMsgs[k].szMsg, iCurGrpIdx == iPrevGrpIdx ? "," : NULL);
3237 : 0 : iPrevGrpIdx = iCurGrpIdx;
3238 : 0 : bFound = 1;
3239 : 0 : break;
3240 : : }
3241 : : }
3242 : : }
3243 : : }
3244 : : }
3245 : 0 : bit <<= 1;
3246 [ # # ]: 0 : } while (bit);
3247 : :
3248 [ # # ]: 0 : if (bits[bMobileH])
3249 : : {
3250 : 0 : len = AddOneMsg(szMsg, len, nLenMsg, ")", NULL);
3251 : : }
3252 : :
3253 : : }
3254 : : }
3255 : :
3256 : 0 : return mismatch; /*len; */
3257 : : }
3258 : :
3259 : :
3260 : : #endif
|