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