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 : : #include "mode.h"
11 : : #include "mol_fmt.h"
12 : : #include "ichierr.h"
13 : : #include "util.h"
14 : : #include "strutil.h"
15 : : #include "inchi_api.h"
16 : :
17 : : #include "bcf_s.h"
18 : :
19 : : #include "logging.h" /*(@nnuk : Nauman Ullah Khan) :: Needed for logging functionality*/
20 : :
21 : : /*
22 : : Convert input molecular data to internal representation
23 : :
24 : : */
25 : :
26 : : /* Local prototypes */
27 : :
28 : : int ReadMolfileToInpAtoms(INCHI_IOSTREAM *inp_file,
29 : : int bDoNotAddH, inp_ATOM **at,
30 : : MOL_COORD **szCoord,
31 : : OAD_Polymer **polymer,
32 : : OAD_V3000 **v3000,
33 : : int treat_polymers,
34 : : int treat_NPZz,
35 : : int max_num_at,
36 : : int *num_dimensions,
37 : : int *num_bonds,
38 : : const char *pSdfLabel,
39 : : char *pSdfValue,
40 : : unsigned long *Id,
41 : : long *lMolfileNumber,
42 : : INCHI_MODE *pInpAtomFlags,
43 : : int *err,
44 : : char *pStrErr,
45 : : int bNoWarnings);
46 : : inp_ATOM *MakeInpAtomsFromMolfileData(MOL_FMT_DATA *mfdata,
47 : : int *num_atoms,
48 : : int *num_bonds,
49 : : inp_ATOM *at_inp,
50 : : int bDoNotAddH,
51 : : int *err,
52 : : char *pStrErr);
53 : : int SetInpAtomsXYZ(MOL_FMT_DATA *mfdata,
54 : : int num_atoms,
55 : : inp_ATOM *at,
56 : : int *err,
57 : : char *pStrErr);
58 : : void calculate_valences(MOL_FMT_DATA *mfdata,
59 : : inp_ATOM *at,
60 : : int *num_atoms,
61 : : int bDoNotAddH,
62 : : int *err,
63 : : char *pStrErr);
64 : :
65 : : int SetExtOrigAtDataByMolfileExtInput(MOL_FMT_DATA *mfdata,
66 : : OAD_Polymer **polymer,
67 : : OAD_V3000 **v3000,
68 : : char *pStrErr);
69 : :
70 : : /****************************************************************************
71 : : Create OrigInpData From Molfile
72 : : ****************************************************************************/
73 : 121 : int CreateOrigInpDataFromMolfile(INCHI_IOSTREAM *inp_file,
74 : : ORIG_ATOM_DATA *orig_at_data,
75 : : int bMergeAllInputStructures,
76 : : int bGetOrigCoord,
77 : : int bDoNotAddH,
78 : : int treat_polymers,
79 : : int treat_NPZz,
80 : : const char *pSdfLabel,
81 : : char *pSdfValue,
82 : : unsigned long *lSdfId,
83 : : long *lMolfileNumber,
84 : : INCHI_MODE *pInpAtomFlags,
85 : : int *err,
86 : : char *pStrErr,
87 : : int bNoWarnings)
88 : : {
89 : : int i, j, max_num_at;
90 : 121 : int num_dimensions_new = 0; /* djb-rwth: initialisation required to avoid garbage values */
91 : : int num_inp_bonds_new;
92 : : int num_inp_atoms_new;
93 : 121 : int nNumAtoms = 0;
94 : 121 : inp_ATOM *at_new = NULL;
95 : 121 : inp_ATOM *at_old = NULL;
96 : 121 : MOL_COORD *szCoordNew = NULL;
97 : 121 : MOL_COORD *szCoordOld = NULL;
98 : 121 : OAD_Polymer *polymer = NULL;
99 : 121 : OAD_V3000 *v3000 = NULL;
100 : :
101 [ + - ]: 121 : if (pStrErr)
102 : : {
103 : 121 : pStrErr[0] = '\0';
104 : : }
105 : :
106 : : /* NB: currently (v. 1.04) legacy CLI option "MERGE" is unsupported
107 : : so the loop below is always a single pass */
108 : 121 : max_num_at = MAX_ATOMS;
109 [ + - ]: 121 : if (!(*pInpAtomFlags & FLAG_SET_INP_LARGE_MOLS))
110 : : {
111 : 121 : max_num_at = NORMALLY_ALLOWED_INP_MAX_ATOMS;
112 : : }
113 : :
114 : : do /* while ( !*err && bMergeAllInputStructures ) */
115 : : {
116 : :
117 [ + - ]: 121 : at_old = orig_at_data ? orig_at_data->at : NULL; /* save pointer to the previous allocation */
118 : :
119 [ + - ]: 121 : szCoordOld = orig_at_data ? orig_at_data->szCoord : NULL;
120 : :
121 [ + - + - ]: 242 : num_inp_atoms_new = ReadMolfileToInpAtoms(inp_file, bDoNotAddH,
122 : : orig_at_data ? &at_new : NULL,
123 [ + - ]: 121 : (bGetOrigCoord && orig_at_data) ? &szCoordNew : NULL,
124 : : &polymer, &v3000,
125 : : treat_polymers, treat_NPZz,
126 : : max_num_at, &num_dimensions_new, &num_inp_bonds_new,
127 : : pSdfLabel, pSdfValue, lSdfId, lMolfileNumber,
128 : : pInpAtomFlags, err, pStrErr, bNoWarnings);
129 : :
130 [ - + - - ]: 121 : if (num_inp_atoms_new <= 0 && !*err)
131 : : {
132 : 0 : TREAT_ERR(*err, 0, "Empty structure");
133 : 0 : *err = 98;
134 : : }
135 [ + - - + ]: 121 : else if (orig_at_data && !num_inp_atoms_new &&
136 [ # # # # ]: 0 : 10 < *err && *err < 20 &&
137 [ # # # # ]: 0 : orig_at_data->num_inp_atoms > 0 &&
138 : : bMergeAllInputStructures)
139 : : {
140 : 0 : *err = 0; /* end of file */
141 : 0 : break;
142 : : }
143 [ + - + - ]: 121 : else if (num_inp_atoms_new > 0 && orig_at_data)
144 : : {
145 : : /* merge pOrigDataTmp + orig_at_data => pOrigDataTmp; */
146 : 121 : nNumAtoms = num_inp_atoms_new + orig_at_data->num_inp_atoms;
147 [ - + ]: 121 : if (nNumAtoms >= max_num_at) /*MAX_ATOMS ) */
148 : : {
149 : 0 : TREAT_ERR(*err, 0, "Too many atoms [did you forget 'LargeMolecules' switch?]");
150 : 0 : *err = 70;
151 : 0 : orig_at_data->num_inp_atoms = -1;
152 : : }
153 [ + - ]: 121 : else if (!at_old)
154 : : {
155 : : /* the first structure */
156 : 121 : orig_at_data->at = at_new;
157 : 121 : orig_at_data->szCoord = szCoordNew;
158 : 121 : at_new = NULL;
159 : 121 : szCoordNew = NULL;
160 : 121 : orig_at_data->num_inp_atoms = num_inp_atoms_new;
161 : 121 : orig_at_data->num_inp_bonds = num_inp_bonds_new;
162 : 121 : orig_at_data->num_dimensions = num_dimensions_new;
163 : : /* v 1.05 */
164 : 121 : orig_at_data->polymer = polymer;
165 : 121 : orig_at_data->v3000 = v3000;
166 : 121 : polymer = NULL;
167 : 121 : v3000 = NULL;
168 : : }
169 [ # # ]: 0 : else if ((orig_at_data->at = (inp_ATOM *)inchi_calloc(nNumAtoms, sizeof(inp_ATOM))) &&
170 [ # # # # ]: 0 : (!szCoordNew || (orig_at_data->szCoord = (MOL_COORD *)inchi_calloc(nNumAtoms, sizeof(MOL_COORD)))))
171 : : {
172 : : /* switch at_new <--> orig_at_data->at; */
173 [ # # ]: 0 : if (orig_at_data->num_inp_atoms)
174 : : {
175 : 0 : memcpy(orig_at_data->at, at_old, orig_at_data->num_inp_atoms * sizeof(orig_at_data->at[0]));
176 : : /* adjust numbering in the newly read structure */
177 [ # # ]: 0 : for (i = 0; i < num_inp_atoms_new; i++)
178 : : {
179 [ # # ]: 0 : if (at_new) /* djb-rwth: fixing a NULL pointer dereference */
180 : : {
181 [ # # ]: 0 : for (j = 0; j < at_new[i].valence; j++)
182 : : {
183 : 0 : at_new[i].neighbor[j] += orig_at_data->num_inp_atoms;
184 : : }
185 : 0 : at_new[i].orig_at_number += orig_at_data->num_inp_atoms; /* 12-19-2003 */
186 : : }
187 : : }
188 [ # # # # ]: 0 : if (orig_at_data->szCoord && szCoordOld)
189 : 0 : memcpy(orig_at_data->szCoord, szCoordOld, orig_at_data->num_inp_atoms * sizeof(MOL_COORD));
190 : : }
191 [ # # ]: 0 : if (at_old)
192 : : {
193 [ # # ]: 0 : inchi_free(at_old);
194 : 0 : at_old = NULL;
195 : : }
196 [ # # ]: 0 : if (szCoordOld)
197 : : {
198 [ # # ]: 0 : inchi_free(szCoordOld);
199 : 0 : szCoordOld = NULL;
200 : : }
201 : :
202 : : /* Copy newly read structure */
203 [ # # ]: 0 : if (at_new) /* djb-rwth: fixing a NULL pointer dereference */
204 : 0 : memcpy(orig_at_data->at + orig_at_data->num_inp_atoms, at_new, num_inp_atoms_new * sizeof(orig_at_data->at[0]));
205 [ # # # # ]: 0 : if (orig_at_data->szCoord && szCoordNew)
206 : : {
207 : 0 : memcpy(orig_at_data->szCoord + orig_at_data->num_inp_atoms,
208 : : szCoordNew,
209 : : num_inp_atoms_new * sizeof(MOL_COORD));
210 : : }
211 : :
212 : : /* Add other things */
213 : 0 : orig_at_data->num_inp_atoms += num_inp_atoms_new;
214 : 0 : orig_at_data->num_inp_bonds += num_inp_bonds_new;
215 : 0 : orig_at_data->num_dimensions = inchi_max(num_dimensions_new, orig_at_data->num_dimensions);
216 : : /* v 1.05 */
217 : 0 : orig_at_data->polymer = polymer;
218 : 0 : orig_at_data->v3000 = v3000;
219 : : }
220 : : else
221 : : {
222 : 0 : TREAT_ERR(*err, 0, "Out of RAM");
223 : 0 : *err = -1;
224 : : }
225 : : }
226 [ # # ]: 0 : else if (num_inp_atoms_new > 0)
227 : : {
228 : 0 : nNumAtoms += num_inp_atoms_new;
229 : : }
230 : :
231 [ - + ]: 121 : if (at_new)
232 : : {
233 [ # # ]: 0 : inchi_free(at_new);
234 : 0 : at_new = NULL;
235 : : }
236 [ - + ]: 121 : if (polymer)
237 : : {
238 [ # # ]: 0 : inchi_free(polymer);
239 : 0 : polymer = NULL;
240 : : }
241 [ - + ]: 121 : if (v3000)
242 : : {
243 [ # # ]: 0 : inchi_free(v3000);
244 : 0 : v3000 = NULL;
245 : : }
246 : :
247 [ + - - + ]: 121 : } while (!*err && bMergeAllInputStructures);
248 : :
249 [ - + ]: 121 : if (szCoordNew)
250 : : {
251 [ # # ]: 0 : inchi_free(szCoordNew);
252 : : }
253 [ - + ]: 121 : if (at_new)
254 : : {
255 [ # # ]: 0 : inchi_free(at_new);
256 : : }
257 : :
258 [ - + ]: 121 : if (*err)
259 : : {
260 : 0 : FreeOrigAtData(orig_at_data);
261 : : }
262 : :
263 [ - + - - : 121 : if (*err && !(10 < *err && *err < 20) && pStrErr && !pStrErr[0])
- - - - -
- ]
264 : : {
265 : 0 : TREAT_ERR(*err, 0, "Unknown error"); /* <BRKPT> */
266 : : }
267 : :
268 [ + - ]: 121 : return orig_at_data ? orig_at_data->num_inp_atoms : nNumAtoms;
269 : : }
270 : :
271 : : /****************************************************************************
272 : : ReadMolfileToInpAtoms
273 : : ****************************************************************************/
274 : 121 : int ReadMolfileToInpAtoms(INCHI_IOSTREAM *inp_file,
275 : : int bDoNotAddH,
276 : : inp_ATOM **at,
277 : : MOL_COORD **szCoord,
278 : : OAD_Polymer **polymer,
279 : : OAD_V3000 **v3000,
280 : : int treat_polymers,
281 : : int treat_NPZz,
282 : : int max_num_at,
283 : : int *num_dimensions,
284 : : int *num_bonds,
285 : : const char *pSdfLabel,
286 : : char *pSdfValue,
287 : : unsigned long *Id,
288 : : long *lMolfileNumber,
289 : : INCHI_MODE *pInpAtomFlags,
290 : : int *err,
291 : : char *pStrErr,
292 : : int bNoWarnings)
293 : : {
294 : 121 : int num_atoms = 0;
295 : 121 : MOL_FMT_DATA *mfdata = NULL;
296 : : MOL_FMT_HEADER_BLOCK OnlyHeaderBlock,
297 : 121 : *pOnlyHeaderBlock = NULL,
298 : : *pHdr;
299 : : MOL_FMT_CTAB OnlyCTab,
300 : 121 : *pOnlyCTab = NULL;
301 : 121 : char cSdfValueFirstChar = 0;
302 : :
303 [ + - ]: 121 : if (at)
304 : : {
305 : 121 : pOnlyHeaderBlock = NULL;
306 [ - + - - ]: 121 : if (*at && max_num_at)
307 : : {
308 : 0 : memset(*at, 0, max_num_at * sizeof(inp_ATOM)); /* djb-rwth: memset_s C11/Annex K variant? */
309 : : }
310 [ + - - + ]: 121 : if (szCoord && *szCoord)
311 : : {
312 [ # # ]: 0 : inchi_free(*szCoord);
313 : 0 : *szCoord = NULL;
314 : : }
315 : : }
316 : : else
317 : : {
318 : 0 : pOnlyHeaderBlock = &OnlyHeaderBlock;
319 : 0 : pOnlyCTab = &OnlyCTab;
320 : : }
321 : :
322 [ - + ]: 121 : if (pSdfValue)
323 : : {
324 : 0 : cSdfValueFirstChar = pSdfValue[0];
325 : 0 : pSdfValue[0] = '\0';
326 : : }
327 : :
328 : : /* Read mol-formatted file (MOL or SD) block */
329 : 121 : mfdata = ReadMolfile(inp_file, pOnlyHeaderBlock, pOnlyCTab, NULL != szCoord,
330 : : treat_polymers, treat_NPZz,
331 : : NULL, 0,
332 : : Id, pSdfLabel, pSdfValue, err, pStrErr, bNoWarnings);
333 : :
334 [ + - ]: 121 : pHdr = (mfdata && !pOnlyHeaderBlock)
335 : : ? &mfdata->hdr
336 [ + - - - ]: 242 : : (!mfdata && pOnlyHeaderBlock) ? pOnlyHeaderBlock
337 [ # # ]: 0 : : NULL;
338 : :
339 [ + - + - ]: 121 : if (lMolfileNumber && pHdr)
340 : : {
341 : 121 : *lMolfileNumber = MolfileExtractStrucNum(pHdr);
342 : : }
343 : :
344 [ - + - - : 121 : if (pSdfValue && !pSdfValue[0] &&
- - ]
345 [ # # # # ]: 0 : pSdfLabel && pSdfLabel[0] &&
346 : : pHdr)
347 : : {
348 [ # # ]: 0 : if (!inchi_stricmp(pSdfLabel, "MolfileName"))
349 : : {
350 : 0 : mystrncpy(pSdfValue, pHdr->molname, MAX_SDF_VALUE + 1);
351 : 0 : lrtrim(pSdfValue, NULL);
352 : : }
353 [ # # ]: 0 : else if (!inchi_stricmp(pSdfLabel, "MolfileLine2"))
354 : : {
355 : 0 : mystrncpy(pSdfValue, pHdr->line2, MAX_SDF_VALUE + 1);
356 : 0 : lrtrim(pSdfValue, NULL);
357 : : }
358 [ # # ]: 0 : else if (!inchi_stricmp(pSdfLabel, "MolfileComment"))
359 : : {
360 : 0 : mystrncpy(pSdfValue, pHdr->comment, MAX_SDF_VALUE + 1);
361 : 0 : lrtrim(pSdfValue, NULL);
362 : : }
363 [ # # # # ]: 0 : else if (!inchi_stricmp(pSdfLabel, "MolfileIntRegNo") && pHdr->internal_regno)
364 : : {
365 : 0 : sprintf(pSdfValue, "%ld", pHdr->internal_regno);
366 : : }
367 : :
368 [ # # ]: 0 : if (!pSdfValue[0])
369 : : {
370 : 0 : pSdfValue[0] = cSdfValueFirstChar;
371 : : }
372 : : }
373 : :
374 [ + - + - : 121 : if (mfdata && at && !*err)
+ - ]
375 : : {
376 : : /* (*at) either points to already allocated memory or NULL */
377 [ + - ]: 121 : if (mfdata->ctab.n_atoms <= max_num_at)
378 : : {
379 : :
380 : 121 : *at = MakeInpAtomsFromMolfileData(mfdata, &num_atoms, num_bonds,
381 : : *at, bDoNotAddH, err, pStrErr);
382 : :
383 [ + - ]: 121 : if (*err >= 0)
384 : : {
385 : 121 : *num_dimensions = SetInpAtomsXYZ(mfdata, num_atoms,
386 : : *at, err, pStrErr);
387 : :
388 [ + - ]: 121 : if (szCoord)
389 : : {
390 : 121 : *szCoord = mfdata->ctab.coords;
391 : 121 : mfdata->ctab.coords = NULL;
392 : : }
393 : :
394 : : /* Check that all atoms nos of Hs are in allowed range ( <=MAXVAL, currently 20 ) */
395 : : if (1)
396 : : {
397 : : int i;
398 [ + + ]: 923 : for (i = 0; i < num_atoms; i++)
399 : : {
400 [ - + ]: 802 : if ((*at)[i].num_iso_H[0] + (*at)[i].num_iso_H[1] + (*at)[i].num_iso_H[2] > MAXVAL)
401 : : {
402 : 0 : *err = 70 + 8;
403 : 0 : TREAT_ERR(*err, 0, "Too many hydrogens at heavy atom");
404 : 0 : num_atoms = -1;
405 : 0 : break;
406 : : }
407 : : }
408 : : }
409 : :
410 [ + - ]: 121 : if (!*err)
411 : : {
412 : 121 : *err = SetExtOrigAtDataByMolfileExtInput(mfdata, polymer, v3000, pStrErr);
413 [ - + ]: 121 : if (*err)
414 : : {
415 : : /*TREAT_ERR (*err, 0, "Error while getting extended Molfile input");*/
416 : 0 : *err = 80;
417 : 0 : num_atoms = -1;
418 : : }
419 : : }
420 : : }
421 : : else
422 : : {
423 [ # # ]: 0 : if (*err == -2) /* unk element */
424 : : {
425 : 0 : *err = 90;
426 : 0 : num_atoms = -1;
427 : : }
428 : : }
429 : : }
430 : : else
431 : : {
432 : : /* non-affordable struct size */
433 : 0 : TREAT_ERR(*err, 0, "Too many atoms [did you forget 'LargeMolecules' switch?]");
434 : 0 : *err = 70;
435 : 0 : num_atoms = -1;
436 : : }
437 : :
438 [ - + ]: 121 : if (*err > 0)
439 : : {
440 : 0 : *err += 100;
441 : : }
442 : :
443 : : /* 11-16-2004: use Chiral flag */
444 [ + - + - : 121 : if (num_atoms > 0 && at && *at && mfdata && pInpAtomFlags)
+ - + - +
- ]
445 : : {
446 [ + + ]: 121 : if (mfdata->ctab.chiral_flag)
447 : : {
448 : 8 : *pInpAtomFlags |= FLAG_INP_AT_CHIRAL;
449 : : }
450 : : else
451 : : {
452 : 113 : *pInpAtomFlags |= FLAG_INP_AT_NONCHIRAL;
453 : : }
454 : : }
455 : : }
456 : :
457 [ # # ]: 0 : else if (!at)
458 : : {
459 : 0 : num_atoms = pOnlyCTab->n_atoms;
460 : : }
461 : :
462 [ + - ]: 121 : if (!pOnlyHeaderBlock)
463 : : {
464 : 121 : FreeMolfileData(mfdata);
465 : : }
466 : :
467 : 121 : return num_atoms;
468 : : }
469 : :
470 : : /****************************************************************************
471 : : Make Inp Atoms From Molfile Data
472 : : ****************************************************************************/
473 : 121 : inp_ATOM *MakeInpAtomsFromMolfileData(MOL_FMT_DATA *mfdata,
474 : : int *num_atoms,
475 : : int *num_bonds,
476 : : inp_ATOM *at_inp,
477 : : int bDoNotAddH,
478 : : int *err,
479 : : char *pStrErr)
480 : : {
481 : 121 : inp_ATOM *at = NULL;
482 : : /* char *bond_stereo = NULL; */
483 : : AT_NUMB *p1, *p2;
484 : : int i, a1, a2, n1, n2, bonds, iso_atw_diff;
485 : : char bond_stereo, bond_type;
486 : :
487 : 121 : *err = 0;
488 : :
489 : 121 : *num_atoms = mfdata->ctab.n_atoms;
490 : 121 : *num_bonds = 0;
491 : :
492 : : /*(@nnuk : Nauman Ullah Khan) */
493 : : LOG_NO_ARGS("\n############### (L579:mol2atom.c) ################\n");
494 : : LOG_MULT_ARGS("Number of atoms : %d\n", *num_atoms);
495 : : LOG_NO_ARGS("####################################################\n");
496 : :
497 [ - + ]: 121 : if (MolfileHasNoChemStruc(mfdata))
498 : : {
499 : 0 : goto exit_function;
500 : : }
501 : :
502 : : /* Allocate memory if necessary */
503 [ - + ]: 121 : if (at_inp)
504 : : {
505 : 0 : at = at_inp;
506 : : }
507 : : else
508 : : {
509 : 121 : at = CreateInpAtom(*num_atoms);
510 [ - + ]: 121 : if (!at)
511 : : {
512 : 0 : *err = -1;
513 [ # # ]: 0 : TREAT_ERR_AND_FIN(*err, -1, exit_function, "Out of RAM");
514 : : }
515 : : }
516 : :
517 : : /* Copy atoms info */
518 : :
519 : : /*(@nnuk : Nauman Ullah Khan) */
520 : : LOG_NO_ARGS("\n##################### Atoms Data #########################\n");
521 : :
522 [ + + ]: 923 : for (i = 0; i < *num_atoms; i++)
523 : : {
524 : :
525 : 802 : mystrncpy(at[i].elname, mfdata->ctab.atoms[i].symbol, sizeof(at->elname));
526 : : /* at[i].chem_bonds_valence = mfdata->ctab.atoms[i].valence; */
527 : : /* MOLfile valence; will change */
528 : :
529 : 802 : at[i].orig_at_number = (AT_NUMB)(i + 1);
530 : 802 : at[i].iso_atw_diff = mfdata->ctab.atoms[i].mass_difference;
531 : 802 : at[i].charge = mfdata->ctab.atoms[i].charge;
532 : 802 : at[i].radical = mfdata->ctab.atoms[i].radical;
533 : :
534 : : /* see SetInpAtomXYZ()
535 : : at[i].x = mfdata->ctab.atoms[i].fx;
536 : : at[i].y = mfdata->ctab.atoms[i].fy;
537 : : at[i].z = mfdata->ctab.atoms[i].fz;
538 : : */
539 : :
540 : 802 : iso_atw_diff = mfdata->ctab.atoms[i].mass_difference;
541 : :
542 [ + - - + ]: 802 : at[i].iso_atw_diff = iso_atw_diff == ZERO_ATW_DIFF
543 : : ? 1
544 : 0 : : iso_atw_diff > 0 ? iso_atw_diff + 1
545 : : : iso_atw_diff;
546 : :
547 : : #if (SINGLET_IS_TRIPLET == 1)
548 [ - + ]: 802 : if (at[i].radical == RADICAL_SINGLET)
549 : : {
550 : 0 : at[i].radical = RADICAL_TRIPLET;
551 : : }
552 : : #endif
553 : : #if (bRELEASE_VERSION != 1)
554 : : if (isdigit(at[i].elname[0]))
555 : : { /* for testing */
556 : : mystrncpy(at[i].elname, "C", sizeof(at->elname));
557 : : }
558 : : #endif
559 : :
560 [ - + ]: 802 : if (ERR_ELEM == (n1 = get_periodic_table_number(at[i].elname)))
561 : : {
562 : : /* Case when elname contains more than 1 element: extract number of H if possible */
563 : 0 : at[i].num_H = extract_H_atoms(at[i].elname, at[i].num_iso_H);
564 : :
565 [ # # # # ]: 0 : if (!at[i].elname[0] && NUMH(at, i))
566 : : {
567 : : /* alias contains only H. Added 2004-07-21, fixed 2004-07-22
568 : : * move the heaviest isotope to the "central atom"
569 : : * Note: this must be consistent with H-H treatment in remove_terminal_HDT()
570 : : */
571 : 0 : strcpy(at[i].elname, "H");
572 [ # # ]: 0 : if (NUM_ISO_H(at, i))
573 : : {
574 : : int j;
575 [ # # ]: 0 : for (j = NUM_H_ISOTOPES - 1; 0 <= j; j--)
576 : : {
577 [ # # ]: 0 : if (at[i].num_iso_H[j])
578 : : {
579 : 0 : at[i].num_iso_H[j]--;
580 : 0 : at[i].iso_atw_diff = 1 + j;
581 : 0 : break;
582 : : }
583 : : }
584 : : }
585 : : else
586 : : {
587 : 0 : at[i].num_H--;
588 : : }
589 : : }
590 [ # # ]: 0 : if (ERR_ELEM == (n1 = get_periodic_table_number(at[i].elname)))
591 : : {
592 : 0 : n1 = 0;
593 : : }
594 : : } /* if ( ERR_ELEM == */
595 : :
596 : 802 : at[i].el_number = (U_CHAR)n1;
597 [ - + ]: 802 : if (!n1)
598 : : {
599 : 0 : *err = -2;
600 [ # # ]: 0 : TREAT_ERR(*err, -2, "Unknown element(s):");
601 [ # # ]: 0 : TREAT_ERR_AND_FIN(*err, -2, exit_function, at[i].elname);
602 : : }
603 : : else
604 : : {
605 : : /* replace explicit D or T with isotopic H (added 2003-06-02) */
606 [ + + + - ]: 802 : if ((int)EL_NUMBER_H == n1 && !at[i].iso_atw_diff)
607 : : {
608 [ - - + ]: 2 : switch (at[i].elname[0])
609 : : {
610 : 0 : case 'D':
611 : 0 : at[i].iso_atw_diff = 2;
612 : 0 : mystrncpy(at[i].elname, "H", sizeof(at->elname));
613 : 0 : break;
614 : 0 : case 'T':
615 : 0 : at[i].iso_atw_diff = 3;
616 : 0 : mystrncpy(at[i].elname, "H", sizeof(at->elname));
617 : 0 : break;
618 : : }
619 : : }
620 : : }
621 : :
622 : : /*(@nnuk : Nauman Ullah Khan) */
623 : : LOG_NO_ARGS("\n############################## (L714:mol2atom.c) #####################################\n");
624 : : LOG_MULT_ARGS("Atom %d: element=%s, x=%f, y=%f, z=%f, chrg=%d, rad=%d, iso=%d\n", i, at[i].elname, at[i].x, at[i].y, at[i].z, at[i].charge, at[i].radical, at[i].iso_atw_diff);
625 : : LOG_NO_ARGS("########################################################################################\n");
626 : :
627 : : } /* eof copy atom info */
628 : :
629 : : /*---------------- stereo information notes. ------------------------
630 : :
631 : : Currently: 1. stereo sign
632 : : ========= --------------
633 : : MOLfile (atom number = MOLfile atom number - 1, no stdata as an intermediate)
634 : : | if mfdata->ctab.bonds[i].atnum1 < mfdata->ctab.bonds[i].atnum2
635 : : v then
636 : : inp_ATOM stereo > 0
637 : : else
638 : : stereo < 0
639 : :
640 : : 2. neighbor z-coordinate
641 : : ------------------------
642 : : neighbor z-coord > 0 for Up if sign(stdata_bond_no) = sign(at[i].neighbor[j]-i)
643 : :
644 : : --------------------------------------------------------------------*/
645 : :
646 : : /* Copy bond info */
647 : :
648 : : LOG_NO_ARGS("\n######################### Bonds Data ###############################\n");
649 : :
650 [ + + ]: 817 : for (i = 0, bonds = 0; i < mfdata->ctab.n_bonds; i++)
651 : : {
652 : :
653 : 696 : bond_stereo = mfdata->ctab.bonds[i].bond_stereo;
654 : 696 : bond_type = mfdata->ctab.bonds[i].bond_type;
655 : :
656 : 696 : a1 = mfdata->ctab.bonds[i].atnum1 - 1;
657 : 696 : a2 = mfdata->ctab.bonds[i].atnum2 - 1;
658 : :
659 [ + - + - : 696 : if (a1 < 0 || a1 >= *num_atoms ||
+ - ]
660 [ + - - + ]: 696 : a2 < 0 || a2 >= *num_atoms ||
661 : : a1 == a2)
662 : : {
663 : 0 : *err |= 1; /* bond for impossible atom number(s); ignored */
664 : 0 : TREAT_ERR(*err, 0, "Bond to nonexistent atom");
665 : 0 : continue;
666 : : }
667 : :
668 : : /* check for multiple bonds between same atoms */
669 : 696 : p1 = is_in_the_list(at[a1].neighbor, (AT_NUMB)a2, at[a1].valence);
670 : 696 : p2 = is_in_the_list(at[a2].neighbor, (AT_NUMB)a1, at[a2].valence);
671 : :
672 : : /*(@nnuk : Nauman Ullah Khan) */
673 : : LOG_NO_ARGS("\n################## (L771:mol2atom.c) ##################\n");
674 : : LOG_MULT_ARGS("Valence = %d\n", at[i].valence);
675 : : LOG_NO_ARGS("#########################################################\n");
676 : :
677 [ + - - + : 696 : if ((p1 || p2) && (p1 || at[a1].valence < MAXVAL) && (p2 || at[a2].valence < MAXVAL))
- - - - -
- - - ]
678 : : {
679 [ # # ]: 0 : n1 = p1 ? (p1 - at[a1].neighbor) : at[a1].valence++;
680 [ # # ]: 0 : n2 = p2 ? (p2 - at[a2].neighbor) : at[a2].valence++;
681 : 0 : TREAT_ERR(*err, 0, "Multiple bonds between two atoms");
682 : 0 : *err |= 2; /* multiple bonds between atoms */
683 : : }
684 [ + - + - : 696 : else if (!p1 && !p2 && at[a1].valence < MAXVAL && at[a2].valence < MAXVAL)
+ - + - ]
685 : : {
686 : 696 : n1 = at[a1].valence++;
687 : 696 : n2 = at[a2].valence++;
688 : 696 : bonds++;
689 : : }
690 : : else
691 : 0 : {
692 : : char szMsg[64];
693 : 0 : *err |= 4; /* too large number of bonds. Some bonds ignored. */
694 : 0 : sprintf(szMsg, "Atom '%s' has more than %d bonds",
695 [ # # ]: 0 : at[a1].valence >= MAXVAL ? at[a1].elname : at[a2].elname, MAXVAL);
696 : 0 : TREAT_ERR(*err, 0, szMsg);
697 : 0 : continue;
698 : : }
699 : :
700 : : /* (@nnuk) : Bond type 9 (coordinative bond) recognized by InChI now */
701 [ + - + + : 696 : if (bond_type < MIN_INPUT_BOND_TYPE || (bond_type > MAX_INPUT_BOND_TYPE && bond_type != COORDINATIVE_BOND))
- + ]
702 : : {
703 : : char szBondType[16];
704 : 0 : sprintf(szBondType, "%d", bond_type);
705 : 0 : bond_type = 1;
706 : 0 : TREAT_ERR(*err, 0, "Unrecognized bond type:");
707 : 0 : TREAT_ERR(*err, 0, szBondType);
708 : 0 : *err |= 8; /* Unrecognized Bond type replaced with single bond */
709 : : }
710 : :
711 : : /* bond type */
712 [ + - + - ]: 696 : if (n1 < MAXVAL && n2 < MAXVAL) /* djb-rwth: buffer overrun prevention */
713 : : {
714 : 696 : at[a1].bond_type[n1] = at[a2].bond_type[n2] = bond_type;
715 : :
716 : : /* connection */
717 : 696 : at[a1].neighbor[n1] = (AT_NUMB)a2;
718 : 696 : at[a2].neighbor[n2] = (AT_NUMB)a1;
719 : :
720 : : /* stereo */
721 [ - + ]: 696 : if (bond_stereo == INPUT_STEREO_DBLE_EITHER /* 3 */)
722 : : {
723 : 0 : at[a1].bond_stereo[n1] =
724 : 0 : at[a2].bond_stereo[n2] =
725 : : STEREO_DBLE_EITHER;
726 : : }
727 [ + + + - ]: 696 : else if (bond_stereo == INPUT_STEREO_SNGL_UP || /* 1 */
728 [ + + ]: 547 : bond_stereo == INPUT_STEREO_SNGL_EITHER || /* 4 */
729 : : bond_stereo == INPUT_STEREO_SNGL_DOWN /* 6 */)
730 : 181 : {
731 : : char cStereo;
732 [ + - + - ]: 181 : switch (bond_stereo)
733 : : {
734 : 149 : case INPUT_STEREO_SNGL_UP:
735 : 149 : cStereo = STEREO_SNGL_UP;
736 : 149 : break;
737 : 0 : case INPUT_STEREO_SNGL_EITHER:
738 : 0 : cStereo = STEREO_SNGL_EITHER;
739 : 0 : break;
740 : 32 : case INPUT_STEREO_SNGL_DOWN:
741 : 32 : cStereo = STEREO_SNGL_DOWN;
742 : 32 : break;
743 : : }
744 : 181 : at[a1].bond_stereo[n1] = cStereo; /* >0: the wedge (pointed) end is at this atom, a1 */
745 : 181 : at[a2].bond_stereo[n2] = -cStereo; /* <0: the wedge (pointed) end is at the opposite atom, a1 */
746 : : }
747 [ - + ]: 515 : else if (bond_stereo)
748 : : {
749 : 0 : *err |= 16; /* Ignored unrecognized Bond stereo */
750 : 0 : TREAT_ERR(*err, 0, "Unrecognized bond stereo");
751 : 0 : continue;
752 : : }
753 : : }
754 : :
755 : : /*(@nnuk : Nauman Ullah Khan) */
756 : : LOG_NO_ARGS("\n################ (L862:mol2atom.c) ##################\n");
757 : : LOG_MULT_ARGS("Bond %d: atom1=%d, atom2=%d, type=%d, stereo=%d\n", i, a1, a2, bond_type, bond_stereo);
758 : : LOG_NO_ARGS("#######################################################\n");
759 : :
760 : : } /* eof copy bond info */
761 : :
762 : 121 : *num_bonds = bonds;
763 : :
764 : : /* (@nnuk) : Handling haptic bonds */
765 [ + + + + ]: 121 : if (mfdata->ctab.v3000 && mfdata->ctab.v3000->n_haptic_bonds > 0 &&
766 [ + - + - ]: 2 : mfdata->ctab.v3000->haptic_bonds && mfdata->ctab.v3000->haptic_bonds->lists)
767 : : {
768 [ + + ]: 5 : for (i = 0; i < mfdata->ctab.v3000->n_haptic_bonds; i++)
769 : : {
770 : 3 : int* list = mfdata->ctab.v3000->haptic_bonds->lists[i];
771 [ - + ]: 3 : if (!list)
772 : : {
773 : 0 : TREAT_ERR(*err, 0, "Null haptic bond list");
774 : 0 : continue;
775 : : }
776 : :
777 : 3 : int bond_type = list[0];
778 : 3 : int central_atom = list[1];
779 : 3 : int endpoint_count = list[2];
780 : 3 : int central_idx = central_atom - 1;
781 : :
782 : 3 : int endpoints_added = 0;
783 : :
784 [ + + ]: 15 : for (int j = 0; j < endpoint_count; j++)
785 : : {
786 : 12 : int n_endpoint = list[3 + j];
787 : 12 : int endpoint_idx = n_endpoint - 1;
788 : :
789 : 12 : int central_at_num = at[central_idx].valence;
790 : 12 : int endpoint_at_num = at[endpoint_idx].valence;
791 : :
792 : 12 : p1 = is_in_the_list(at[central_idx].neighbor, (AT_NUMB)endpoint_idx, central_at_num);
793 : 12 : p2 = is_in_the_list(at[endpoint_idx].neighbor, (AT_NUMB)central_idx, endpoint_at_num);
794 : :
795 [ + - - + ]: 12 : if (central_at_num >= MAXVAL || endpoint_at_num >= MAXVAL)
796 : : {
797 : 0 : fprintf(stderr, "Atom number exceeded when trying to add haptic bond between atoms %d and %d\n", central_idx, endpoint_idx);
798 : 0 : continue;
799 : : }
800 : :
801 : 12 : at[central_idx].neighbor[central_at_num] = endpoint_idx;
802 : 12 : at[central_idx].bond_type[central_at_num] = COORDINATIVE_BOND;
803 : 12 : at[central_idx].bond_stereo[central_at_num] = 0;
804 : 12 : at[central_idx].valence++;
805 : :
806 : 12 : at[endpoint_idx].neighbor[endpoint_at_num] = central_idx;
807 : 12 : at[endpoint_idx].bond_type[endpoint_at_num] = COORDINATIVE_BOND;
808 : 12 : at[endpoint_idx].bond_stereo[endpoint_at_num] = 0;
809 : 12 : at[endpoint_idx].valence++;
810 : :
811 : 12 : bonds++;
812 : 12 : endpoints_added++;
813 : : }
814 : : }
815 : :
816 : 2 : *num_bonds = bonds;
817 : : }
818 : :
819 : : /* special valences */
820 : 121 : calculate_valences(mfdata, at, num_atoms, bDoNotAddH, err, pStrErr);
821 : :
822 : 121 : exit_function:;
823 : :
824 : 121 : return at;
825 : : }
826 : :
827 : : /****************************************************************************/
828 : 121 : void calculate_valences(MOL_FMT_DATA *mfdata,
829 : : inp_ATOM *at,
830 : : int *num_atoms,
831 : : int bDoNotAddH,
832 : : int *err,
833 : : char *pStrErr)
834 : : {
835 : : int bNonMetal;
836 : : int a1, a2, n1, n2, valence;
837 : : AT_NUMB *p1;
838 : 121 : int* coord_bonds_count = NULL; /* (@nnuk) :: Array to track coordination bonds for non - metals */
839 : :
840 : : /* (@nnuk) :: Allocate memory for coordination bonds count */
841 : 121 : coord_bonds_count = (int*)inchi_calloc(*num_atoms, sizeof(int));
842 [ - + ]: 121 : if (!coord_bonds_count)
843 : : {
844 : 0 : *err = -1;
845 : 0 : TREAT_ERR(*err, 0, "Memory allocation failed for coord_bonds_count");
846 : 0 : return;
847 : : }
848 : :
849 : : /* (@nnuk : Nauman Ullah Khan)
850 : : * Count coordination bonds (type 9) for each non-metal atom
851 : : * Iterates through all atoms and their bonds to identify coordination bonds
852 : : * and tracks count per non-metal atom in coord_bonds_count array
853 : : */
854 [ + + ]: 923 : for (a1 = 0; a1 < *num_atoms; a1++)
855 : : {
856 [ + + ]: 802 : if (!is_el_a_metal(at[a1].el_number))
857 : : {
858 [ + + ]: 2099 : for (n1 = 0; n1 < at[a1].valence; n1++)
859 : : {
860 [ + + ]: 1352 : if (at[a1].bond_type[n1] == COORDINATIVE_BOND)
861 : : {
862 : 23 : coord_bonds_count[a1]++;
863 : : }
864 : : }
865 : : }
866 : : }
867 : :
868 : : /* special valences */
869 : :
870 [ + + ]: 363 : for (bNonMetal = 0; bNonMetal < 2; bNonMetal++)
871 : : {
872 [ + + ]: 1846 : for (a1 = 0; a1 < *num_atoms; a1++)
873 : : {
874 : : int num_bond_type[MAX_INPUT_BOND_TYPE - MIN_INPUT_BOND_TYPE + 1],
875 : : bond_type,
876 : : bHasMetalNeighbor;
877 : : /* should the "!=" be replaced with "==" ??? */
878 [ + + ]: 1604 : if (bNonMetal == is_el_a_metal(at[a1].el_number))
879 : : {
880 : : /* first process all metals, after that all non-metals */
881 : 802 : continue;
882 : : }
883 : :
884 : 802 : memset(num_bond_type, 0, sizeof(num_bond_type)); /* djb-rwth: memset_s C11/Annex K variant? */
885 : :
886 : : /* valence = at[a1].chem_bonds_valence; */ /* save atom valence if available */
887 : : /* 2006-08-31: fix for uncharged >N(IV)- in an aromatic ring */
888 : :
889 : 802 : valence =
890 [ + - ]: 802 : (mfdata && mfdata->ctab.atoms) ? mfdata->ctab.atoms[a1].valence
891 [ + - ]: 1604 : : at[a1].chem_bonds_valence;
892 : :
893 : 802 : at[a1].chem_bonds_valence = 0;
894 : 802 : bHasMetalNeighbor = 0;
895 [ + + ]: 2218 : for (n1 = 0; n1 < at[a1].valence; n1++)
896 : : {
897 : 1416 : bond_type = at[a1].bond_type[n1] - MIN_INPUT_BOND_TYPE;
898 [ + - + + ]: 1416 : if (bond_type < 0 || bond_type > MAX_INPUT_BOND_TYPE - MIN_INPUT_BOND_TYPE)
899 : : {
900 : 46 : bond_type = 0;
901 : 46 : TREAT_ERR(*err, 0, "Unknown bond type or a COORDINATIVE BOND (9) in MOLfile assigned as a single bond"); /* @nnuk : Coordinative bond is accepted now and is assigned as a single bond */
902 : : }
903 : 1416 : num_bond_type[bond_type]++;
904 : : /* -- too a radical solution -- removed from next to ver 1.12B --- */
905 : : }
906 : :
907 : 802 : for (n1 = 0;
908 [ + + + - ]: 3208 : MIN_INPUT_BOND_TYPE + n1 <= 3 &&
909 : : MIN_INPUT_BOND_TYPE + n1 <= MAX_INPUT_BOND_TYPE;
910 : 2406 : n1++)
911 : : {
912 : : /* add all bond orders except for "aromatic" bonds */
913 : 2406 : at[a1].chem_bonds_valence += (MIN_INPUT_BOND_TYPE + n1) * num_bond_type[n1];
914 : : }
915 : :
916 : 802 : n2 = 0; /* djb-rwth: ignoring LLVM warning: value used */
917 : 802 : if (MIN_INPUT_BOND_TYPE <= BOND_TYPE_ALTERN &&
918 : : BOND_TYPE_ALTERN <= MAX_INPUT_BOND_TYPE &&
919 [ - + ]: 802 : (n2 = num_bond_type[BOND_TYPE_ALTERN - MIN_INPUT_BOND_TYPE]))
920 : : {
921 : : /* accept input aromatic bonds for now */
922 [ # # # ]: 0 : switch (n2)
923 : : {
924 : 0 : case 2:
925 : 0 : at[a1].chem_bonds_valence += 3; /* =A- */
926 : 0 : break;
927 : 0 : case 3:
928 : 0 : at[a1].chem_bonds_valence += 4; /* =A< */
929 : 0 : break;
930 : 0 : default:
931 : : /* if 1 or >= 4 aromatic bonds then replace */
932 : : /* such bonds with single bonds */
933 : : /* and detect an error in the input structure */
934 [ # # ]: 0 : for (n1 = 0; n1 < at[a1].valence; n1++)
935 : : {
936 [ # # ]: 0 : if (at[a1].bond_type[n1] == BOND_TYPE_ALTERN)
937 : : {
938 : 0 : a2 = at[a1].neighbor[n1];
939 : 0 : p1 = is_in_the_list(at[a2].neighbor, (AT_NUMB)a1,
940 : 0 : at[a2].valence);
941 [ # # ]: 0 : if (p1)
942 : : {
943 : 0 : at[a1].bond_type[n1] =
944 : 0 : at[a2].bond_type[p1 - at[a2].neighbor] = BOND_TYPE_SINGLE;
945 : : }
946 : : else
947 : : {
948 : 0 : *err = -2; /* Program error */
949 : 0 : TREAT_ERR(*err, 0, "Program error interpreting MOLfile");
950 : 0 : return; /* no structure */
951 : : }
952 : : }
953 : : }
954 : :
955 : 0 : at[a1].chem_bonds_valence += n2;
956 : 0 : *err |= 32;
957 : 0 : TREAT_ERR(*err, 0, "Atom has 1 or more than 3 aromatic bonds");
958 : 0 : n2 = 0;
959 : 0 : break;
960 : : }
961 : : }
962 : :
963 [ - + - - ]: 802 : if (n2 && !valence)
964 : 0 : {
965 : : /* atom has aromatic bonds AND the chemical valence is not known */
966 : :
967 : 0 : int num_H = NUMH(at, a1);
968 : : /* bug fix 2006-08-25: aliased H result in num_H > 0 */
969 : : /* => wrong call to detect_unusual_el_valence() */
970 : 0 : int chem_valence = at[a1].chem_bonds_valence /*+ num_H*/;
971 : :
972 : : int bUnusualValenceArom =
973 : 0 : detect_unusual_el_valence((int)at[a1].el_number, at[a1].charge,
974 : 0 : at[a1].radical, chem_valence,
975 : 0 : num_H, at[a1].valence);
976 : : int bUnusualValenceNoArom =
977 : 0 : detect_unusual_el_valence((int)at[a1].el_number, at[a1].charge,
978 : 0 : at[a1].radical, chem_valence - 1,
979 : 0 : num_H, at[a1].valence);
980 : :
981 : : #if (CHECK_AROMBOND2ALT == 1)
982 [ # # # # ]: 0 : if (bUnusualValenceArom &&
983 [ # # ]: 0 : !bUnusualValenceNoArom &&
984 : 0 : 0 == nBondsValToMetal(at, a1))
985 : : #else
986 : : if (bUnusualValenceArom && !bUnusualValenceNoArom)
987 : : #endif
988 : : {
989 : : /* typically NH in 5-member aromatic ring */
990 : 0 : at[a1].chem_bonds_valence--;
991 : : }
992 : : }
993 [ - + - - ]: 802 : else if (n2 && valence)
994 : : {
995 : : /* atom has aromatic bonds AND the chemical valence is known */
996 : 0 : int num_H = NUMH(at, a1);
997 : 0 : int chem_valence = at[a1].chem_bonds_valence + num_H;
998 [ # # ]: 0 : if (valence == chem_valence - 1)
999 : : {
1000 : : /* typically NH in 5-member aromatic ring */
1001 : 0 : at[a1].chem_bonds_valence--;
1002 : : }
1003 : : }
1004 : :
1005 : : /* Set number of hydrogen atoms */
1006 [ + - ]: 802 : if (mfdata)
1007 : : {
1008 : 802 : int additional_H = coord_bonds_count[a1];
1009 : :
1010 : 802 : int newValence = -1;
1011 : :
1012 [ + + + + ]: 802 : if (!is_el_a_metal(at[a1].el_number) && additional_H)
1013 : 22 : {
1014 : : /* (@fbaensch) Non-metal donor of one or more coordinative (type 9)
1015 : : * bonds. Treat the MOLfile VAL field as the donor's covalent
1016 : : * valence VALUE (consistent with the else-branch below), falling
1017 : : * back to the element's standard valence when VAL is 0. Then add
1018 : : * one unit per coordinative bond so the dative bonds do not consume
1019 : : * hydrogen-filling slots: num_H = base_val - (covalent bonds present).
1020 : : *
1021 : : * NOTE for input authors: a type-9 bond models a NEUTRAL lone-pair
1022 : : * donor. For a coordinative bond to an ANIONIC donor (e.g. the O of
1023 : : * an M-OH), set the donor's covalent valence via the VAL field
1024 : : * (and/or its formal charge); otherwise the donor is completed to
1025 : : * its neutral valence (e.g. O -> H2O). A genuinely ionic M-O(H)
1026 : : * bond such as NaOH is best drawn with a plain single bond - the
1027 : : * standard metal disconnection already yields Na+ + OH-. */
1028 : 22 : int base_val = mfdata->ctab.atoms[a1].valence;
1029 [ + + ]: 22 : if (!base_val)
1030 : : {
1031 : 19 : base_val = get_el_valence(at[a1].el_number, at[a1].charge, 0);
1032 : : }
1033 : 22 : newValence = base_val + additional_H;
1034 : : }
1035 : : else
1036 : : {
1037 : : /* If the atom is a metal or has no coordination bonds, use the valence defined in input file */
1038 : 780 : newValence = mfdata->ctab.atoms[a1].valence;
1039 : : }
1040 : :
1041 : 802 : at[a1].num_H = get_num_H(at[a1].elname,
1042 : 802 : at[a1].num_H,
1043 : 802 : at[a1].num_iso_H,
1044 : 802 : at[a1].charge, at[a1].radical,
1045 : 802 : at[a1].chem_bonds_valence,
1046 : : /*mfdata->ctab.atoms[a1].valence,*/
1047 : : newValence, /* instead of valence */ /* (@Felix Bänsch)(@Gerd Blanke)(@nnuk) : The valence stated in the mol file is considerd here. A value of 0 means use default value for this element. */
1048 : 802 : mfdata->ctab.atoms[a1].atom_aliased_flag,
1049 : : bDoNotAddH,
1050 : : bHasMetalNeighbor);
1051 : : }
1052 : : }
1053 : : } /* for ( bNonMetal = ... */
1054 : :
1055 : : /* (@nnuk) : Free allocated memory */
1056 : 121 : free(coord_bonds_count);
1057 : :
1058 : 121 : return;
1059 : : }
1060 : :
1061 : : /****************************************************************************/
1062 : 121 : int SetInpAtomsXYZ(MOL_FMT_DATA *mfdata,
1063 : : int num_atoms,
1064 : : inp_ATOM *at,
1065 : : int *err,
1066 : : char *pStrErr)
1067 : : {
1068 : 121 : int i, num_dimensions = 0;
1069 : :
1070 : : #if (NORMALIZE_INP_COORD == 1)
1071 : : int do_scale_xyz = 1;
1072 : : #else
1073 : 121 : int do_scale_xyz = 0;
1074 : : #endif
1075 : : double x0, y0, z0, xmin, ymin, zmin, scaler;
1076 : :
1077 : 121 : num_dimensions = MolfileGetXYZDimAndNormFactors(mfdata, do_scale_xyz,
1078 : : &x0, &y0, &z0,
1079 : : &xmin, &ymin, &zmin,
1080 : : &scaler, err, pStrErr);
1081 : :
1082 [ + + ]: 121 : if (num_dimensions == 0)
1083 : : {
1084 : 48 : goto exit_function;
1085 : : }
1086 : :
1087 [ + + ]: 827 : for (i = 0; i < num_atoms; i++)
1088 : : {
1089 : :
1090 : 754 : double x = mfdata->ctab.atoms[i].fx;
1091 : 754 : double y = mfdata->ctab.atoms[i].fy;
1092 : 754 : double z = mfdata->ctab.atoms[i].fz;
1093 : :
1094 [ + - ]: 754 : if (!do_scale_xyz)
1095 : : {
1096 : 754 : at[i].x = x;
1097 : 754 : at[i].y = y;
1098 : 754 : at[i].z = z;
1099 : : }
1100 : : else
1101 : : {
1102 : 0 : x = (x - xmin) * scaler + x0;
1103 : 0 : y = (y - ymin) * scaler + y0;
1104 : 0 : z = (z - zmin) * scaler + z0;
1105 : : /* floor() behavior is not well defined for negative arguments.
1106 : : * Use positive arguments only to get nearest integer.
1107 : : */
1108 [ # # ]: 0 : at[i].x = (x >= 0.0) ? (int)floor(x + 0.5) : -(int)floor(-x + 0.5);
1109 [ # # ]: 0 : at[i].y = (y >= 0.0) ? (int)floor(y + 0.5) : -(int)floor(-y + 0.5);
1110 [ # # ]: 0 : at[i].z = (z >= 0.0) ? (int)floor(z + 0.5) : -(int)floor(-z + 0.5);
1111 : : }
1112 : : }
1113 : :
1114 : 73 : exit_function:;
1115 : :
1116 : 121 : return num_dimensions;
1117 : : }
1118 : :
1119 : : /****************************************************************************/
1120 : 641 : inp_ATOM *CreateInpAtom(int num_atoms)
1121 : : {
1122 : 641 : void *p = NULL;
1123 [ + - ]: 641 : if (num_atoms >= 0)
1124 : : {
1125 : 641 : p = inchi_calloc(num_atoms, sizeof(inp_ATOM));
1126 : : }
1127 : :
1128 : : // void *p = inchi_calloc(num_atoms, sizeof(inp_ATOM));
1129 : 641 : return (inp_ATOM *)p;
1130 : : }
1131 : :
1132 : : /****************************************************************************/
1133 : 3214 : void FreeInpAtom(inp_ATOM **at)
1134 : : {
1135 [ + - + + ]: 3214 : if (at && *at)
1136 : : {
1137 [ + - ]: 764 : inchi_free(*at);
1138 : 764 : *at = NULL;
1139 : : }
1140 : :
1141 : 3214 : return;
1142 : : }
1143 : :
1144 : : /****************************************************************************/
1145 : 979 : void FreeInpAtomData(INP_ATOM_DATA *inp_at_data)
1146 : : {
1147 [ + - ]: 979 : if (inp_at_data)
1148 : : {
1149 : 979 : FreeInpAtom(&inp_at_data->at);
1150 : 979 : FreeInpAtom(&inp_at_data->at_fixed_bonds);
1151 : :
1152 : : /*@nnuk*/
1153 [ + + ]: 979 : if (inp_at_data->keep_explicit_HDT)
1154 : : {
1155 [ + - ]: 2 : inchi_free(inp_at_data->keep_explicit_HDT);
1156 : 2 : inp_at_data->keep_explicit_HDT = NULL;
1157 : : }
1158 : :
1159 : 979 : memset(inp_at_data, 0, sizeof(*inp_at_data)); /* djb-rwth: memset_s C11/Annex K variant? */
1160 : : }
1161 : :
1162 : 979 : return;
1163 : : }
1164 : :
1165 : : /****************************************************************************/
1166 : 322 : int CreateInpAtomData(INP_ATOM_DATA *inp_at_data,
1167 : : int num_atoms,
1168 : : int create_at_fixed_bonds)
1169 : : {
1170 : 322 : FreeInpAtomData(inp_at_data);
1171 : :
1172 [ + - + + ]: 322 : if ((inp_at_data->at = CreateInpAtom(num_atoms)) &&
1173 [ + - ]: 161 : (!create_at_fixed_bonds || (inp_at_data->at_fixed_bonds = CreateInpAtom(num_atoms))))
1174 : : {
1175 : 322 : inp_at_data->num_at = num_atoms;
1176 : 322 : return 1;
1177 : : }
1178 : :
1179 : 0 : FreeInpAtomData(inp_at_data);
1180 : :
1181 : 0 : return 0;
1182 : : }
1183 : :
1184 : : /****************************************************************************/
1185 : 769 : void FreeCompAtomData(COMP_ATOM_DATA *inp_at_data)
1186 : : {
1187 : 769 : FreeInpAtom(&inp_at_data->at);
1188 : :
1189 [ + + ]: 769 : if (inp_at_data->nOffsetAtAndH)
1190 : : {
1191 [ + - ]: 26 : inchi_free(inp_at_data->nOffsetAtAndH);
1192 : : }
1193 : 769 : memset(inp_at_data, 0, sizeof(*inp_at_data)); /* djb-rwth: memset_s C11/Annex K variant? */
1194 : 769 : }
1195 : :
1196 : : #ifndef TARGET_API_LIB
1197 : :
1198 : : /****************************************************************************/
1199 : : int CreateCompAtomData(COMP_ATOM_DATA *inp_at_data,
1200 : : int num_atoms,
1201 : : int num_components,
1202 : : int bIntermediateTaut)
1203 : : {
1204 : : FreeCompAtomData(inp_at_data);
1205 : :
1206 : : if ((inp_at_data->at = CreateInpAtom(num_atoms)) &&
1207 : : (num_components <= 1 || bIntermediateTaut ||
1208 : : (inp_at_data->nOffsetAtAndH = (AT_NUMB *)inchi_calloc(2 * ((long long)num_components + 1), sizeof(inp_at_data->nOffsetAtAndH[0]))))) /* djb-rwth: cast operator added */
1209 : : {
1210 : : inp_at_data->num_at = num_atoms;
1211 : : inp_at_data->num_components = (num_components > 1) ? num_components : 0;
1212 : : return 1;
1213 : : }
1214 : :
1215 : : FreeCompAtomData(inp_at_data);
1216 : :
1217 : : return 0;
1218 : : }
1219 : : #endif
1220 : :
1221 : : #ifndef COMPILE_ANSI_ONLY
1222 : :
1223 : : /****************************************************************************/
1224 : : void FreeInfAtom(inf_ATOM **at)
1225 : : {
1226 : : if (at && *at)
1227 : : {
1228 : : inchi_free(*at);
1229 : : *at = NULL;
1230 : : }
1231 : : return;
1232 : : }
1233 : :
1234 : : /****************************************************************************/
1235 : : inf_ATOM *CreateInfAtom(int num_atoms)
1236 : : {
1237 : : return (inf_ATOM *)inchi_calloc(num_atoms, sizeof(inf_ATOM));
1238 : : }
1239 : :
1240 : : /****************************************************************************/
1241 : : void FreeInfoAtomData(INF_ATOM_DATA *inf_at_data)
1242 : : {
1243 : : FreeInfAtom(&inf_at_data->at);
1244 : : if (inf_at_data->pStereoFlags)
1245 : : {
1246 : : inchi_free(inf_at_data->pStereoFlags);
1247 : : }
1248 : : memset(inf_at_data, 0, sizeof(*inf_at_data)); /* djb-rwth: memset_s C11/Annex K variant? */
1249 : :
1250 : : return;
1251 : : }
1252 : :
1253 : : /****************************************************************************/
1254 : : int CreateInfoAtomData(INF_ATOM_DATA *inf_at_data,
1255 : : int num_atoms,
1256 : : int num_components)
1257 : : {
1258 : : FreeInfoAtomData(inf_at_data);
1259 : :
1260 : : memset(inf_at_data, 0, sizeof(*inf_at_data)); /* djb-rwth: memset_s C11/Annex K variant? */
1261 : :
1262 : : if ((inf_at_data->at = CreateInfAtom(num_atoms)) &&
1263 : : (num_components <= 1 ||
1264 : : (inf_at_data->pStereoFlags = (AT_NUMB *)inchi_calloc((long long)num_components + 1, sizeof(inf_at_data->pStereoFlags[0]))) /* djb-rwth: cast operator added */
1265 : : ))
1266 : : {
1267 : : inf_at_data->num_at = num_atoms;
1268 : : inf_at_data->num_components = num_components;
1269 : : return 1;
1270 : : }
1271 : :
1272 : : FreeInfoAtomData(inf_at_data);
1273 : :
1274 : : return 0;
1275 : : }
1276 : :
1277 : : /****************************************************************************/
1278 : : int AllocateInfoAtomData(INF_ATOM_DATA *inf_at_data,
1279 : : int num_atoms,
1280 : : int num_components)
1281 : : {
1282 : : if ((inf_at_data->at = CreateInfAtom(num_atoms))) /* djb-rwth: addressing LLVM warning */
1283 : : {
1284 : : if (num_components > 1 &&
1285 : : !(inf_at_data->pStereoFlags = (AT_NUMB *)inchi_calloc((long long)num_components + 1, sizeof(inf_at_data->pStereoFlags[0])))) /* djb-rwth: cast operator added */
1286 : : {
1287 : : FreeInfAtom(&inf_at_data->at);
1288 : : return 0;
1289 : : }
1290 : : return 1;
1291 : : }
1292 : :
1293 : : return 0;
1294 : : }
1295 : :
1296 : : /****************************************************************************/
1297 : : int DuplicateInfoAtomData(INF_ATOM_DATA *inf_at_data_to,
1298 : : const INF_ATOM_DATA *inf_at_data_from)
1299 : : {
1300 : : *inf_at_data_to = *inf_at_data_from;
1301 : :
1302 : : if (AllocateInfoAtomData(inf_at_data_to, inf_at_data_from->num_at, inf_at_data_from->num_components))
1303 : : {
1304 : : memcpy(inf_at_data_to->at, inf_at_data_from->at,
1305 : : inf_at_data_from->num_at * sizeof(inf_at_data_to->at[0]));
1306 : : if (inf_at_data_to->pStereoFlags && inf_at_data_from->pStereoFlags)
1307 : : {
1308 : : memcpy(inf_at_data_to->pStereoFlags, inf_at_data_from->pStereoFlags,
1309 : : ((long long)inf_at_data_from->num_components + 1) * sizeof(inf_at_data_to->pStereoFlags[0])); /* djb-rwth: cast operator added */
1310 : : }
1311 : : return 1;
1312 : : }
1313 : :
1314 : : return 0;
1315 : : }
1316 : : #endif /* COMPILE_ANSI_ONLY */
1317 : :
1318 : : /****************************************************************************/
1319 : 487 : void FreeOrigAtData(ORIG_ATOM_DATA *orig_at_data)
1320 : : {
1321 [ - + ]: 487 : if (!orig_at_data)
1322 : : {
1323 : 0 : return;
1324 : : }
1325 : :
1326 : 487 : FreeInpAtom(&orig_at_data->at);
1327 : :
1328 [ + + ]: 487 : if (orig_at_data->nCurAtLen)
1329 : : {
1330 [ + - ]: 123 : inchi_free(orig_at_data->nCurAtLen);
1331 : : }
1332 : :
1333 [ + + ]: 487 : if (orig_at_data->nOldCompNumber)
1334 : : {
1335 [ + - ]: 123 : inchi_free(orig_at_data->nOldCompNumber);
1336 : : }
1337 : :
1338 [ - + ]: 487 : if (orig_at_data->szCoord)
1339 : : {
1340 [ # # ]: 0 : inchi_free(orig_at_data->szCoord);
1341 : : }
1342 : :
1343 [ - + ]: 487 : if (orig_at_data->nEquLabels)
1344 : : {
1345 [ # # ]: 0 : inchi_free(orig_at_data->nEquLabels);
1346 : : }
1347 : :
1348 [ - + ]: 487 : if (orig_at_data->nSortedOrder)
1349 : : {
1350 [ # # ]: 0 : inchi_free(orig_at_data->nSortedOrder);
1351 : : }
1352 : :
1353 : : /* v 1.05 */
1354 : 487 : FreeExtOrigAtData(orig_at_data->polymer, orig_at_data->v3000);
1355 : :
1356 : 487 : memset(orig_at_data, 0, sizeof(*orig_at_data)); /* djb-rwth: memset_s C11/Annex K variant? */
1357 : :
1358 : 487 : return;
1359 : : }
1360 : :
1361 : : /****************************************************************************
1362 : : Free v. 1.05 extensions stuff
1363 : : ****************************************************************************/
1364 : 491 : void FreeExtOrigAtData(OAD_Polymer *pd, OAD_V3000 *v3k)
1365 : : {
1366 : : int k;
1367 : :
1368 : 491 : OAD_Polymer_Free(pd);
1369 : 491 : pd = NULL;
1370 : :
1371 [ + + ]: 491 : if (v3k)
1372 : : {
1373 [ + - ]: 114 : if (v3k->atom_index_orig)
1374 : : {
1375 [ + - ]: 114 : inchi_free(v3k->atom_index_orig);
1376 : 114 : v3k->atom_index_orig = NULL;
1377 : : }
1378 [ + - ]: 114 : if (v3k->atom_index_fin)
1379 : : {
1380 [ + - ]: 114 : inchi_free(v3k->atom_index_fin);
1381 : 114 : v3k->atom_index_fin = NULL;
1382 : : }
1383 [ + + + - ]: 114 : if (v3k->n_haptic_bonds && v3k->lists_haptic_bonds)
1384 : : {
1385 [ + + ]: 10 : for (k = 0; k < v3k->n_haptic_bonds; k++)
1386 [ + - ]: 6 : if (v3k->lists_haptic_bonds[k])
1387 : : {
1388 [ + - ]: 6 : inchi_free(v3k->lists_haptic_bonds[k]);
1389 : 6 : v3k->lists_haptic_bonds[k] = NULL;
1390 : : }
1391 [ + - ]: 4 : inchi_free(v3k->lists_haptic_bonds);
1392 : 4 : v3k->lists_haptic_bonds = NULL;
1393 : : }
1394 [ + + + - ]: 114 : if (v3k->n_steabs && v3k->lists_steabs)
1395 : : {
1396 [ + + ]: 92 : for (k = 0; k < v3k->n_steabs; k++)
1397 [ + - ]: 46 : if (v3k->lists_steabs[k])
1398 : : {
1399 [ + - ]: 46 : inchi_free(v3k->lists_steabs[k]);
1400 : 46 : v3k->lists_steabs[k] = NULL;
1401 : : }
1402 [ + - ]: 46 : inchi_free(v3k->lists_steabs);
1403 : 46 : v3k->lists_steabs = NULL;
1404 : : }
1405 [ + + + - ]: 114 : if (v3k->n_sterel && v3k->lists_sterel)
1406 : : {
1407 [ + + ]: 96 : for (k = 0; k < v3k->n_sterel; k++)
1408 [ + - ]: 62 : if (v3k->lists_sterel[k])
1409 : : {
1410 [ + - ]: 62 : inchi_free(v3k->lists_sterel[k]);
1411 : 62 : v3k->lists_sterel[k] = NULL;
1412 : : }
1413 [ + - ]: 34 : inchi_free(v3k->lists_sterel);
1414 : 34 : v3k->lists_sterel = NULL;
1415 : : }
1416 [ + + + - ]: 114 : if (v3k->n_sterac && v3k->lists_sterac)
1417 : : {
1418 [ + + ]: 146 : for (k = 0; k < v3k->n_sterac; k++)
1419 [ + - ]: 94 : if (v3k->lists_sterac[k])
1420 : : {
1421 [ + - ]: 94 : inchi_free(v3k->lists_sterac[k]);
1422 : 94 : v3k->lists_sterac[k] = NULL;
1423 : : }
1424 [ + - ]: 52 : inchi_free(v3k->lists_sterac);
1425 : 52 : v3k->lists_sterac = NULL;
1426 : : }
1427 : 114 : memset(v3k, 0, sizeof(*v3k)); /* djb-rwth: memset_s C11/Annex K variant? */
1428 [ + - ]: 114 : inchi_free(v3k);
1429 : : }
1430 : :
1431 : 491 : return;
1432 : : }
1433 : :
1434 : : /****************************************************************************/
1435 : :
1436 : 121 : int SetExtOrigAtDataByMolfileExtInput(MOL_FMT_DATA *mfdata,
1437 : : OAD_Polymer **ppPolymer,
1438 : : OAD_V3000 **ppV3000,
1439 : : char *pStrErr)
1440 : : {
1441 : 121 : int k, m, err = 0;
1442 : 121 : OAD_V3000 *pv = NULL;
1443 : 121 : int nsgroups = mfdata->ctab.sgroups.used;
1444 : :
1445 : : /* djb-rwth: addressing coverity ID #499476 -- TREAT_ERR properly used in all cases */
1446 : : /* Polymers */
1447 [ + + ]: 121 : if (nsgroups > 0)
1448 : : {
1449 : : /* Prepare OAD_Polymer container */
1450 : 1 : *ppPolymer = (OAD_Polymer *)inchi_calloc(1, sizeof(OAD_Polymer));
1451 [ - + ]: 1 : if (!(*ppPolymer))
1452 : : {
1453 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1454 : 0 : goto exit_function;
1455 : : }
1456 : :
1457 : : /* Convert Molfile's Sgroup's to OAD_PolymerUnit's */
1458 : 1 : (*ppPolymer)->units = (OAD_PolymerUnit **)inchi_calloc(nsgroups, sizeof((*ppPolymer)->units[0]));
1459 [ - + ]: 1 : if (!(*ppPolymer)->units)
1460 : : {
1461 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1462 : 0 : goto exit_function;
1463 : : }
1464 : 1 : memset((*ppPolymer)->units, 0, sizeof(*(*ppPolymer)->units)); /* djb-rwth: memset_s C11/Annex K variant? */
1465 : :
1466 : 1 : (*ppPolymer)->n = nsgroups;
1467 : 1 : (*ppPolymer)->is_in_reconn = 0;
1468 : 1 : (*ppPolymer)->pzz = NULL;
1469 : 1 : (*ppPolymer)->edit_repeats = 0;
1470 : 1 : (*ppPolymer)->really_do_frame_shift = 0;
1471 : 1 : (*ppPolymer)->frame_shift_scheme = FSS_STARS_CYCLED;
1472 : 1 : (*ppPolymer)->treat = POLYMERS_MODERN;
1473 : :
1474 [ + + ]: 2 : for (k = 0; k < nsgroups; k++)
1475 : : {
1476 : 1 : int q = 0;
1477 : 1 : MOL_FMT_SGROUP *groupk = mfdata->ctab.sgroups.group[k];
1478 : :
1479 : 1 : OAD_PolymerUnit *unitk = (*ppPolymer)->units[k] = (OAD_PolymerUnit *)inchi_calloc(1, sizeof(OAD_PolymerUnit));
1480 : :
1481 [ - + ]: 1 : if (!unitk)
1482 : : {
1483 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1484 : 0 : goto exit_function;
1485 : : }
1486 : :
1487 : 1 : memset(unitk, 0, sizeof(*unitk)); /* djb-rwth: memset_s C11/Annex K variant? */
1488 : 1 : unitk->id = groupk->id;
1489 : 1 : unitk->type = groupk->type;
1490 : 1 : unitk->subtype = groupk->subtype;
1491 : 1 : unitk->conn = groupk->conn;
1492 : 1 : unitk->label = groupk->label;
1493 : :
1494 [ + + ]: 5 : for (q = 0; q < 4; q++)
1495 : : {
1496 : 4 : unitk->xbr1[q] = groupk->xbr1[q];
1497 : 4 : unitk->xbr2[q] = groupk->xbr2[q];
1498 : : }
1499 : 1 : strcpy(unitk->smt, groupk->smt);
1500 : 1 : unitk->na = groupk->alist.used;
1501 : 1 : unitk->alist = (int *)inchi_calloc(unitk->na, sizeof(int));
1502 [ - + ]: 1 : if (!unitk->alist)
1503 : : {
1504 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1505 : 0 : goto exit_function;
1506 : : }
1507 [ + + ]: 4 : for (m = 0; m < unitk->na; m++)
1508 : : {
1509 : 3 : unitk->alist[m] = groupk->alist.item[m];
1510 : : }
1511 : 1 : unitk->nb = groupk->blist.used;
1512 [ + - ]: 1 : if (unitk->nb > 0)
1513 : : {
1514 : 1 : unitk->blist = (int *)inchi_calloc(2 * (long long)unitk->nb, sizeof(int)); /* djb-rwth: cast operator added */
1515 [ - + ]: 1 : if (!unitk->blist)
1516 : : {
1517 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1518 : 0 : goto exit_function;
1519 : : }
1520 [ + + ]: 3 : for (m = 0; m < groupk->blist.used; m++)
1521 : : {
1522 : : int ib, ia1, ia2;
1523 : 2 : ib = groupk->blist.item[m];
1524 [ + - - + ]: 2 : if (ib < 1 || ib > mfdata->ctab.n_bonds)
1525 : : {
1526 [ # # ]: 0 : TREAT_ERR(err, 9004, "Polymer unit in Molfile refers to invalid bond");
1527 : 0 : goto exit_function;
1528 : : }
1529 : 2 : ia1 = mfdata->ctab.bonds[ib - 1].atnum1;
1530 : 2 : ia2 = mfdata->ctab.bonds[ib - 1].atnum2;
1531 : 2 : unitk->blist[2 * m] = ia1;
1532 : 2 : unitk->blist[2 * m + 1] = ia2;
1533 : :
1534 : : /**
1535 : : *@nnuk: GHI#252 addressed and redundant logic removed
1536 : : */
1537 : : }
1538 : : }
1539 : : else
1540 : : {
1541 : 0 : unitk->blist = NULL;
1542 : : }
1543 : : }
1544 : : }
1545 : :
1546 : : /* V3000 Extensions */
1547 [ + + ]: 121 : if (mfdata->ctab.v3000)
1548 : : {
1549 : : int nn;
1550 : 57 : MOL_FMT_v3000 *mpv = mfdata->ctab.v3000;
1551 : :
1552 : 57 : *ppV3000 = (OAD_V3000 *)inchi_calloc(1, sizeof(OAD_V3000));
1553 : 57 : pv = *ppV3000;
1554 [ - + ]: 57 : if (!pv)
1555 : : {
1556 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1557 : 0 : goto exit_function;
1558 : : }
1559 : 57 : memset(pv, 0, sizeof(*pv)); /* djb-rwth: memset_s C11/Annex K variant? */
1560 : :
1561 : 57 : pv->n_collections = mpv->n_collections;
1562 : 57 : pv->n_haptic_bonds = mpv->n_haptic_bonds;
1563 : 57 : pv->n_non_haptic_bonds = mpv->n_non_haptic_bonds;
1564 : 57 : pv->n_sgroups = mpv->n_sgroups;
1565 : 57 : pv->n_non_star_atoms = mpv->n_non_star_atoms;
1566 : 57 : pv->n_star_atoms = mpv->n_star_atoms;
1567 : 57 : pv->n_steabs = mpv->n_steabs;
1568 : 57 : pv->n_sterac = mpv->n_sterac;
1569 : 57 : pv->n_sterel = mpv->n_sterel;
1570 : 57 : pv->n_3d_constraints = mpv->n_3d_constraints;
1571 : :
1572 [ + - ]: 57 : if (mpv->atom_index_orig)
1573 : : {
1574 : 57 : pv->atom_index_orig = (int *)inchi_calloc(mfdata->ctab.n_atoms, sizeof(int));
1575 [ - + ]: 57 : if (NULL == pv->atom_index_orig)
1576 : : {
1577 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1578 : 0 : goto exit_function;
1579 : : }
1580 : 57 : memcpy(pv->atom_index_orig, mpv->atom_index_orig, mfdata->ctab.n_atoms);
1581 : : }
1582 [ + - ]: 57 : if (mpv->atom_index_fin)
1583 : : {
1584 : 57 : pv->atom_index_fin = (int *)inchi_calloc(mfdata->ctab.n_atoms, sizeof(int));
1585 [ - + ]: 57 : if (NULL == pv->atom_index_fin)
1586 : : {
1587 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1588 : 0 : goto exit_function;
1589 : : }
1590 : 57 : memcpy(pv->atom_index_fin, mpv->atom_index_fin, mfdata->ctab.n_atoms);
1591 : : }
1592 [ + + + - ]: 57 : if (mpv->n_haptic_bonds && mpv->haptic_bonds)
1593 : : {
1594 : 2 : pv->lists_haptic_bonds = (int **)inchi_calloc(mpv->n_haptic_bonds, sizeof(int *));
1595 [ - + ]: 2 : if (NULL == pv->lists_haptic_bonds)
1596 : : {
1597 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1598 : 0 : goto exit_function;
1599 : : }
1600 [ + + ]: 5 : for (m = 0; m < mpv->n_haptic_bonds; m++)
1601 : : {
1602 : 3 : int *lst = NULL;
1603 : 3 : int *mol_lst = mpv->haptic_bonds->lists[m];
1604 : 3 : nn = mol_lst[2] + 3;
1605 : 3 : lst = pv->lists_haptic_bonds[m] = (int *)inchi_calloc(nn, sizeof(int));
1606 [ - + ]: 3 : if (NULL == lst)
1607 : : {
1608 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1609 : 0 : goto exit_function;
1610 : : }
1611 [ + + ]: 24 : for (k = 0; k < nn; k++)
1612 : : {
1613 : 21 : lst[k] = mol_lst[k];
1614 : : }
1615 : : }
1616 : : }
1617 [ + + + - ]: 57 : if (mpv->n_steabs && mpv->steabs)
1618 : : {
1619 : 23 : pv->lists_steabs = (int **)inchi_calloc(mpv->n_steabs, sizeof(int *));
1620 [ - + ]: 23 : if (NULL == pv->lists_steabs)
1621 : : {
1622 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1623 : 0 : goto exit_function;
1624 : : }
1625 [ + + ]: 46 : for (m = 0; m < mpv->n_steabs; m++)
1626 : : {
1627 : 23 : int *lst = NULL;
1628 : 23 : int *mol_lst = mpv->steabs->lists[m];
1629 : 23 : nn = mol_lst[1] + 2;
1630 : 23 : lst = pv->lists_steabs[m] = (int *)inchi_calloc(nn, sizeof(int));
1631 [ - + ]: 23 : if (NULL == lst)
1632 : : {
1633 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1634 : 0 : goto exit_function;
1635 : : }
1636 [ + + ]: 119 : for (k = 0; k < nn; k++)
1637 : : {
1638 : 96 : lst[k] = mol_lst[k];
1639 : : }
1640 : : }
1641 : : }
1642 [ + + + - ]: 57 : if (mpv->n_sterac && mpv->sterac)
1643 : : {
1644 : 26 : pv->lists_sterac = (int **)inchi_calloc(mpv->n_sterac, sizeof(int *));
1645 [ - + ]: 26 : if (NULL == pv->lists_sterac)
1646 : : {
1647 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1648 : 0 : goto exit_function;
1649 : : }
1650 [ + + ]: 73 : for (m = 0; m < mpv->n_sterac; m++)
1651 : : {
1652 : 47 : int *lst = NULL;
1653 : 47 : int *mol_lst = mpv->sterac->lists[m];
1654 : 47 : nn = mol_lst[1] + 2;
1655 : 47 : lst = pv->lists_sterac[m] = (int *)inchi_calloc(nn, sizeof(int));
1656 [ - + ]: 47 : if (NULL == lst)
1657 : : {
1658 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1659 : 0 : goto exit_function;
1660 : : }
1661 [ + + ]: 211 : for (k = 0; k < nn; k++)
1662 : : {
1663 : 164 : lst[k] = mol_lst[k];
1664 : : }
1665 : : }
1666 : : }
1667 [ + + - + ]: 57 : if (mpv->n_sterel && mpv->sterel)
1668 : : {
1669 : 17 : pv->lists_sterel = (int **)inchi_calloc(mpv->n_sterel, sizeof(int *));
1670 [ - + ]: 17 : if (NULL == pv->lists_sterel)
1671 : : {
1672 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1673 : 0 : goto exit_function;
1674 : : }
1675 [ + + ]: 48 : for (m = 0; m < mpv->n_sterel; m++)
1676 : : {
1677 : 31 : int *lst = NULL;
1678 : 31 : int *mol_lst = mpv->sterel->lists[m];
1679 : 31 : nn = mol_lst[1] + 2;
1680 : 31 : lst = pv->lists_sterel[m] = (int *)inchi_calloc(nn, sizeof(int));
1681 [ - + ]: 31 : if (NULL == lst)
1682 : : {
1683 [ # # ]: 0 : TREAT_ERR(err, 9001, "Out of RAM");
1684 : 0 : goto exit_function;
1685 : : }
1686 [ + + ]: 144 : for (k = 0; k < nn; k++)
1687 : : {
1688 : 113 : lst[k] = mol_lst[k];
1689 : : }
1690 : : }
1691 : : }
1692 : : }
1693 : :
1694 : 121 : exit_function:
1695 [ - + ]: 121 : if (err)
1696 : : {
1697 : 0 : FreeExtOrigAtData((*ppPolymer), pv);
1698 : 0 : *ppPolymer = NULL;
1699 : : }
1700 : :
1701 : 121 : return err;
1702 : : }
|